mirror of https://github.com/python/cpython
gh-111545: Test PyHash_GetFuncDef() function (#112098)
Add Modules/_testcapi/hash.c and Lib/test/test_capi/test_hash.py.
This commit is contained in:
parent
e0f5127975
commit
55f3cce821
|
@ -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
|
|
@ -17,6 +17,7 @@ and parsing function arguments and constructing Python values from C values.
|
||||||
marshal.rst
|
marshal.rst
|
||||||
arg.rst
|
arg.rst
|
||||||
conversion.rst
|
conversion.rst
|
||||||
|
hash.rst
|
||||||
reflection.rst
|
reflection.rst
|
||||||
codec.rst
|
codec.rst
|
||||||
perfmaps.rst
|
perfmaps.rst
|
||||||
|
|
|
@ -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)
|
|
@ -159,7 +159,7 @@
|
||||||
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
|
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
|
||||||
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.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__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_TRUE@_testclinic _testclinic.c
|
||||||
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
|
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -58,6 +58,7 @@ int _PyTestCapi_Init_Codec(PyObject *module);
|
||||||
int _PyTestCapi_Init_Immortal(PyObject *module);
|
int _PyTestCapi_Init_Immortal(PyObject *module);
|
||||||
int _PyTestCapi_Init_GC(PyObject *module);
|
int _PyTestCapi_Init_GC(PyObject *module);
|
||||||
int _PyTestCapi_Init_Sys(PyObject *module);
|
int _PyTestCapi_Init_Sys(PyObject *module);
|
||||||
|
int _PyTestCapi_Init_Hash(PyObject *module);
|
||||||
|
|
||||||
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
|
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
|
||||||
int _PyTestCapi_Init_HeaptypeRelative(PyObject *module);
|
int _PyTestCapi_Init_HeaptypeRelative(PyObject *module);
|
||||||
|
|
|
@ -3995,6 +3995,9 @@ PyInit__testcapi(void)
|
||||||
if (_PyTestCapi_Init_HeaptypeRelative(m) < 0) {
|
if (_PyTestCapi_Init_HeaptypeRelative(m) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (_PyTestCapi_Init_Hash(m) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
PyState_AddModule(m, &_testcapimodule);
|
PyState_AddModule(m, &_testcapimodule);
|
||||||
return m;
|
return m;
|
||||||
|
|
|
@ -124,6 +124,7 @@
|
||||||
<ClCompile Include="..\Modules\_testcapi\file.c" />
|
<ClCompile Include="..\Modules\_testcapi\file.c" />
|
||||||
<ClCompile Include="..\Modules\_testcapi\codec.c" />
|
<ClCompile Include="..\Modules\_testcapi\codec.c" />
|
||||||
<ClCompile Include="..\Modules\_testcapi\sys.c" />
|
<ClCompile Include="..\Modules\_testcapi\sys.c" />
|
||||||
|
<ClCompile Include="..\Modules\_testcapi\hash.c" />
|
||||||
<ClCompile Include="..\Modules\_testcapi\immortal.c" />
|
<ClCompile Include="..\Modules\_testcapi\immortal.c" />
|
||||||
<ClCompile Include="..\Modules\_testcapi\gc.c" />
|
<ClCompile Include="..\Modules\_testcapi\gc.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -102,6 +102,9 @@
|
||||||
<ClCompile Include="..\Modules\_testcapi\sys.c">
|
<ClCompile Include="..\Modules\_testcapi\sys.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Modules\_testcapi\hash.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\Modules\_testcapi\gc.c">
|
<ClCompile Include="..\Modules\_testcapi\gc.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
Loading…
Reference in New Issue