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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions