Skip to main content

Extended Inspect - view and modify memory structs of runtime objects.

Project description

einspect

Build codecov security

PyPI PyPI - Python Version

Extended Inspections for CPython

Documentation

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

from einspect import view

t = ("A", "B")
view(t)[1] = 10
print(t)
("A", 10)
from einspect import view

a = "hello"
b = 100

view(a).buffer[:] = b"world"
view(b).value = 5

print("hello", 100)
world 5

Modify attributes of built-in types

from einspect import view

v = view(int)
v["__iter__"] = lambda self: iter(range(self))
v["__str__"] = lambda self: "custom: " + repr(self)

for i in 3:
    print(i)
custom: 0
custom: 1
custom: 2

Move objects in memory

from einspect import view

s = "meaning of life"

v = view(s)
with v.unsafe():
    v <<= 42

print("meaning of life")
print("meaning of life" == 42)
42
True

Fully typed interface

image

Table of Contents

Views

Using the einspect.view constructor

This is the recommended and simplest way to create a View onto an object. Equivalent to constructing a specific View subtype from einspect.views, except the choice of subtype is automatic based on object type.

from einspect import view

print(view(1))
print(view("hello"))
print(view([1, 2]))
print(view((1, 2)))
IntView(<PyLongObject at 0x102058920>)
StrView(<PyUnicodeObject at 0x100f12ab0>)
ListView(<PyListObject at 0x10124f800>)
TupleView(<PyTupleObject at 0x100f19a00>)

Inspecting struct attributes

Attributes of the underlying C Struct of objects can be accessed through the view's properties.

from einspect import view

ls = [1, 2]
v = view(ls)

# Inherited from PyObject
print(v.ref_count)  # ob_refcnt
print(v.type)       # ob_type
# Inherited from PyVarObject
print(v.size)       # ob_size
# From PyListObject
print(v.item)       # ob_item
print(v.allocated)  # allocated
4
<class 'tuple'>
3
<einspect.structs.c_long_Array_3 object at 0x105038ed0>

2. Writing to view attributes

Writing to these attributes will affect the underlying object of the view.

Note that most memory-unsafe attribute modifications require entering an unsafe context manager with View.unsafe()

with v.unsafe():
    v.size -= 1

print(obj)

(1, 2)

Since items is an array of integer pointers to python objects, they can be replaced by id() addresses to modify index items in the tuple.

from einspect import view

tup = (100, 200)

with view(tup).unsafe() as v:
    s = "dog"
    v.item[0] = id(s)

print(tup)
('dog', 200)

>> Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

So here we did set the item at index 0 with our new item, the string "dog", but this also caused a segmentation fault. Note that the act of setting an item in containers like tuples and lists "steals" a reference to the object, even if we only supplied the address pointer.

To make this safe, we will have to manually increment a ref-count before the new item is assigned. To do this we can either create a view of our new item, and increment its ref_count += 1, or use the apis from einspect.api, which are pre-typed implementations of ctypes.pythonapi methods.

from einspect import view
from einspect.api import Py

tup = (100, 200)

with view(tup).unsafe() as v:
    a = "bird"
    Py.IncRef(a)
    v.item[0] = id(a)

    b = "kitten"
    Py.IncRef(b)
    v.item[1] = id(b)

print(tup)

('bird', 'kitten')

🎉 No more seg-faults, and we just successfully set both items in an otherwise immutable tuple.

To make the above routine easier, you can access an abstraction by simply indexing the view.

from einspect import view

tup = ("a", "b", "c")

v = view(tup)
v[0] = 123
v[1] = "hm"
v[2] = "🤔"

print(tup)

(123, 'hm', '🤔')

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

einspect-0.4.1.post1.tar.gz (32.9 kB view details)

Uploaded Source

Built Distribution

einspect-0.4.1.post1-py3-none-any.whl (46.0 kB view details)

Uploaded Python 3

File details

Details for the file einspect-0.4.1.post1.tar.gz.

File metadata

  • Download URL: einspect-0.4.1.post1.tar.gz
  • Upload date:
  • Size: 32.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.0 CPython/3.11.1 Linux/5.15.0-1030-azure

File hashes

Hashes for einspect-0.4.1.post1.tar.gz
Algorithm Hash digest
SHA256 164c0eddecb9616783f362b2443e58c8d1343a9ddff102ffdec3d1d13cd576c4
MD5 ed96bfcdaeb14c93bcec2a1e840af583
BLAKE2b-256 74675d82a9d857e36cd5211ee020a75872319f7050b1925cb6d9d41cccd08250

See more details on using hashes here.

File details

Details for the file einspect-0.4.1.post1-py3-none-any.whl.

File metadata

  • Download URL: einspect-0.4.1.post1-py3-none-any.whl
  • Upload date:
  • Size: 46.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.0 CPython/3.11.1 Linux/5.15.0-1030-azure

File hashes

Hashes for einspect-0.4.1.post1-py3-none-any.whl
Algorithm Hash digest
SHA256 0b226fef8e03d1a1152e39a3684ded9688f9ed41e7c5ee41542e0cce56fdc529
MD5 2ae055257405f4ac40745b8b28f9ac93
BLAKE2b-256 d92a83fa4e1147f71c09314149245bba386fd075ce5c37d512a7b57266e30056

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page