Skip to content

Commit

Permalink
Merge pull request #51 from ionite34/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
ionite34 committed Feb 2, 2023
2 parents 31b50f6 + ae6b3cb commit 807b70c
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 29 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
project = "einspect"
copyright = "2023, Ionite"
author = "Ionite"
release = "v0.5.7"
release = "v0.5.8"


# -- General configuration ---------------------------------------------------
Expand Down
35 changes: 18 additions & 17 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "einspect"
version = "0.5.7.post1"
version = "0.5.8"
packages = [{ include = "einspect", from = "src" }]
description = "Extended Inspect - view and modify memory structs of runtime objects."
authors = ["ionite34 <dev@ionite.io>"]
Expand Down
2 changes: 1 addition & 1 deletion src/einspect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@

__all__ = ("view", "unsafe", "impl", "orig", "ptr", "NULL")

__version__ = "0.5.7.post1"
__version__ = "0.5.8"

unsafe: ContextManager[None] = global_unsafe
25 changes: 16 additions & 9 deletions src/einspect/views/view_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def wrap_py_object(obj: _T | py_object[_T]) -> py_object[_T]:
class BaseView(ABC, Generic[_T, _KT, _VT], UnsafeContext):
"""Base class for all views."""

_struct_type: Type[PyObject]

def __init__(self, obj: _T, ref: bool = REF_DEFAULT) -> None:
super().__init__()
# Stores base info for repr and errors
Expand All @@ -64,6 +66,19 @@ def __init__(self, obj: _T, ref: bool = REF_DEFAULT) -> None:
except TypeError:
self._base_weakref = None

def __init_subclass__(cls, **kwargs: Any) -> None:
"""Add `_struct_type` to subclass using the `_pyobject` type hint."""
super().__init_subclass__(**kwargs)

struct_type = get_type_hints(cls)["_pyobject"]
# For unions, use first type
# There's no easy way to check this in <3.9 without types.UnionType
# So we just check if not a PyObject / generic alias
if not getattr(struct_type, "from_object", None):
struct_type = get_args(struct_type)[0]

cls._struct_type = struct_type


class View(BaseView[_T, _KT, _VT]):
"""
Expand All @@ -78,15 +93,7 @@ class View(BaseView[_T, _KT, _VT]):

def __init__(self, obj: _T, ref: bool = REF_DEFAULT) -> None:
super().__init__(obj, ref)

struct_type = get_type_hints(self.__class__)["_pyobject"]
# For unions, use first type
# There's no easy way to check this in <3.9 without types.UnionType
# So we just check if not a PyObject / generic alias
if not getattr(struct_type, "from_object", None):
struct_type = get_args(struct_type)[0]

self._pyobject = struct_type.from_object(obj)
self._pyobject = self._struct_type.from_object(obj)
self.__dropped = False
_ = self.mem_allocated # cache allocated property

Expand Down
18 changes: 18 additions & 0 deletions tests/views/test_view_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import gc
import sys
from functools import cached_property

import pytest
Expand Down Expand Up @@ -32,12 +33,29 @@ def check_ref(self, a, b):
return
assert a == b

def test_ref_count(self):
obj = self.get_obj()
v = self.view_type(obj, ref=False)
with v.unsafe():
v.ref_count += 0
assert v.ref_count

def test_type(self):
obj = self.get_obj()
v = self.view_type(obj)
assert isinstance(v, View)
assert isinstance(v._pyobject, structs.PyObject)
assert v.type == type(obj)
with v.unsafe():
v.type = type(obj)
assert isinstance(obj, self.obj_type)

def test_repr(self):
obj = self.get_obj()
v = self.view_type(obj)
text = repr(v)
assert type(v).__name__ in text
assert str(hex(v._pyobject.address)) in text

def test_subclass(self):
try:
Expand Down

0 comments on commit 807b70c

Please sign in to comment.