Skip to content

Commit 7d75e6d

Browse files
committed
update tests and some patches
1 parent 68103fc commit 7d75e6d

File tree

13 files changed

+221
-68
lines changed

13 files changed

+221
-68
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ classifiers = [
2323
dependencies = [
2424
"typing_extensions",
2525
]
26-
version="2.0.0"
26+
version="2.0.0-alpha"
2727

2828
[project.urls]
2929
Documentation = "https://pointers.zintensity.dev"

src/pointers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
StructPointer, TypedCPointer, VoidPointer, array, cast, to_c_ptr,
44
to_struct_ptr
55
)
6+
from .c_utils import force_set_attr
67
from .calloc import AllocatedArrayPointer, calloc
78
from .custom_binding import binding, binds
89
from .decay import decay
@@ -11,8 +12,8 @@
1112
InvalidBindingParameter, InvalidSizeError, IsFrozenError,
1213
IsMallocPointerError, NotEnoughChunks
1314
)
15+
from .magic import _
1416
from .malloc import AllocatedPointer, free, malloc, realloc
1517
from .object_pointer import Pointer, to_ptr
1618
from .struct import Struct
17-
from .utils import _, force_set_attr
1819
from .version import __version__

src/pointers/_pointer.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010

1111
from _pointers import add_ref, remove_ref
1212

13-
from .c_utils import move_to_mem
13+
from .c_utils import deref, force_set_attr, move_to_mem
1414
from .exceptions import DereferenceError, FreedMemoryError, NullPointerError
15-
from .utils import force_set_attr
1615

1716
__all__ = (
1817
"BasePointer",
@@ -231,13 +230,14 @@ def address(self) -> Optional[int]:
231230
return self._address
232231

233232
def dereference(self) -> T:
234-
return ctypes.cast(self.ensure(), ctypes.py_object).value
233+
return deref(self.ensure())
235234

236235
def __irshift__(
237236
self,
238237
value: Optional[Union["BaseObjectPointer[T]", T]],
239-
) -> None:
238+
):
240239
self.assign(value)
240+
return self
241241

242242
@classmethod
243243
@abstractmethod
@@ -321,6 +321,10 @@ class BaseAllocatedPointer(BasePointer[T], Sized, ABC):
321321
def address(self) -> Optional[int]:
322322
...
323323

324+
@address.setter
325+
def address(self, value: int) -> None:
326+
...
327+
324328
@property
325329
def freed(self) -> bool:
326330
"""Whether the allocated memory has been freed."""
@@ -348,11 +352,6 @@ def move(
348352

349353
data_ptr = data if isinstance(data, BasePointer) else to_ptr(data)
350354

351-
if not isinstance(data_ptr, BaseAllocatedPointer):
352-
raise ValueError(
353-
f"{data_ptr} does not point to allocated memory",
354-
)
355-
356355
ptr, byte_stream = self._make_stream_and_ptr(
357356
sys.getsizeof(~data_ptr),
358357
data_ptr.ensure(),
@@ -372,7 +371,7 @@ def dereference(self):
372371
"cannot dereference allocated memory that has no value",
373372
)
374373

375-
return super().dereference()
374+
return deref(self.ensure())
376375

377376
@abstractmethod
378377
def __add__(self, amount: int) -> "BaseAllocatedPointer[Any]":

src/pointers/bindings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ def gmtime(timer: PointerLike) -> StructPointer[Tm]:
994994
return _base(dll.gmtime, timer)
995995

996996

997-
def signal(signum: int, func: Callable[[int, None], int]) -> None:
997+
def signal(signum: int, func: Callable[[int], Any]) -> None:
998998
return _base(dll.signal, signum, func)
999999

10001000

src/pointers/c_utils.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import ctypes
22
from typing import Any, Dict, Type, Union
33

4+
from _pointers import force_set_attr as _force_set_attr
5+
46
from .exceptions import InvalidSizeError
57

68
__all__ = (
@@ -22,15 +24,16 @@ def move_to_mem(
2224
target: str = "memory allocation",
2325
):
2426
"""Move data to a C pointer."""
25-
try:
26-
if not unsafe:
27-
ptr.contents[:] = stream
28-
else:
29-
ctypes.memmove(ptr, stream, len(stream))
30-
except ValueError as e:
27+
28+
slen = len(stream)
29+
plen = len(ptr.contents)
30+
31+
if slen > plen:
3132
raise InvalidSizeError(
32-
f"object is of size {len(stream)}, while {target} is {len(ptr.contents)}" # noqa
33-
) from e
33+
f"object is of size {slen}, while {target} is {plen}",
34+
)
35+
36+
ctypes.memmove(ptr, stream, slen)
3437

3538

3639
def attempt_decode(data: bytes) -> Union[str, bytes]:
@@ -78,10 +81,10 @@ def get_py(
7881
data: Type["ctypes._CData"],
7982
) -> Type[Any]:
8083
"""Map the specified C type to a Python type."""
81-
from ._pointer import BasePointer
84+
from ._pointer import BaseCPointer
8285

8386
if data.__name__.startswith("LP_"):
84-
return BasePointer
87+
return BaseCPointer
8588

8689
types: Dict[Type["ctypes._CData"], type] = {
8790
ctypes.c_bool: bool,
@@ -122,3 +125,19 @@ def make_py(data: "ctypes._CData"):
122125
res = attempt_decode(res)
123126

124127
return res
128+
129+
130+
def force_set_attr(typ: Type[Any], key: str, value: Any) -> None:
131+
"""Force setting an attribute on the target type."""
132+
133+
if not isinstance(typ, type):
134+
raise ValueError(
135+
f"{typ} does not derive from type (did you pass an instance and not a class)?", # noqa
136+
)
137+
138+
_force_set_attr(typ, key, value)
139+
140+
141+
def deref(address: int) -> Any:
142+
"""Get the value at the target address."""
143+
return ctypes.cast(address, ctypes.py_object).value

src/pointers/calloc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(
3333
if chunk_cache:
3434
self._chunk_cache[self.current_index] = self
3535

36-
@property
36+
@property # type: ignore
3737
def address(self) -> Optional[int]:
3838
return self._address
3939

src/pointers/magic.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import TYPE_CHECKING, TypeVar
2+
3+
if TYPE_CHECKING:
4+
from ._pointer import BasePointer
5+
from .object_pointer import Pointer
6+
7+
from .object_pointer import to_ptr
8+
9+
__all__ = ("_",)
10+
11+
T = TypeVar("T")
12+
13+
14+
class _PointerOperatorMagic:
15+
def __and__(self, obj: T) -> "Pointer[T]":
16+
return to_ptr(obj)
17+
18+
def __mul__(self, ptr: "BasePointer[T]") -> T:
19+
return ~ptr
20+
21+
22+
_ = _PointerOperatorMagic()

src/pointers/malloc.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ def size(self, value: int) -> None:
3737
def address(self) -> Optional[int]:
3838
return self._address
3939

40+
@address.setter
41+
def address(self, value: int) -> None:
42+
self._address = value
43+
4044
def __repr__(self) -> str:
4145
return f"<pointer to {self.size} bytes of memory at {str(self)}>"
4246

@@ -68,18 +72,24 @@ def malloc(size: int) -> AllocatedPointer[Any]:
6872
return AllocatedPointer(mem, size)
6973

7074

71-
def free(target: AllocatedPointer):
75+
def free(target: BaseAllocatedPointer):
7276
"""Free allocated memory."""
77+
if target.freed:
78+
raise ValueError(
79+
f"{target} has already been freed",
80+
)
81+
7382
ct_ptr = target.make_ct_pointer()
7483
c_free(ct_ptr)
7584
target.freed = True
7685

7786

7887
def realloc(target: AllocatedPointer, size: int) -> None:
7988
"""Resize a memory block created by malloc."""
80-
mem = c_realloc(target.address, size)
89+
addr = c_realloc(target.address, size)
8190

82-
if not mem:
91+
if not addr:
8392
raise AllocationError("failed to resize memory")
8493

8594
target.size = size
95+
target.address = addr

src/pointers/utils.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/pointers/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.5.0"
1+
__version__ = "2.0.0-alpha"

0 commit comments

Comments
 (0)