Collected lower-priority findings for consideration:
Exception swallowing
PyDict_GetItem x24 across dynamicscope.cpp (8), signaling.cpp (9), weakmethod.cpp (1), compiler_helpers.cpp (5, dead file) silently swallows exceptions. Hot scope resolution and signal dispatch paths are affected. Migrate to PyDict_GetItemWithError (available since 3.3).
- Unchecked
PyDict_SetItem x2 in compiler_helpers.cpp:239-240 — on OOM, execution continues with active exception.
- Unguarded
PyErr_Clear in compiler_helpers.cpp:460 after PyObject_Hash — clears all exceptions including MemoryError. Also, PyErr_Format at line 461 is called without an exception type as first argument (gets a format string instead) — likely crash or garbage exception.
Version compatibility cleanup
- 9 dead
#if PY_VERSION_HEX >= 0x03090000 guards — min is 3.10, these are always true
- 17 deprecated
PyModule_AddObject calls — should migrate to PyModule_AddObjectRef (available since 3.10)
PyWeakref_GET_OBJECT deprecated since 3.13, 5 sites across callableref.cpp, weakmethod.cpp, signaling.cpp. Replace with PyWeakref_GetRef (3.13+).
PyErr_Fetch/PyErr_Restore in dynamicscope.cpp:135-136 — deprecated in 3.12
compiler_helpers.cpp is dead code (not in setup.py) — should be deleted
Private API uses
_Py_NewReference x2 (freelist reuse in signaling.cpp:951, declarative_function.cpp:487) — private, may change
_PyObject_GetDictPtr x4 (dynamicscope.cpp:100,196,267, signaling.cpp:93) — private, no public equivalent with same semantics
_PyType_Lookup x3 (dynamicscope.cpp:91,178,257) — private, used for MRO lookup without descriptor invocation
GC and type notes
- Alias, Color, Font have
PyObject* members but no Py_TPFLAGS_HAVE_GC / tp_traverse — cycles through these types can't be collected
Signal has Py_TPFLAGS_HAVE_GC but no PyObject* members (minor overhead, forward-looking)
weak_methods dict in weakmethod.cpp — growing mutable global, never cleaned up
Free-threading readiness
- 2 freelists (BoundSignal, BoundDMethod) without synchronization
- ~18 global
PyObject* across modules — all m_size=0
- No
Py_MOD_GIL_NOT_USED on any module
pythoncapi-compat adoption would help with PyModule_AddObjectRef, PyErr_GetRaisedException migrations
Other
- Copy-paste naming:
Nonlocals_Type_slots in fontext.cpp:239 should be Font_Type_slots
add_alias incomplete in compiler_helpers.cpp:691-693 — empty branch, never creates the alias
BoundSignal_disconnect leaks CallableRef on method-path disconnect (signaling.cpp:854,867)
Found by cext-review-toolkit.
Collected lower-priority findings for consideration:
Exception swallowing
PyDict_GetItemx24 acrossdynamicscope.cpp(8),signaling.cpp(9),weakmethod.cpp(1),compiler_helpers.cpp(5, dead file) silently swallows exceptions. Hot scope resolution and signal dispatch paths are affected. Migrate toPyDict_GetItemWithError(available since 3.3).PyDict_SetItemx2 incompiler_helpers.cpp:239-240— on OOM, execution continues with active exception.PyErr_Clearincompiler_helpers.cpp:460afterPyObject_Hash— clears all exceptions including MemoryError. Also,PyErr_Formatat line 461 is called without an exception type as first argument (gets a format string instead) — likely crash or garbage exception.Version compatibility cleanup
#if PY_VERSION_HEX >= 0x03090000guards — min is 3.10, these are always truePyModule_AddObjectcalls — should migrate toPyModule_AddObjectRef(available since 3.10)PyWeakref_GET_OBJECTdeprecated since 3.13, 5 sites acrosscallableref.cpp,weakmethod.cpp,signaling.cpp. Replace withPyWeakref_GetRef(3.13+).PyErr_Fetch/PyErr_Restoreindynamicscope.cpp:135-136— deprecated in 3.12compiler_helpers.cppis dead code (not insetup.py) — should be deletedPrivate API uses
_Py_NewReferencex2 (freelist reuse insignaling.cpp:951,declarative_function.cpp:487) — private, may change_PyObject_GetDictPtrx4 (dynamicscope.cpp:100,196,267,signaling.cpp:93) — private, no public equivalent with same semantics_PyType_Lookupx3 (dynamicscope.cpp:91,178,257) — private, used for MRO lookup without descriptor invocationGC and type notes
PyObject*members but noPy_TPFLAGS_HAVE_GC/tp_traverse— cycles through these types can't be collectedSignalhasPy_TPFLAGS_HAVE_GCbut noPyObject*members (minor overhead, forward-looking)weak_methodsdict inweakmethod.cpp— growing mutable global, never cleaned upFree-threading readiness
PyObject*across modules — allm_size=0Py_MOD_GIL_NOT_USEDon any modulepythoncapi-compatadoption would help withPyModule_AddObjectRef,PyErr_GetRaisedExceptionmigrationsOther
Nonlocals_Type_slotsinfontext.cpp:239should beFont_Type_slotsadd_aliasincomplete incompiler_helpers.cpp:691-693— empty branch, never creates the aliasBoundSignal_disconnectleaksCallableRefon method-path disconnect (signaling.cpp:854,867)Found by cext-review-toolkit.