From 01fafa5b9e1de0f1ab2a9d108cd0fce20ab9568f Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 24 May 2024 12:17:54 +0200 Subject: [PATCH] added nb::hash wrapper --- docs/api_core.rst | 6 ++++++ include/nanobind/nb_misc.h | 7 +++++++ tests/test_functions.cpp | 2 ++ tests/test_functions.py | 4 ++++ tests/test_functions_ext.pyi.ref | 2 ++ 5 files changed, 21 insertions(+) diff --git a/docs/api_core.rst b/docs/api_core.rst index a61b0571..b4765ead 100644 --- a/docs/api_core.rst +++ b/docs/api_core.rst @@ -2744,6 +2744,12 @@ Miscellaneous Return the ``globals()`` dictionary. +.. cpp:function:: Py_hash_t hash(handle h) + + Hash the given argument like ``hash()`` in pure Python. The type of the + return value (``Py_hash_t``) is an implementation-specific signed integer + type. + .. cpp:function:: template void implicitly_convertible() Indicate that the type `Source` is implicitly convertible into `Target` diff --git a/include/nanobind/nb_misc.h b/include/nanobind/nb_misc.h index 3020f224..6f7cfb77 100644 --- a/include/nanobind/nb_misc.h +++ b/include/nanobind/nb_misc.h @@ -46,6 +46,13 @@ inline dict globals() { return borrow(p); } +inline Py_hash_t hash(handle h) { + Py_hash_t rv = PyObject_Hash(h.ptr()); + if (rv == -1 && PyErr_Occurred()) + nanobind::raise_python_error(); + return rv; +} + inline bool is_alive() noexcept { return detail::is_alive(); } diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index b62e1e0d..d11ad7e3 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -359,4 +359,6 @@ NB_MODULE(test_functions_ext, m) { return b; }); + + m.def("hash_it", [](nb::handle h) { return nb::hash(h); }); } diff --git a/tests/test_functions.py b/tests/test_functions.py index e8b8e099..f335e614 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -591,3 +591,7 @@ def test43_wrappers_dict(): def test43_wrappers_set(): assert t.test_wrappers_set() + +def test44_hash(): + value = (1, 2, 3) + assert t.hash_it(value) == hash(value); diff --git a/tests/test_functions_ext.pyi.ref b/tests/test_functions_ext.pyi.ref index 5bb16ecc..45a6701d 100644 --- a/tests/test_functions_ext.pyi.ref +++ b/tests/test_functions_ext.pyi.ref @@ -5,6 +5,8 @@ from typing import Annotated, Any, overload def call_guard_value() -> int: ... +def hash_it(arg: object, /) -> int: ... + def identity_i16(arg: int, /) -> int: ... def identity_i32(arg: int, /) -> int: ...