einspect#
Extended Inspections for CPython.
Check detailed states of built-in objects#
from einspect import view
ls = [1, 2, 3]
v = view(ls)
print(v.info())
PyListObject(at 0x2833738):
ob_refcnt: Py_ssize_t = 5
ob_type: *PyTypeObject = &[list]
ob_item: **PyObject = &[&[1], &[2], &[3]]
allocated: Py_ssize_t = 4
Mutate tuples, strings, ints, or other immutable types#
TupleView and StrView supports all MutableSequence methods (append, extend, insert, pop, remove, reverse, clear).
⚠️ A note on safety.
from einspect import view
tup = (1, 2)
v = view(tup)
v[1] = 500
print(tup) # (1, 500)
v.append(3)
print(tup) # (1, 500, 3)
del v[:2]
print(tup) # (3,)
print(v.pop()) # 3
v.extend([1, 2])
print(tup) # (1, 2)
v.clear()
print(tup) # ()
from einspect import view
text = "hello"
v = view(text)
v[1] = "3"
v[4:] = "o~"
v.append("!")
print(text) # h3llo~!
v.reverse()
print(text) # !~oll3h
from einspect import view
n = 500
view(n).value = 10
print(500) # 10
print(500 == 10) # True
Modify attributes of built-in types, get original attributes with orig
#
from einspect import view, orig
v = view(int)
v["__name__"] = "custom_int"
v["__iter__"] = lambda s: iter(range(s))
v["__repr__"] = lambda s: "custom: " + orig(int).__repr__(s)
print(int)
for i in 3:
print(i)
<class 'custom_int'>
custom: 0
custom: 1
custom: 2
Implement methods on built-in types#
See the Extending Types docs page for more information.
from einspect import impl, orig
@impl(int)
def __add__(self, other):
other = int(other)
return orig(int).__add__(self, other)
print(50 + "25") # 75
Move objects in memory#
from einspect import view
s = "meaning of life"
v = view(s)
with v.unsafe():
v <<= 42
print("meaning of life") # 42
print("meaning of life" == 42) # True
CPython Struct bindings and API methods#
Easily make calls to CPython stable ABI (
ctypes.pythonapi
) as bound methods onPyObject
instances.
from einspect.structs import PyDictObject
d = {"a": (1, 2), "b": (3, 4)}
res = PyDictObject(d).GetItem("a")
if res:
print(res.contents.NewRef())
Equivalent to the following with ctypes:
from ctypes import pythonapi, py_object, c_void_p, cast
d = {"a": (1, 2), "b": (3, 4)}
PyDict_GetItem = pythonapi["PyDict_GetItem"]
# Can't use auto cast py_object for restype,
# since missing keys return NULL and causes segmentation fault with no set error
PyDict_GetItem.restype = c_void_p
PyDict_GetItem.argtypes = [py_object, py_object]
res = PyDict_GetItem(d, "a")
res = cast(res, py_object)
Py_NewRef = pythonapi["Py_NewRef"]
Py_NewRef.restype = py_object
Py_NewRef.argtypes = [py_object]
try:
print(Py_NewRef(res.value))
except ValueError:
pass
Create new instances of PyObject structs with field values, from existing objects, or from address.
from einspect.structs import PyLongObject, PyTypeObject
x = PyLongObject(
ob_refcnt=1,
ob_type=PyTypeObject(int).as_ref(),
ob_size=1,
ob_item=[15],
).into_object()
print(x) # 15
print(x == 15) # True
print(x is 15) # False