New
- `einspect.view` now supports subtypes. The additional instance dictionary is supported to be moved during `View.move_from` or `View.move_to`
python
from einspect import view
class Num(int):
pass
print(view(10))
IntView(<PyLongObject at 0x101786a60>)
print(view(Num(10)))
IntView[Num](<PyLongObject at 0x1006e7440>)
- Memory moves now no longer require an unsafe context if it can be performed safely.
- If safe moving is not possible (target size exceeds allocated memory for the object) an UnsafeError is raised.
python
from einspect import view
x = 900
view(x) << 50
ls = [1, 2]
view(ls) << [3, 4, 5]
tup = (1, 2)
view(tup) << (1, 2)
Changes
- `einspect.view` DeprecationWarning for non-concrete types is removed.
- `View.move_from` no longer makes a deep-copy of `other`, this was originally added to prevent member references from being dropped but hindered features like connected instance dictionary pointers from working.
- Such, the target of a move will receive most heap-allocated pointers of the source. For example, moved lists will share the original `ob_item` array
python
from einspect import view, unsafe
ls = []
x = [3, 4]
with unsafe():
view(ls) << x
print(ls) [3, 4]
Updating x will now affect ls as well
x[0] = "hi"
print(ls) ['hi', 4]
- However, this only applies to pointers referring to allocations off the object struct, other attributes are still statically moved. For example, calling `x.clear()` will deallocate the `ob_item` array of `x` and set it as a `NULL` pointer. But `ls` still has an `ob_size` of 2, and will try to access its `ob_item` pointer to get elements.
python
from einspect import view, unsafe
ls = []
x = [3, 4]
with unsafe():
view(ls) << x
x.clear()
print(ls) Segmentation fault (likely)
- To revert to original behavior, `deepcopy` can be called explicitly
python
from copy import deepcopy
from einspect import view, unsafe
ls = []
x = [3, 4]
with unsafe():
view(ls) << deepcopy(x)
x.clear()
print(ls) [3, 4]
- PyObject and subclasses can now be provided 1 positional argument to invoke `from_object` behavior:
python
from einspect.structs import PyObject, PyTypeObject
obj = PyObject("foo")
equivalent to
obj = PyObject.from_object("foo")
- Manual struct creation can still be done with kwargs. This mode will also now invoke the relevant `_PyObject_New`, `_PyObject_NewVar`, or `_PyObject_GC_NewVar` C APIs to correctly initialize GC linked lists and allocate the object using free-lists, matching the interpreter’s native handling of new objects.
python
from einspect.structs import PyObject, PyTypeObject
obj = PyObject(
ob_refcnt=1,
ob_type=PyTypeObject(object).as_ref(),
)
**Full Changelog**: https://github.com/ionite34/einspect/compare/v0.4.10...v0.5.0