Browse Source

Merge branch 'master' of pion.martmists.com:Martmists/PythonSnippets

master
Martijn 2 years ago
parent
commit
0d20d0429f
  1. 37
      py_ctypes/cpy_types/meta_types.py
  2. 34
      py_ctypes/cpy_types/method_types.py
  3. 13
      py_ctypes/ctype.py
  4. 2
      py_ctypes/ctype_view.py
  5. 29
      py_ctypes/test.py

37
py_ctypes/cpy_types/meta_types.py

@ -59,9 +59,9 @@ class CPyTypeObject(CPyVarObject): @@ -59,9 +59,9 @@ class CPyTypeObject(CPyVarObject):
self.tp_vectorcall_offset = cprop("tp_vectorcall_offset", "n")
self.tp_getattr = cprop("tp_getattr", "P[void]")
self.tp_setattr = cprop("tp_setattr", "P[void]")
self.tp_as_async = cprop("tp_as_async", "P[void]") # TODO: Maybe add tp_reserved for <3.4?
self.tp_as_async = cprop("tp_as_async", "P[CPyAsyncMethods]")
self.tp_repr = cprop("tp_repr", "P[void]")
self.tp_as_number = cprop("tp_as_number", "P[void]")
self.tp_as_number = cprop("tp_as_number", "P[CPyNumberMethods]")
self.tp_as_sequence = cprop("tp_as_sequence", "P[CPySequenceMethods]")
self.tp_as_mapping = cprop("tp_as_mapping", "P[CPyMappingMethods]")
self.tp_hash = cprop("tp_hash", "P[void]")
@ -69,7 +69,7 @@ class CPyTypeObject(CPyVarObject): @@ -69,7 +69,7 @@ class CPyTypeObject(CPyVarObject):
self.tp_str = cprop("tp_str", "P[void]")
self.tp_getattro = cprop("tp_getattro", "P[void]")
self.tp_setattro = cprop("tp_setattro", "P[void]")
self.tp_as_buffer = cprop("tp_as_buffer", "P[void]")
self.tp_as_buffer = cprop("tp_as_buffer", "P[CPyBufferProcs]")
self.tp_flags = cprop("tp_flags", "l")
self.tp_doc = cprop("tp_doc", "P[void]")
self.tp_traverse = cprop("tp_traverse", "P[void]")
@ -153,5 +153,32 @@ class CPyTypeObject(CPyVarObject): @@ -153,5 +153,32 @@ class CPyTypeObject(CPyVarObject):
)
# TODO:
# - PyHeapTypeObject
class CPyHeapTypeObject(CType):
def __init__(self):
super().__init__()
self.ht_type = cprop("ht_type", "A[CPyTypeObject]1")
self.as_async = cprop("as_async", "A[CPyAsyncMethods]1")
self.as_number = cprop("as_number", "A[CPyNumberMethods]1")
self.as_mapping = cprop("as_mapping", "A[CPyMappingMethods]1")
self.as_sequence = cprop("as_sequence", "A[CPySequenceMethods]1")
self.as_buffer = cprop("as_buffer", "A[PyBufferProcs]1")
self.ht_name = cprop("ht_name", "P[CPyObject]")
self.ht_slots = cprop("ht_slots", "P[CPyObject]")
self.ht_qualname = cprop("ht_qualname", "P[CPyObject]")
self.ht_cached_keys = cprop("ht_cached_keys", "P[CPyDictKeysObject]")
self.ht_module = cprop("ht_module", "P[CPyObject]")
self.add_props(
self.ht_type,
self.as_async,
self.as_number,
self.as_mapping,
self.as_sequence,
self.as_buffer,
self.ht_name,
self.ht_slots,
self.ht_qualname,
self.ht_cached_keys,
self.ht_module,
)

34
py_ctypes/cpy_types/method_types.py

@ -21,10 +21,6 @@ class CPyMethodDef(CType): @@ -21,10 +21,6 @@ class CPyMethodDef(CType):
def get(cls, obj):
raise NotImplementedError
# TODO:
# - PyAsyncMethods
# - PyBufferProcs
class CPyNumberMethods(CType):
def __init__(self):
@ -161,3 +157,33 @@ class CPyMappingMethods(CType): @@ -161,3 +157,33 @@ class CPyMappingMethods(CType):
@classmethod
def get(cls, obj):
raise NotImplementedError
class CPyAsyncMethods(CType):
def __init__(self):
super().__init__()
self.am_await = cprop("am_await", "P[void]")
self.am_aiter = cprop("am_aiter", "P[void]")
self.am_anext = cprop("am_anext", "P[void]")
self.am_send = cprop("am_send", "P[void]").constraint(since=(3, 10))
self.add_props(
self.am_await,
self.am_aiter,
self.am_anext,
self.am_send
)
class CPyBufferProcs(CType):
def __init__(self):
super().__init__()
self.bf_getbuffer = cprop("bf_getbuffer", "P[void]")
self.bf_releasebuffer = cprop("bf_releasebuffer", "P[void]")
self.add_props(
self.bf_getbuffer,
self.bf_releasebuffer
)

13
py_ctypes/ctype.py

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import sys
from struct import calcsize
from typing import Tuple, Optional
from sys import version_info
from util import property
@ -9,16 +9,23 @@ __all__ = ('cprop', 'CType', '_TYPES') @@ -9,16 +9,23 @@ __all__ = ('cprop', 'CType', '_TYPES')
_TYPES = {}
def _version(x, min: tuple, max: tuple = None):
if max:
return x if min < version_info < max else None
return x if min < version_info else None
def cprop(name: str, ctype: str):
new = property()
new._name = name
new._ctype = ctype
new.version = lambda x, y=None: _version(new, x, y)
new.offset = 0
new.offset_after = 0
def constraint(since: Tuple[int, int, int], until: Tuple[int, int, int] = None) -> Optional[property]:
if since <= sys.version_info:
if until is None or sys.version_info < until:
if since <= version_info:
if until is None or version_info < until:
return new
return None

2
py_ctypes/ctype_view.py

@ -146,6 +146,8 @@ def get_view(addr: int, type_: _TYPE_ARG) -> _TYPE_ARG: @@ -146,6 +146,8 @@ def get_view(addr: int, type_: _TYPE_ARG) -> _TYPE_ARG:
for i in range(int(end_marker)):
items.append(get_view(addr + offset + i * type_obj.get_size(), type_obj))
if len(items) == 1:
items = items[0]
return items
def fset(obj, new_obj: List[CType]):

29
py_ctypes/test.py

@ -13,27 +13,26 @@ def main(): @@ -13,27 +13,26 @@ def main():
x = "totally a string"
y = 10
x_as_pyascii = get_view(id(x), CPyASCIIObject.instance()) # This sets the offsets properly on PyASCIIObject
y_as_pylong = get_view(id(y), CPyLongObject.instance())
offset = CPyASCIIObject.instance().wstr.offset_after # offset of content of PyASCIIObject
y_as_pylong.ob_type.tp_name = id(x)+offset # set address of int tp_name pointer to our string
print(type(420)) # used to be "int", now "totally a string"
x_as_pyascii = get_view(id(x), CPyASCIIObject.instance()) # This sets the offsets properly on PyASCIIObject
y_as_pylong = get_view(id(y), CPyLongObject.instance()) # Get an object representing the internal PyLongObject
offset = CPyASCIIObject.instance().wstr.offset_after # offset of string content of PyASCIIObject
y_as_pylong.ob_type.tp_name = id(x)+offset # set address of PyLongObject->ob_type->tp_name to the address of our string
print(type(420)) # used to be <class "int">, now <class "totally a string">
print(len(int.__name__)) # We didn't set .length, but len() still works.
# Note that this means some internal stuff can break
z = [10]
z_as_pylist = get_view(id(z), CPyListObject.instance())
print(CPyObject.by_reference(z_as_pylist) is z) # We get the exact same object back
f = __import__('sys')._getframe(1)
f_as_pyframe = get_view(id(f), CPyFrameObject.instance())
print(id(CPyObject.by_reference(f_as_pyframe.f_code).co_consts))
print("-")
print(CPyObject.by_reference(f_as_pyframe.f_code.co_filename))
class Dummy:
def __getitem__(self, item):
return None
# f = __import__('sys')._getframe(1)
# f_as_pyframe = get_view(id(f), CPyFrameObject.instance())
# print(id(CPyObject.by_reference(f_as_pyframe.f_code).co_consts))
# print("-")
# print(CPyObject.by_reference(f_as_pyframe.f_code.co_filename))
# class Dummy:
# def __getitem__(self, item):
# return None
# dummy = get_view(id(Dummy), CPyTypeObject.instance())
# x_as_pyascii.ob_type.tp_as_mapping.mp_subscript = dummy.tp_as_mapping.mp_subscript # Set str getitem handler to one that uses __getitem__
# str_dict = CPyObject.by_reference(x_as_pyascii.ob_type.tp_dict)
@ -81,7 +80,7 @@ def main(): @@ -81,7 +80,7 @@ def main():
print("start")
print(py10.ob_size)
print(py10.ob_digit[0].value)
10[20] = -30 # 10.ob_digit = 20.ob_digit + -30.ob_digit
10[20] = 30 # 10.ob_digit = 20.ob_digit + 30.ob_digit
print("end")
print(py10.ob_size)
print(py10.ob_digit[0].value)

Loading…
Cancel
Save