Skip to content

Commit 6100937

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 1bc682e commit 6100937

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
@@ -365,7 +365,18 @@ meth_hash(PythonQtSignalFunctionObject *a)
365365
if (x == -1)
366366
return -1;
367367
}
368+
#if PY_VERSION_HEX >= 0x30D0000 /* 0x30D0000 == 3.13.0a0 */
369+
y = Py_HashPointer((void*)(a->m_ml)); /* public in 3.13+ */
370+
#elif !defined(Py_LIMITED_API)
371+
/* fallback: use CPython’s private helper (requires full API) */
368372
y = _Py_HashPointer((void*)(a->m_ml));
373+
#else
374+
/* portable fallback for the limited/stable ABI */
375+
uintptr_t v = (uintptr_t)(void*)(a->m_ml);
376+
/* simple mixing, similar to CPython’s */
377+
Py_hash_t y = (Py_hash_t)(v >> 4) ^ (Py_hash_t)(v >> (sizeof(v)*4));
378+
if (y == -1) y = -2; /* never return −1 */
379+
#endif
369380
if (y == -1)
370381
return -1;
371382
x ^= y;

src/PythonQtSlot.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,18 @@ meth_hash(PythonQtSlotFunctionObject *a)
772772
return -1;
773773
}
774774
y = _Py_HashPointer((void*)(a->m_ml));
775+
#if PY_VERSION_HEX >= 0x30D0000 /* 0x30D0000 == 3.13.0a0 */
776+
y = Py_HashPointer((void*)(a->m_ml)); /* public in 3.13+ */
777+
#elif !defined(Py_LIMITED_API)
778+
/* fallback: use CPython’s private helper (requires full API) */
779+
y = _Py_HashPointer((void*)(a->m_ml));
780+
#else
781+
/* portable fallback for the limited/stable ABI */
782+
uintptr_t v = (uintptr_t)(void*)(a->m_ml);
783+
/* simple mixing, similar to CPython’s */
784+
Py_hash_t y = (Py_hash_t)(v >> 4) ^ (Py_hash_t)(v >> (sizeof(v)*4));
785+
if (y == -1) y = -2; /* never return −1 */
786+
#endif
775787
if (y == -1)
776788
return -1;
777789
x ^= y;

0 commit comments

Comments
 (0)