Skip to content

Align ctypes call ownership and C error state with Python 3.15 - #9218

Draft
youknowdot wants to merge 3 commits into
RustPython:mainfrom
youknowdot:split/ctypes-call-contracts-315
Draft

youknowdot wants to merge 3 commits into
RustPython:mainfrom
youknowdot:split/ctypes-call-contracts-315

Conversation

@youknowdot

@youknowdot youknowdot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Extract the Python3.15 ctypes call-contract closure from #8954, with its required CAPI error-state dependency:

  • Retain converted argument owners, traverse CArg owners, support pointer callback arguments and preserve attachment around native calls/callbacks.
  • Use fallible variadic call interfaces and match the canonical optional complex-type/type-layout contracts.
  • Keep raised C errors separate from handled exceptions, including the existing mega CAPI reader/writer changes.
  • Preserve pending C errors across finalizers, weakref callbacks and Python buffer-release hooks; clear before exception constructors and match arbitrary-object _ctypes.__getattr__ behavior.
  • Regenerate three production ctypes modules and twelve related canonical test/helper files from CPython3.15.0 d220409a13b77de7a6c30abe16ea90db01528edc through the existing updater. Preserve existing guards except the proven Linux system-enumeration skip, narrowed through documented updater marker data. No manual Lib changes or updater special cases.

The utility/dllist dependency is included: synchronous native enumeration on Linux and Android copies loader-owned names before Python decoding. Existing macOS/Windows paths are preserved; unsupported outer targets are not newly supported. Android uses the repository API24 baseline, above the loader API21 requirement. Contributor-owned sequence-repetition changes are not duplicated.

Validation

Current combined checkpoint 607e121

The initial hosted Linux run at 8e78504 failed with test_ctypes ENV CHANGED: the old Python/libffi dllist callback raised an unraisable ValueError: PyObject is NULL, then the test skipped its missing extension fixture. Its automatic rerun reproduced the same environmental failure. The native dllist dependency removes that obsolete callback path.

  • Fresh source-bound sqlite+CAPI release, normal/-E/-I provenance and all 21 focused Python stages pass.
  • Existing canonical ListSharedLibraries under canonical unraisable/environment checking: system test passes, genuine missing _ctypes_test fixture skips, environment_altered=false. The fixture guard is retained.
  • Four canonical Linux discovery cases pass on both candidate and pinned CPython. A separate verified official-libffi copy/load observation passes on both; no library function is invoked and this is not represented as canonical fixture execution.
  • Prior ctypes, PythonAPI, teardown and unchanged snippet selections rerun successfully on combined source.
  • Combined root/VM tests: 174 passed, 2 ignored; CAPI tests: 123 passed, 4 ignored. Workspace and CAPI strict Clippy passed. Source/protected audits clean. No incidental main rebase was mixed into this repair.

Historical constituent evidence

Standalone dllist on main eb2ffc6: fresh release, 1,401 workspace tests passed/18 ignored, 123 CAPI tests passed/4 ignored, both strict Clippy gates passed. Historical main58b54 fails the unchanged system-enumeration body with Unsupported argument type; native candidate and oracle pass. Local Android runtime and OpenGL-loader coverage are not claimed.

Original ctypes checkpoint 8e78504 (fresh sqlite+capi release):

  • Source-bound normal/-E/-I provenance checked.
  • Candidate31 canonical ctypes executions, including2 skips; five other selected modules are entirely skipped by their existing missing _ctypes_test guard.
  • Pinned oracle136 ctypes executions, including4 skips.
  • Eight existing finalizer/weakref/buffer selections pass on both.
  • Two unchanged scalar/pointer/errno and aggregate-ABI snippets pass on both.
  • PythonAPI observations match the oracle: successful call inside except, real conversion error, callback/constructor reentry, clear and handled identity.
  • _ctypes.__getattr__(None/42/tuple) produced TypeError on sealed mega baseline and now matches the oracle's exact AttributeError/messages.
  • Source/marker audits and68 oracle binary/extension hashes unchanged; normal hooks pass.
  • Full workspace baseline at 54e6f3d0: 1,402 passed, 18 ignored. The final checkpoint aligns raised-field destruction order with mega; after that change, affected root/VM tests were rerun: 174 passed, 2 ignored, including the native guard invariant and existing drop/GC tests.
  • Final CAPI tests: 123 passed, 4 ignored. Workspace and CAPI strict Clippy passed.

Important provenance: mega already had the separate raised slot. The initial narrowed extraction omitted that dependency; it was restored before candidate runtime. The same PYFUNCTYPE inside-except probe passed on both mega and oracle, so this PR does not claim a newly reproduced mega conflation bug.

The native guard test checks storage nesting and Rust unwind. The Python teardown selections exercise real boundaries, but do not establish every nonempty-native-error reentrancy combination. No all-platform ABI or comprehensive callback/GC parity claim. Existing foreign-thread callback entry, callback conversion-error reporting, errcheck locking and incomplete callback metadata traversal remain separate limitations.

OpenAI Codex assisted with implementation, source review, canonical regeneration, automated validation and this PR description. The stated local checks were automated; this does not claim manual human testing. Prepared for the user's maintainer-directed Python3.15 upgrade work.

Keep native raised errors separate from handled exceptions and preserve them across teardown callbacks. Import the related canonical ctypes call and type contracts.

Assisted-by: OpenAI Codex: model version unavailable
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

:4: SyntaxWarning: invalid decimal literal
:7: SyntaxWarning: "\z" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\z"? A raw string is also an option.
:10: SyntaxWarning: "\400" is an invalid octal escape sequence. Such sequences will not work in the future. Did you mean "\400"? A raw string is also an option.
:4: SyntaxWarning: invalid decimal literal
:7: SyntaxWarning: "\z" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\z"? A raw string is also an option.
:10: SyntaxWarning: "\400" is an invalid octal escape sequence. Such sequences will not work in the future. Did you mean "\400"? A raw string is also an option.
:4: SyntaxWarning: invalid decimal literal
:7: SyntaxWarning: "\z" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\z"? A raw string is also an option.
:10: SyntaxWarning: "\400" is an invalid octal escape sequence. Such sequences will not work in the future. Did you mean "\400"? A raw string is also an option.
[ ] lib: cpython/Lib/ctypes
[ ] test: cpython/Lib/test/test_ctypes (TODO: 8)
[ ] test: cpython/Lib/test/test_stable_abi_ctypes.py

dependencies:

  • ctypes (native: _ctypes, ctypes._aix, ctypes._endian, ctypes.macholib.dyld, ctypes.macholib.dylib, ctypes.macholib.framework, importlib.machinery, itertools, nt, sys)
    • sysconfig (native: _sysconfig, _winapi, importlib.machinery, importlib.util, os.path, sys)
    • os, re, shutil, struct, subprocess, tempfile, types, warnings

dependent tests: (34 tests)

  • ctypes: test_android test_buffer test_bytes test_code test_codecs test_ctypes test_genericalias test_ntpath test_os test_ssl test_venv
    • platform: test__locale test__osx_support test_asyncio test_baseexception test_builtin test_calendar test_cmath test_fcntl test_math test_mimetypes test_os test_platform test_regrtest test_shutil test_socket test_strptime test_sysconfig test_time test_winreg test_wsgiref
      • pydoc: test_enum test_pydoc
    • webbrowser: test_webbrowser

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

Copy loader-owned names before Python filesystem decoding and update the related canonical ctypes utility and discovery tests from CPython 3.15. Preserve existing platform paths and dllist test markers.

Assisted-by: OpenAI Codex: model version unavailable
Regenerate the pinned test through update_lib patches with reviewed marker data. Preserve other platform conditions and the unavailable extension-fixture guard.

Assisted-by: OpenAI Codex: model version unavailable
@codspeed

codspeed Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 13.4%

❌ 1 regressed benchmark
✅ 61 untouched benchmarks
⏩ 4 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ rustpython[frozenset.py] 358.4 µs 413.8 µs -13.4%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing youknowdot:split/ctypes-call-contracts-315 (607e121) with main (c08375b)

Open in CodSpeed

Footnotes

  1. 4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant