8000 gh-113024: C API: Add PyObject_GenericHash() function · serhiy-storchaka/cpython@9999130 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9999130

Browse files
pythongh-113024: C API: Add PyObject_GenericHash() function
1 parent cde1417 commit 9999130

File tree

14 files changed

+50
-7
lines changed

14 files changed

+50
-7
lines changed

Doc/c-api/hash.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,13 @@ See also the :c:member:`PyTypeObject.tp_hash` member.
5959
The function cannot fail: it cannot return ``-1``.
6060
6161
.. versionadded:: 3.13
62+
63+
.. c:function:: Py_hash_t PyObject_GenericHash(PyObject *obj)
64+
65+
Generic hashing function that is meant to be put into a type
66+
object's ``tp_hash`` slot.
67+
It's result only depends on the object's identitity.
68+
69+
In CPython it is equivalent to :c:func:`Py_HashPointer`.
70+
71+
.. versionadded:: 3.13

Doc/c-api/typeobj.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,10 @@ and :c:data:`PyType_Type` effectively act as defaults.)
883883
:c:member:`~PyTypeObject.tp_richcompare` and :c:member:`~PyTypeObject.tp_hash`, when the subtype's
884884
:c:member:`~PyTypeObject.tp_richcompare` and :c:member:`~PyTypeObject.tp_hash` are both ``NULL``.
885885

886+
**Default:**
887+
888+
:c:data:`PyBaseObject_Type` uses :c:func:`PyObject_GenericHash`.
889+
886890

887891
.. c:member:: ternaryfunc PyTypeObject.tp_call
888892

Doc/whatsnew/3.13.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,10 @@ New Features
12741274
* Add :c:func:`Py_HashPointer` function to hash a pointer.
12751275
(Contributed by Victor Stinner in :gh:`111545`.)
12761276

1277+
* Add :c:func:`PyObject_GenericHash` function that implements the default
1278+
hashing function of a Python object.
1279+
(Contributed by Serhiy Storchaka in :gh:`113024`.)
1280+
12771281

12781282
Porting to Python 3.13
12791283
----------------------

Include/cpython/pyhash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ typedef struct {
3737
PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void);
3838

3939
PyAPI_FUNC(Py_hash_t) Py_HashPointer(const void *ptr);
40+
PyAPI_FUNC(Py_hash_t) PyObject_GenericHash(PyObject *);

Lib/test/test_capi/test_abstract.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,12 @@ def test_number_check(self):
10001000
self.assertTrue(number_check(0.5))
10011001
self.assertFalse(number_check("1 + 1j"))
10021002

1003+
def test_object_generichash(self):
1004+
# Test PyObject_GenericHash()
1005+
generichash = _testcapi.object_generichash
1006+
for obj in object(), 1, 'string', []:
1007+
self.assertEqual(generichash(obj), object.__hash__(obj))
1008+
10031009

10041010
if __name__ == "__main__":
10051011
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add :c:func:`PyObject_GenericHash` function.

Modules/_decimal/_decimal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4842,7 +4842,7 @@ _dec_hash(PyDecObject *v)
48424842
return -1;
48434843
}
48444844
else if (mpd_isnan(MPD(v))) {
4845-
return _Py_HashPointer(v);
4845+
return PyObject_GenericHash((PyObject *)v);
48464846
}
48474847
else {
48484848
return py_hash_inf * mpd_arith_sign(MPD(v));

Modules/_testcapi/hash.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,20 @@ hash_pointer(PyObject *Py_UNUSED(module), PyObject *arg)
5959
}
6060

6161

62+
static PyObject *
63+
object_generichash(PyObject *Py_UNUSED(module), PyObject *arg)
64+
{
65+
NULLABLE(arg);
66+
Py_hash_t hash = PyObject_GenericHash(arg);
67+
Py_BUILD_ASSERT(sizeof(long long) >= sizeof(hash));
68+
return PyLong_FromLongLong(hash);
69+
}
70+
71+
6272
static PyMethodDef test_methods[] = {
6373
{"hash_getfuncdef", hash_getfuncdef, METH_NOARGS},
64 EDC1 74
{"hash_pointer", hash_pointer, METH_O},
75+
{"object_generichash", object_generichash, METH_O},
6576
{NULL},
6677
};
6778

Objects/classobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ static Py_hash_t
301301
method_hash(PyMethodObject *a)
302302
{
303303
Py_hash_t x, y;
304-
x = _Py_HashPointer(a->im_self);
304+
x = PyObject_GenericHash(a->im_self);
305305
y = PyObject_Hash(a->im_func);
306306
if (y == -1)
307307
return -1;

Objects/descrobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ static Py_hash_t
13111311
wrapper_hash(wrapperobject *wp)
13121312
{
13131313
Py_hash_t x, y;
1314-
x = _Py_HashPointer(wp->self);
1314+
x = PyObject_GenericHash(wp->self);
13151315
y = _Py_HashPointer(wp->descr);
13161316
x = x ^ y;
13171317
if (x == -1)

0 commit comments

Comments
 (0)
0