From 3da47e299f55a0c015fddc6c3df62a5cbcf139f0 Mon Sep 17 00:00:00 2001 From: ZeroIntensity Date: Sat, 17 Sep 2022 12:48:16 -0400 Subject: [PATCH] patch null pointers --- pyproject.toml | 2 +- src/pointers/__init__.py | 2 +- src/pointers/_utils.py | 64 +++++++++++++++++----------------- src/pointers/base_pointers.py | 14 +++++--- src/pointers/object_pointer.py | 5 +-- tests/test_pointer.py | 8 +++++ 6 files changed, 54 insertions(+), 41 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bd77550..e623c23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,4 +23,4 @@ classifiers = [ dependencies = [ "typing_extensions", ] -version = "2.1.0" +version = "2.1.1" diff --git a/src/pointers/__init__.py b/src/pointers/__init__.py index 26730e5..01b4a5b 100644 --- a/src/pointers/__init__.py +++ b/src/pointers/__init__.py @@ -27,4 +27,4 @@ from .std_structs import DivT, Lconv, LDivT, Tm from .structure import Struct -__version__ = "2.1.0" +__version__ = "2.1.1" diff --git a/src/pointers/_utils.py b/src/pointers/_utils.py index 977cd4f..84e0693 100644 --- a/src/pointers/_utils.py +++ b/src/pointers/_utils.py @@ -15,6 +15,36 @@ "make_py", ) +_C_TYPES: Dict[type, Type["ctypes._CData"]] = { + bytes: ctypes.c_char_p, + str: ctypes.c_wchar_p, + int: ctypes.c_int, + float: ctypes.c_float, + bool: ctypes.c_bool, +} + +_PY_TYPES: Dict[Type["ctypes._CData"], type] = { + ctypes.c_bool: bool, + ctypes.c_char: bytes, + ctypes.c_wchar: str, + ctypes.c_ubyte: int, + ctypes.c_short: int, + ctypes.c_int: int, + ctypes.c_uint: int, + ctypes.c_long: int, + ctypes.c_ulong: int, + ctypes.c_longlong: int, + ctypes.c_ulonglong: int, + ctypes.c_size_t: int, + ctypes.c_ssize_t: int, + ctypes.c_float: float, + ctypes.c_double: float, + ctypes.c_longdouble: float, + ctypes.c_char_p: bytes, + ctypes.c_wchar_p: str, + ctypes.c_void_p: int, +} + def move_to_mem( ptr: "ctypes._PointerLike", @@ -52,15 +82,7 @@ def map_type(data: Any) -> "ctypes._CData": def get_mapped(typ: Any): """Get the C mapped value of the given type.""" - types: Dict[type, Type["ctypes._CData"]] = { - bytes: ctypes.c_char_p, - str: ctypes.c_wchar_p, - int: ctypes.c_int, - float: ctypes.c_float, - bool: ctypes.c_bool, - } - - res = types.get(typ) + res = _C_TYPES.get(typ) if not res: raise ValueError(f'"{typ.__name__}" is not mappable to a c type') @@ -86,30 +108,8 @@ def get_py( if data.__name__.startswith("LP_"): return BaseCPointer - types: Dict[Type["ctypes._CData"], type] = { - ctypes.c_bool: bool, - ctypes.c_char: bytes, - ctypes.c_wchar: str, - ctypes.c_ubyte: int, - ctypes.c_short: int, - ctypes.c_int: int, - ctypes.c_uint: int, - ctypes.c_long: int, - ctypes.c_ulong: int, - ctypes.c_longlong: int, - ctypes.c_ulonglong: int, - ctypes.c_size_t: int, - ctypes.c_ssize_t: int, - ctypes.c_float: float, - ctypes.c_double: float, - ctypes.c_longdouble: float, - ctypes.c_char_p: bytes, - ctypes.c_wchar_p: str, - ctypes.c_void_p: int, - } - try: - return types[data] + return _PY_TYPES[data] except KeyError as e: raise ValueError( f"{data} is not a valid ctypes type", diff --git a/src/pointers/base_pointers.py b/src/pointers/base_pointers.py index d996d11..4ac874f 100644 --- a/src/pointers/base_pointers.py +++ b/src/pointers/base_pointers.py @@ -246,12 +246,11 @@ def __init__( """ # noqa self._address: Optional[int] = address self._type: Type[T] = typ - obj = ~self if increment_ref and address: - add_ref(obj) + add_ref(~self) - self._origin_size = sys.getsizeof(obj) + self._origin_size = sys.getsizeof(~self if address else None) @property def type(self): @@ -285,12 +284,17 @@ def assign( "can only point to object pointer", ) - if new.type is not self.type: + if (new.type is not self.type) and self.address: raise TypeError( f"object at new address must be the same type (pointer looks at {self.type.__name__}, target is {new.type.__name__})", # noqa ) - remove_ref(~self) + if not self.address: + self._type = new.type + + with suppress(NullPointerError): + remove_ref(~self) + self._address = new.address add_ref(~self) diff --git a/src/pointers/object_pointer.py b/src/pointers/object_pointer.py index 6323013..ceae6c3 100644 --- a/src/pointers/object_pointer.py +++ b/src/pointers/object_pointer.py @@ -63,10 +63,11 @@ def move( @classmethod def make_from(cls, obj: Nullable[T]) -> "Pointer[T]": + is_null = obj is NULL return Pointer( - id(obj) if obj is not NULL else None, + id(obj) if not is_null else None, type(obj), # type: ignore - True, + not is_null, ) diff --git a/tests/test_pointer.py b/tests/test_pointer.py index 683d3b3..6054bfe 100644 --- a/tests/test_pointer.py +++ b/tests/test_pointer.py @@ -81,6 +81,14 @@ def _(): with raises(NullPointerError): print(~to_ptr(NULL)) + ptr2 = to_ptr(NULL) + ptr2 >>= 1 + + with raises(TypeError): + ptr2 >>= "" + + ptr2 >>= NULL + @test("operator magic") def _():