Skip to content

Commit c9a6302

Browse files
committed
ENH: Add compatibility for Python 3.13 hashing with fallbacks for older versions
Py_HashPointer() is not available in Python 3.12. It was only added to the public C-API in Python 3.13 (see the “What’s New in 3.13” notes) Release Status of a pointer-hash helper ≤ 3.12 Only the private, internal function _Py_HashPointer() exists. It is not exported in the limited- or stable-ABI headers and may disappear or change without notice. 3.13+ Py_HashPointer(const void *ptr) becomes a public API entry in <Python.h>.
1 parent 2c6f7fc commit c9a6302

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

src/PythonQtSignal.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,18 @@ meth_hash(PythonQtSignalFunctionObject *a)
358358
if (x == -1)
359359
return -1;
360360
}
361+
#if PY_VERSION_HEX >= 0x30D0000 /* 0x30D0000 == 3.13.0a0 */
362+
y = Py_HashPointer((void*)(a->m_ml)); /* public in 3.13+ */
363+
#elif !defined(Py_LIMITED_API)
364+
/* fallback: use CPython’s private helper (requires full API) */
361365
y = _Py_HashPointer((void*)(a->m_ml));
366+
#else
367+
/* portable fallback for the limited/stable ABI */
368+
uintptr_t v = (uintptr_t)(void*)(a->m_ml);
369+
/* simple mixing, similar to CPython’s */
370+
Py_hash_t y = (Py_hash_t)(v >> 4) ^ (Py_hash_t)(v >> (sizeof(v)*4));
371+
if (y == -1) y = -2; /* never return −1 */
372+
#endif
362373
if (y == -1)
363374
return -1;
364375
x ^= y;

src/PythonQtSlot.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,18 @@ meth_hash(PythonQtSlotFunctionObject *a)
765765
return -1;
766766
}
767767
y = _Py_HashPointer((void*)(a->m_ml));
768+
#if PY_VERSION_HEX >= 0x30D0000 /* 0x30D0000 == 3.13.0a0 */
769+
y = Py_HashPointer((void*)(a->m_ml)); /* public in 3.13+ */
770+
#elif !defined(Py_LIMITED_API)
771+
/* fallback: use CPython’s private helper (requires full API) */
772+
y = _Py_HashPointer((void*)(a->m_ml));
773+
#else
774+
/* portable fallback for the limited/stable ABI */
775+
uintptr_t v = (uintptr_t)(void*)(a->m_ml);
776+
/* simple mixing, similar to CPython’s */
777+
Py_hash_t y = (Py_hash_t)(v >> 4) ^ (Py_hash_t)(v >> (sizeof(v)*4));
778+
if (y == -1) y = -2; /* never return −1 */
779+
#endif
768780
if (y == -1)
769781
return -1;
770782
x ^= y;

0 commit comments

Comments
 (0)