]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111545: Test PyHash_GetFuncDef() function (#112098)
authorVictor Stinner <vstinner@python.org>
Wed, 15 Nov 2023 02:41:29 +0000 (03:41 +0100)
committerGitHub <noreply@github.com>
Wed, 15 Nov 2023 02:41:29 +0000 (03:41 +0100)
Add Modules/_testcapi/hash.c and Lib/test/test_capi/test_hash.py.

Doc/c-api/hash.rst [new file with mode: 0644]
Doc/c-api/utilities.rst
Lib/test/test_capi/test_hash.py [new file with mode: 0644]
Modules/Setup.stdlib.in
Modules/_testcapi/hash.c [new file with mode: 0644]
Modules/_testcapi/parts.h
Modules/_testcapimodule.c
PCbuild/_testcapi.vcxproj
PCbuild/_testcapi.vcxproj.filters

diff --git a/Doc/c-api/hash.rst b/Doc/c-api/hash.rst
new file mode 100644 (file)
index 0000000..4dc121d
--- /dev/null
@@ -0,0 +1,48 @@
+.. highlight:: c
+
+PyHash API
+----------
+
+See also the :c:member:`PyTypeObject.tp_hash` member.
+
+.. c:type:: Py_hash_t
+
+   Hash value type: signed integer.
+
+   .. versionadded:: 3.2
+
+.. c:type:: Py_uhash_t
+
+   Hash value type: unsigned integer.
+
+   .. versionadded:: 3.2
+
+
+.. c:type:: PyHash_FuncDef
+
+   Hash function definition used by :c:func:`PyHash_GetFuncDef`.
+
+   .. c::member:: Py_hash_t (*const hash)(const void *, Py_ssize_t)
+
+      Hash function.
+
+   .. c:member:: const char *name
+
+      Hash function name (UTF-8 encoded string).
+
+   .. c:member:: const int hash_bits
+
+      Internal size of the hash value in bits.
+
+   .. c:member:: const int seed_bits
+
+      Size of seed input in bits.
+
+   .. versionadded:: 3.4
+
+
+.. c:function:: PyHash_FuncDef* PyHash_GetFuncDef(void)
+
+   Get the hash function definition.
+
+   .. versionadded:: 3.4
index ccbf14e1850f6875ed52a8b54c24fdf41f982f86..48ae54acebe887930d24ef9be7d821c6a880350b 100644 (file)
@@ -17,6 +17,7 @@ and parsing function arguments and constructing Python values from C values.
    marshal.rst
    arg.rst
    conversion.rst
+   hash.rst
    reflection.rst
    codec.rst
    perfmaps.rst
diff --git a/Lib/test/test_capi/test_hash.py b/Lib/test/test_capi/test_hash.py
new file mode 100644 (file)
index 0000000..59dec15
--- /dev/null
@@ -0,0 +1,33 @@
+import sys
+import unittest
+from test.support import import_helper
+_testcapi = import_helper.import_module('_testcapi')
+
+
+SIZEOF_PY_HASH_T = _testcapi.SIZEOF_VOID_P
+
+
+class CAPITest(unittest.TestCase):
+    def test_hash_getfuncdef(self):
+        # Test PyHash_GetFuncDef()
+        hash_getfuncdef = _testcapi.hash_getfuncdef
+        func_def = hash_getfuncdef()
+
+        match func_def.name:
+            case "fnv":
+                self.assertEqual(func_def.hash_bits, 8 * SIZEOF_PY_HASH_T)
+                self.assertEqual(func_def.seed_bits, 16 * SIZEOF_PY_HASH_T)
+            case "siphash13":
+                self.assertEqual(func_def.hash_bits, 64)
+                self.assertEqual(func_def.seed_bits, 128)
+            case "siphash24":
+                self.assertEqual(func_def.hash_bits, 64)
+                self.assertEqual(func_def.seed_bits, 128)
+            case _:
+                self.fail(f"unknown function name: {func_def.name!r}")
+
+        # compare with sys.hash_info
+        hash_info = sys.hash_info
+        self.assertEqual(func_def.name, hash_info.algorithm)
+        self.assertEqual(func_def.hash_bits, hash_info.hash_bits)
+        self.assertEqual(func_def.seed_bits, hash_info.seed_bits)
index d144ad312ef5604d63a2e92ac21f47c1b9676471..54650ea9c1d4ac11f8f0d346dcabf6fda7c22a06 100644 (file)
 @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
 @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
 @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/hash.c
 @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
 @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
 
diff --git a/Modules/_testcapi/hash.c b/Modules/_testcapi/hash.c
new file mode 100644 (file)
index 0000000..d0b8127
--- /dev/null
@@ -0,0 +1,56 @@
+#include "parts.h"
+#include "util.h"
+
+static PyObject *
+hash_getfuncdef(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+    // bind PyHash_GetFuncDef()
+    PyHash_FuncDef *def = PyHash_GetFuncDef();
+
+    PyObject *types = PyImport_ImportModule("types");
+    if (types == NULL) {
+        return NULL;
+    }
+
+    PyObject *result = PyObject_CallMethod(types, "SimpleNamespace", NULL);
+    Py_DECREF(types);
+    if (result == NULL) {
+        return NULL;
+    }
+
+    // ignore PyHash_FuncDef.hash
+
+    PyObject *value = PyUnicode_FromString(def->name);
+    int res = PyObject_SetAttrString(result, "name", value);
+    Py_DECREF(value);
+    if (res < 0) {
+        return NULL;
+    }
+
+    value = PyLong_FromLong(def->hash_bits);
+    res = PyObject_SetAttrString(result, "hash_bits", value);
+    Py_DECREF(value);
+    if (res < 0) {
+        return NULL;
+    }
+
+    value = PyLong_FromLong(def->seed_bits);
+    res = PyObject_SetAttrString(result, "seed_bits", value);
+    Py_DECREF(value);
+    if (res < 0) {
+        return NULL;
+    }
+
+    return result;
+}
+
+static PyMethodDef test_methods[] = {
+    {"hash_getfuncdef", hash_getfuncdef, METH_NOARGS},
+    {NULL},
+};
+
+int
+_PyTestCapi_Init_Hash(PyObject *m)
+{
+    return PyModule_AddFunctions(m, test_methods);
+}
index 9af414e10d01604d2434ba6f28e259c493b5b923..29817edd69b134876ddc250e7444e8c196e66ce4 100644 (file)
@@ -58,6 +58,7 @@ int _PyTestCapi_Init_Codec(PyObject *module);
 int _PyTestCapi_Init_Immortal(PyObject *module);
 int _PyTestCapi_Init_GC(PyObject *module);
 int _PyTestCapi_Init_Sys(PyObject *module);
+int _PyTestCapi_Init_Hash(PyObject *module);
 
 int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
 int _PyTestCapi_Init_HeaptypeRelative(PyObject *module);
index 300025ce3705fe8c3035b6f5c1d4ff5fcda7b59c..999bd866f148144e662a2c6a0c306067bf608379 100644 (file)
@@ -3995,6 +3995,9 @@ PyInit__testcapi(void)
     if (_PyTestCapi_Init_HeaptypeRelative(m) < 0) {
         return NULL;
     }
+    if (_PyTestCapi_Init_Hash(m) < 0) {
+        return NULL;
+    }
 
     PyState_AddModule(m, &_testcapimodule);
     return m;
index 2d8a652a84b92d2571c60114f49ef0b6287110fe..1c15541d3ec735fd5eb827a1cee5daef402b1e6f 100644 (file)
     <ClCompile Include="..\Modules\_testcapi\file.c" />
     <ClCompile Include="..\Modules\_testcapi\codec.c" />
     <ClCompile Include="..\Modules\_testcapi\sys.c" />
+    <ClCompile Include="..\Modules\_testcapi\hash.c" />
     <ClCompile Include="..\Modules\_testcapi\immortal.c" />
     <ClCompile Include="..\Modules\_testcapi\gc.c" />
   </ItemGroup>
index 573e54d56a2020adc0f7928bbabe2af075c708e7..6059959bb9a040f393f3e07d8736cd42434082bb 100644 (file)
     <ClCompile Include="..\Modules\_testcapi\sys.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_testcapi\hash.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\_testcapi\gc.c">
       <Filter>Source Files</Filter>
     </ClCompile>