Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ionite34/einspect
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.5.8
Choose a base ref
...
head repository: ionite34/einspect
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Loading
Showing with 2,340 additions and 791 deletions.
  1. +3 −0 .gitignore
  2. +7 −7 .pre-commit-config.yaml
  3. +53 −0 README.md
  4. +1 −1 docs/source/conf.py
  5. +518 −476 poetry.lock
  6. +20 −8 pyproject.toml
  7. +5 −8 src/einspect/__init__.py
  8. +0 −2 src/einspect/_compat/py_function_3_10.py
  9. +0 −2 src/einspect/_compat/py_function_3_9.py
  10. +1 −6 src/einspect/_compat/py_unicode_3_12.py
  11. +9 −5 src/einspect/_patch.py
  12. +11 −0 src/einspect/_typing.py
  13. +4 −0 src/einspect/api.py
  14. +11 −2 src/einspect/protocols/type_parse.py
  15. +86 −12 src/einspect/structs/deco.py
  16. +4 −6 src/einspect/structs/include/descrobject_h.py
  17. +3 −4 src/einspect/structs/include/methodobject_h.py
  18. +9 −14 src/einspect/structs/include/object_h.py
  19. +0 −2 src/einspect/structs/mapping_proxy.py
  20. +0 −2 src/einspect/structs/py_bool.py
  21. +0 −2 src/einspect/structs/py_cfunction.py
  22. +8 −8 src/einspect/structs/py_dict.py
  23. +1 −3 src/einspect/structs/py_float.py
  24. +0 −2 src/einspect/structs/py_function.py
  25. +3 −5 src/einspect/structs/py_gc.py
  26. +4 −3 src/einspect/structs/py_list.py
  27. +0 −2 src/einspect/structs/py_long.py
  28. +30 −16 src/einspect/structs/py_object.py
  29. +8 −7 src/einspect/structs/py_set.py
  30. +3 −2 src/einspect/structs/py_tuple.py
  31. +140 −15 src/einspect/structs/py_type.py
  32. +1 −6 src/einspect/structs/py_unicode.py
  33. +14 −5 src/einspect/structs/slots_map.py
  34. +142 −15 src/einspect/type_orig.py
  35. +3 −0 src/einspect/types.py
  36. +5 −0 src/einspect/views/view_base.py
  37. +364 −43 src/einspect/views/view_type.py
  38. +0 −10 tests/conftest.py
  39. +58 −0 tests/structs/test_null.py
  40. +9 −0 tests/structs/test_structs.py
  41. +84 −58 tests/test_impl.py
  42. +169 −0 tests/test_impl_sp.py
  43. +24 −2 tests/test_orig.py
  44. +1 −1 tests/test_patch.py
  45. +11 −0 tests/test_typing.py
  46. +25 −17 tests/views/test_move.py
  47. +6 −0 tests/views/test_view_base.py
  48. +44 −12 tests/views/test_view_type.py
  49. +7 −0 tools/README.md
  50. 0 tools/__init__.py
  51. +4 −0 tools/__main__.py
  52. +133 −0 tools/app.py
  53. +132 −0 tools/sources.py
  54. +162 −0 tools/struct_meta.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -142,6 +142,9 @@ venv.bak/
.dmypy.json
dmypy.json

# ruff linter
.ruff_cache/

# Pyre type checker
.pyre/

14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -18,16 +18,16 @@ repos:
exclude: einspect/structs/__init__.py

- repo: https://github.com/psf/black
rev: 22.12.0
rev: 23.3.0
hooks:
- id: black

- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.0.262"
hooks:
- id: flake8
additional_dependencies: [flake8-builtins, flake8-print]
- id: ruff
files: ^src/
args:
- --ignore=W503,E203,F842,A003,F403,F405
- --max-line-length=120
- --ignore=F842,A003,F403,F405
- --line-length=120
- --fix
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -139,6 +139,59 @@ 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 on `PyObject` instances.
```python
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:
```python
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.
```python
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
```

<!-- end intro -->

## Fully typed interface
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
project = "einspect"
copyright = "2023, Ionite"
author = "Ionite"
release = "v0.5.8"
release = "v0.5.16"


# -- General configuration ---------------------------------------------------
Loading