diff --git a/docs/api.rst b/docs/api.rst index d817bc3..d79eb87 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -10,7 +10,7 @@ Supported Python versions: * Python 3.6 - 3.14 * PyPy 2.7 and PyPy 3.6 - 3.10 -Python 2.7 and Python 3.4 are no longer officially supported since GitHub +Python 2.7 and Python 3.5 are no longer officially supported since GitHub Actions doesn't support them anymore: only best effort support is provided. C++03 and C++11 are supported on Python 3.6 and newer. @@ -37,6 +37,10 @@ Python 3.14 See `PyBytes_Join() documentation `__. +.. c:function:: Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) + + See `Py_HashBuffer() documentation `__. + .. c:function:: int PyUnicode_Equal(PyObject *str1, PyObject *str2) See `PyUnicode_Equal() documentation `__. @@ -83,7 +87,34 @@ Python 3.14 Not supported: +* ``PyConfig_Get()`` +* ``PyConfig_GetInt()`` +* ``PyConfig_Names()`` +* ``PyConfig_Set()`` +* ``PyInitConfig_AddModule()`` +* ``PyInitConfig_Create()`` +* ``PyInitConfig_Free()`` +* ``PyInitConfig_FreeStrList()`` +* ``PyInitConfig_GetError()`` +* ``PyInitConfig_GetExitCode()`` +* ``PyInitConfig_GetInt()`` +* ``PyInitConfig_GetStr()`` +* ``PyInitConfig_GetStrList()`` +* ``PyInitConfig_HasOption()`` +* ``PyInitConfig_SetInt()`` +* ``PyInitConfig_SetStr()`` +* ``PyInitConfig_SetStrList()`` +* ``PyLong_AsInt32()`` +* ``PyLong_AsInt64()`` +* ``PyLong_AsUInt32()`` +* ``PyLong_AsUInt64()`` +* ``PyLong_FromInt32()`` +* ``PyLong_FromInt64()`` +* ``PyLong_FromUInt32()`` +* ``PyLong_FromUInt64()`` +* ``PyType_GetBaseByToken()`` * ``PyUnicodeWriter_DecodeUTF8Stateful()`` +* ``Py_InitializeFromInitConfig()`` Python 3.13 diff --git a/docs/changelog.rst b/docs/changelog.rst index 18121ab..157a08b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog * ``PyBytes_Join()`` * ``PyUnicode_Equal()`` + * ``Py_HashBuffer()`` * 2024-07-18: Add functions: diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index 02df115..dfd65a2 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -1555,6 +1555,27 @@ static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) #endif +#if PY_VERSION_HEX < 0x030E00A0 +static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) +{ +#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) + extern Py_hash_t _Py_HashBytes(const void *src, Py_ssize_t len); + + return _Py_HashBytes(ptr, len); +#else + Py_hash_t hash; + PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len); + if (bytes == NULL) { + return -1; + } + hash = PyObject_Hash(bytes); + Py_DECREF(bytes); + return hash; +#endif +} +#endif + + #ifdef __cplusplus } #endif diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index e5f7d2f..2d8db5c 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -1618,6 +1618,20 @@ test_hash(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(imag != 0); #endif + // Test Py_HashBuffer() + { + PyObject *abc = PyBytes_FromString("abc"); + if (abc == NULL) { + return NULL; + } + Py_hash_t hash = Py_HashBuffer(PyBytes_AS_STRING(abc), + PyBytes_GET_SIZE(abc)); + Py_hash_t hash2 = PyObject_Hash(abc); + assert(hash == hash2); + + Py_DECREF(abc); + } + Py_RETURN_NONE; } @@ -1884,6 +1898,7 @@ test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) static PyObject * test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { + // Test PyBytes_Join() PyObject *abc = PyBytes_FromString("a b c"); if (abc == NULL) { return NULL;