Skip to content

Modernization notes: dead version guards, deprecated APIs, private APIs, free-threading gaps #262

@devdanzin

Description

@devdanzin

Collected lower-priority findings for consideration:

Version compatibility cleanup

  • 11 dead #if PY_VERSION_HEX >= 0x03090000 guards across 8 files — minimum is 3.10, can be unconditionally removed
  • 19 deprecated PyModule_AddObject calls — should migrate to PyModule_AddObjectRef (available since 3.10, the minimum version). 10 of these are unchecked (see Copy-paste bug in init_containerlistchange + unchecked PyModule_AddObject x10 + cached_property stores NULL #261).
  • Py_TPFLAGS_HAVE_VERSION_TAG in 2 type specs (atomdict.cpp:349,430) — no-op since Python 3.0
  • PyErr_Fetch/PyErr_Restore in modifyguard.h:42,60 — deprecated in 3.12, clean migration to PyErr_GetRaisedException/PyErr_SetRaisedException
  • PyMapping_HasKey fallback for 3.10-3.12 (catom.cpp:454-460) suppresses exceptions

Private API uses

  • _Py_NewReference in eventbinder.cpp:170 and signalconnector.cpp:184 (freelist reuse) — private API, may change across versions
  • _PyObject_GetDictPtr in catom.cpp:383 — private API, no public equivalent with identical semantics
  • pythoncapi-compat adoption would eliminate the active PyMapping_HasKeyWithError version guard and enable forward API migrations

Free-threading readiness

  • 2 freelists (EventBinder, SignalConnector) without synchronization — would race under Py_GIL_DISABLED
  • Global GuardMap and RefMap (catom.cpp:653, atomref.cpp:37) — process-global mutable state
  • Non-atomic bitfield operations on CAtom flags
  • set_slot TOCTOU between validation and store
  • ObserverPool unprotected container operations
  • No Py_MOD_GIL_NOT_USED declared in either module

Type slot notes

  • MethodWrapper and AtomMethodWrapper have PyObject* members but no Py_TPFLAGS_HAVE_GC — GC can't break cycles through these types
  • sortedmap_modexec returns false(0) not -1 — wrong return convention for Py_mod_exec (should return -1 on error)

Module state

  • Multi-phase init without per-module state: Both PyModuleDef have m_size=0 despite ~47 global PyObject* variables. HIGH migration difficulty.
  • Py_TPFLAGS_IMMUTABLETYPE not set on any type (available since 3.10)

Found by cext-review-toolkit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions