Skip to content

Commit 5de18dd

Browse files
committed
refactor(c_types): Enable setting the numeric C type from CAny
Enable setting the C type for numeric type wrappers from the `CAny` adapter class. This allows functions that use `CAny`, instead of the type-specific `C*` classes, to specify the C types that will be used to represent numeric Python types. PR: #29 Signed-off-by: Kostis Papazafeiropoulos <papazof@gmail.com> Reviewed-by: Anastassios Nanos <ananos@nubificus.co.uk> Approved-by: Anastassios Nanos <ananos@nubificus.co.uk>
1 parent f982cd4 commit 5de18dd

7 files changed

Lines changed: 58 additions & 17 deletions

File tree

vaccel/_c_types/types.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,18 @@ class CAny(CType):
7575
_wrapped (CType): The wrapped C object.
7676
"""
7777

78-
def __init__(self, obj: Any):
78+
def __init__(self, obj: Any, *, precision: str | None = None):
7979
"""Initializes a new `CAny` object.
8080
8181
Args:
8282
obj: The python object to be wrapped as a C type.
83+
precision: The C type that will be used to represent the python
84+
object type, if the type is numeric.
8385
"""
84-
self._wrapped = to_ctype(obj)
86+
if precision is not None:
87+
self._wrapped = to_ctype(obj, precision=precision)
88+
else:
89+
self._wrapped = to_ctype(obj)
8590

8691
def _init_c_obj(self):
8792
msg = "CAny is a generic adapter, not meant for initialization."
@@ -111,11 +116,13 @@ def __repr__(self):
111116

112117

113118
@singledispatch
114-
def to_ctype(value: Any):
119+
def to_ctype(value: Any, *, precision: str | None = None):
120+
_ = precision
115121
msg = f"No CType wrapper registered for {type(value)}"
116122
raise TypeError(msg)
117123

118124

119125
@to_ctype.register
120-
def _(value: CType):
126+
def _(value: CType, *, precision: str | None = None):
127+
_ = precision
121128
return value

vaccel/_c_types/wrappers/cbytes.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def __eq__(self, other: "CBytes | bytes | bytearray | memoryview"):
8585
return self._data == other
8686
return NotImplemented
8787

88+
__hash__ = None
89+
8890
def __bytes__(self):
8991
return bytes(self._data)
9092

@@ -102,10 +104,12 @@ def __repr__(self):
102104

103105

104106
@to_ctype.register
105-
def _(value: bytes):
107+
def _(value: bytes, *, precision: str | None = None):
108+
_ = precision
106109
return CBytes(value)
107110

108111

109112
@to_ctype.register
110-
def _(value: bytearray):
113+
def _(value: bytearray, *, precision: str | None = None):
114+
_ = precision
111115
return CBytes(value)

vaccel/_c_types/wrappers/cfloat.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
"""C type interface for `float` objects."""
44

5+
from typing import Final
6+
57
from vaccel._c_types.types import CType, to_ctype
68
from vaccel._libvaccel import ffi
79
from vaccel.error import NullPointerError
@@ -22,15 +24,18 @@ class CFloat(CType):
2224
_ctype_str (str): The actual string that is used for the C type.
2325
"""
2426

27+
_SUPPORTED_PRECISIONS: Final[set[str]] = {"float", "double"}
28+
2529
def __init__(self, value: float, precision: str = "float"):
2630
"""Initializes a new `CFloat` object.
2731
2832
Args:
2933
value: The float to be wrapped.
3034
precision: The C type that will be used to represent the float.
3135
"""
32-
if precision not in ("float", "double"):
33-
msg = "precision must be 'float' or 'double'"
36+
if precision not in self._SUPPORTED_PRECISIONS:
37+
supported = ", ".join(str(d) for d in self._SUPPORTED_PRECISIONS)
38+
msg = f"Unsupported precision: {precision}. Supported: {supported}"
3439
raise ValueError(msg)
3540
self._value = float(value)
3641
self._precision = precision
@@ -158,5 +163,5 @@ def __repr__(self):
158163

159164

160165
@to_ctype.register
161-
def _(value: float):
162-
return CFloat(value)
166+
def _(value: float, *, precision: str | None = "float"):
167+
return CFloat(value, precision)

vaccel/_c_types/wrappers/cint.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
"""C type interface for `int` objects."""
44

5+
from typing import Final
6+
57
from vaccel._c_types.types import CType, to_ctype
68
from vaccel._libvaccel import ffi
79
from vaccel.error import NullPointerError
@@ -22,16 +24,33 @@ class CInt(CType):
2224
_ctype_str (str): The actual string that is used for the C type.
2325
"""
2426

27+
_SUPPORTED_PRECISIONS: Final[set[str]] = {
28+
"int",
29+
"int8_t",
30+
"int16_t",
31+
"int32_t",
32+
"int64_t",
33+
"unsigned",
34+
"unsigned int",
35+
"uint8_t",
36+
"uint16_t",
37+
"uint32_t",
38+
"uint64_t",
39+
}
40+
2541
def __init__(self, value: int, precision: str = "int"):
2642
"""Initializes a new `CInt` object.
2743
2844
Args:
2945
value: The int to be wrapped.
3046
precision: The C type that will be used to represent the int.
3147
"""
48+
if precision not in self._SUPPORTED_PRECISIONS:
49+
supported = ", ".join(str(d) for d in self._SUPPORTED_PRECISIONS)
50+
msg = f"Unsupported precision: {precision}. Supported: {supported}"
51+
raise ValueError(msg)
3252
self._value = int(value)
3353
self._precision = precision
34-
# TODO: validate user input # noqa: FIX002
3554
self._ctype_str = self._precision
3655
super().__init__()
3756

@@ -156,5 +175,5 @@ def __repr__(self):
156175

157176

158177
@to_ctype.register
159-
def _(value: int):
160-
return CInt(value)
178+
def _(value: int, *, precision: str | None = "int"):
179+
return CInt(value, precision)

vaccel/_c_types/wrappers/clist.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,5 +218,6 @@ def __repr__(self):
218218

219219
@to_ctype.register(tuple)
220220
@to_ctype.register(list)
221-
def _(value: list):
221+
def _(value: list, *, precision: str | None = None):
222+
_ = precision
222223
return CList(value)

vaccel/_c_types/wrappers/cnumpyarray.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,5 +152,6 @@ def is_contiguous(self) -> bool:
152152
if HAS_NUMPY:
153153

154154
@to_ctype.register
155-
def _(value: np.ndarray):
155+
def _(value: np.ndarray, *, precision: str | None = None):
156+
_ = precision
156157
return CNumpyArray(value)

vaccel/_c_types/wrappers/cstr.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ def __eq__(self, other: "CStr | str"):
9090
return self._value == other
9191
return NotImplemented
9292

93+
__hash__ = None
94+
9395
def __repr__(self):
9496
try:
9597
c_ptr = (
@@ -104,10 +106,12 @@ def __repr__(self):
104106

105107

106108
@to_ctype.register
107-
def _(value: str):
109+
def _(value: str, *, precision: str | None = None):
110+
_ = precision
108111
return CStr(value)
109112

110113

111114
@to_ctype.register
112-
def _(value: Path):
115+
def _(value: Path, *, precision: str | None = None):
116+
_ = precision
113117
return CStr(value)

0 commit comments

Comments
 (0)