Skip to content

Commit 4678af4

Browse files
authored
Add Py_HashPointer() (#83)
1 parent 2ff4441 commit 4678af4

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

docs/api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ Python 3.13
137137
138138
See `PyDict_PopString() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_PopString>`__.
139139
140+
.. c:function:: Py_hash_t Py_HashPointer(const void *ptr)
141+
142+
See `Py_HashPointer() documentation <https://docs.python.org/dev/c-api/hash.html#c.Py_HashPointer>`__.
143+
140144
141145
Python 3.12
142146
-----------

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Changelog
22
=========
33

4+
* 2023-12-15: Add function ``Py_HashPointer()``.
45
* 2023-11-14: Add functions:
56

67
* ``PyDict_Pop()``

pythoncapi_compat.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,25 @@ PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
10891089
}
10901090
#endif
10911091

1092+
1093+
#if PY_VERSION_HEX < 0x030200A4
1094+
// Python 3.2.0a4 added Py_hash_t type
1095+
typedef Py_ssize_t Py_hash_t;
1096+
#endif
1097+
1098+
1099+
// gh-111545 added Py_HashPointer() to Python 3.13.0a3
1100+
#if PY_VERSION_HEX < 0x030D00A3
1101+
static inline Py_hash_t Py_HashPointer(const void *ptr)
1102+
{
1103+
#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION)
1104+
return _Py_HashPointer(ptr);
1105+
#else
1106+
return _Py_HashPointer(_Py_CAST(void*, ptr));
1107+
#endif
1108+
}
1109+
#endif
1110+
10921111
#ifdef __cplusplus
10931112
}
10941113
#endif

tests/test_pythoncapi_compat_cext.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,34 @@ test_list(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
14981498
}
14991499

15001500

1501+
static PyObject *
1502+
test_hash(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
1503+
{
1504+
void *ptr0 = NULL;
1505+
assert(Py_HashPointer(ptr0) == 0);
1506+
1507+
#ifndef PYPY_VERSION
1508+
#if SIZEOF_VOID_P == 8
1509+
void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890;
1510+
assert(Py_HashPointer(ptr1) == (uintptr_t)0x0ABCDEF123456789);
1511+
#else
1512+
void *ptr1 = (void*)(uintptr_t)0xDEADCAFE;
1513+
assert(Py_HashPointer(ptr1) == (uintptr_t)0xEDEADCAF);
1514+
#endif
1515+
#else
1516+
// PyPy
1517+
#if SIZEOF_VOID_P == 8
1518+
void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890;
1519+
#else
1520+
void *ptr1 = (void*)(uintptr_t)0xDEADCAFE;
1521+
#endif
1522+
assert(Py_HashPointer(ptr1) == (Py_hash_t)ptr1);
1523+
#endif
1524+
1525+
Py_RETURN_NONE;
1526+
}
1527+
1528+
15011529
static struct PyMethodDef methods[] = {
15021530
{"test_object", test_object, METH_NOARGS, _Py_NULL},
15031531
{"test_py_is", test_py_is, METH_NOARGS, _Py_NULL},
@@ -1530,6 +1558,7 @@ static struct PyMethodDef methods[] = {
15301558
#endif
15311559
{"test_unicode", test_unicode, METH_NOARGS, _Py_NULL},
15321560
{"test_list", test_list, METH_NOARGS, _Py_NULL},
1561+
{"test_hash", test_hash, METH_NOARGS, _Py_NULL},
15331562
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
15341563
};
15351564

0 commit comments

Comments
 (0)