From d5589fea42eb99105ab0f83de5e0382659f21103 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Tue, 22 Apr 2025 13:20:48 +0200 Subject: [PATCH 1/5] add `Py_HashBuffer` to `pyo3-ffi` --- newsfragments/5086.added.md | 1 + pyo3-ffi/src/compat/mod.rs | 2 ++ pyo3-ffi/src/compat/py_3_14.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 newsfragments/5086.added.md create mode 100644 pyo3-ffi/src/compat/py_3_14.rs diff --git a/newsfragments/5086.added.md b/newsfragments/5086.added.md new file mode 100644 index 00000000000..9e8394e95c5 --- /dev/null +++ b/newsfragments/5086.added.md @@ -0,0 +1 @@ +add `Py_HashBuffer` to `pyo3-ffi` diff --git a/pyo3-ffi/src/compat/mod.rs b/pyo3-ffi/src/compat/mod.rs index 11f2912848e..044ea46762b 100644 --- a/pyo3-ffi/src/compat/mod.rs +++ b/pyo3-ffi/src/compat/mod.rs @@ -52,8 +52,10 @@ macro_rules! compat_function { mod py_3_10; mod py_3_13; +mod py_3_14; mod py_3_9; pub use self::py_3_10::*; pub use self::py_3_13::*; +pub use self::py_3_14::*; pub use self::py_3_9::*; diff --git a/pyo3-ffi/src/compat/py_3_14.rs b/pyo3-ffi/src/compat/py_3_14.rs new file mode 100644 index 00000000000..d8dab5a4c69 --- /dev/null +++ b/pyo3-ffi/src/compat/py_3_14.rs @@ -0,0 +1,26 @@ +compat_function!( + originally_defined_for(Py_3_14); + + #[inline] + pub unsafe fn Py_HashBuffer( + ptr: *const std::ffi::c_void, + len: crate::Py_ssize_t, + ) -> crate::Py_hash_t { + #[cfg(not(any(Py_LIMITED_API, PyPy)))] + { + crate::_Py_HashBytes(ptr, len) + } + + #[cfg(any(Py_LIMITED_API, PyPy))] + { + let bytes = crate::PyBytes_FromStringAndSize(ptr as *const std::os::raw::c_char, len); + if bytes.is_null() { + -1 + } else { + let result = crate::PyObject_Hash(bytes); + crate::Py_DECREF(bytes); + result + } + } + } +); From 595be1a04692046513879f2c6a1ac52a97dcab4d Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Wed, 23 Apr 2025 09:19:52 +0200 Subject: [PATCH 2/5] Add `Py_HashBuffer` binding when 3.14+ --- pyo3-ffi/src/pyhash.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyo3-ffi/src/pyhash.rs b/pyo3-ffi/src/pyhash.rs index 4f14e04a695..fdfabe0c753 100644 --- a/pyo3-ffi/src/pyhash.rs +++ b/pyo3-ffi/src/pyhash.rs @@ -14,6 +14,9 @@ extern "C" { #[cfg(not(any(Py_LIMITED_API, PyPy)))] pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t; + + #[cfg(Py_3_14)] + pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t; } pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; From ff3039c94e1ea5310e80959d76c93e123c4b2d1a Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Fri, 25 Apr 2025 10:48:15 +0200 Subject: [PATCH 3/5] Move to `cpython/pyhash.rs` --- pyo3-ffi/src/cpython/mod.rs | 2 ++ pyo3-ffi/src/cpython/pyhash.rs | 30 ++++++++++++++++++++++++++++++ pyo3-ffi/src/pyhash.rs | 28 ---------------------------- 3 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 pyo3-ffi/src/cpython/pyhash.rs diff --git a/pyo3-ffi/src/cpython/mod.rs b/pyo3-ffi/src/cpython/mod.rs index f09d51d0e4e..373e4b034b9 100644 --- a/pyo3-ffi/src/cpython/mod.rs +++ b/pyo3-ffi/src/cpython/mod.rs @@ -38,6 +38,7 @@ pub(crate) mod pythonrun; // skipped sysmodule.h pub(crate) mod floatobject; pub(crate) mod pyframe; +pub(crate) mod pyhash; pub(crate) mod tupleobject; pub(crate) mod unicodeobject; pub(crate) mod weakrefobject; @@ -73,6 +74,7 @@ pub use self::pydebug::*; pub use self::pyerrors::*; #[cfg(all(Py_3_11, not(PyPy)))] pub use self::pyframe::*; +pub use self::pyhash::*; #[cfg(all(Py_3_8, not(PyPy)))] pub use self::pylifecycle::*; pub use self::pymem::*; diff --git a/pyo3-ffi/src/cpython/pyhash.rs b/pyo3-ffi/src/cpython/pyhash.rs new file mode 100644 index 00000000000..f0807eca7fa --- /dev/null +++ b/pyo3-ffi/src/cpython/pyhash.rs @@ -0,0 +1,30 @@ +#[cfg(Py_3_13)] +use crate::PyObject; +use crate::{Py_hash_t, Py_ssize_t}; +use std::os::raw::{c_char, c_int, c_void}; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyHash_FuncDef { + pub hash: Option Py_hash_t>, + pub name: *const c_char, + pub hash_bits: c_int, + pub seed_bits: c_int, +} + +impl Default for PyHash_FuncDef { + #[inline] + fn default() -> Self { + unsafe { std::mem::zeroed() } + } +} + +extern "C" { + pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef; + #[cfg(Py_3_13)] + pub fn Py_HashPointer(ptr: *const c_void) -> Py_hash_t; + #[cfg(Py_3_13)] + pub fn PyObject_GenericHash(obj: *mut PyObject) -> Py_hash_t; + #[cfg(Py_3_14)] + pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t; +} diff --git a/pyo3-ffi/src/pyhash.rs b/pyo3-ffi/src/pyhash.rs index fdfabe0c753..074278ddf3c 100644 --- a/pyo3-ffi/src/pyhash.rs +++ b/pyo3-ffi/src/pyhash.rs @@ -1,7 +1,5 @@ #[cfg(not(any(Py_LIMITED_API, PyPy)))] use crate::pyport::{Py_hash_t, Py_ssize_t}; -#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] -use std::os::raw::c_char; #[cfg(not(any(Py_LIMITED_API, PyPy)))] use std::os::raw::c_void; @@ -14,9 +12,6 @@ extern "C" { #[cfg(not(any(Py_LIMITED_API, PyPy)))] pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t; - - #[cfg(Py_3_14)] - pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t; } pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; @@ -25,29 +20,6 @@ pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; // skipped non-limited _Py_HashSecret_t -#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct PyHash_FuncDef { - pub hash: Option Py_hash_t>, - pub name: *const c_char, - pub hash_bits: c_int, - pub seed_bits: c_int, -} - -#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] -impl Default for PyHash_FuncDef { - #[inline] - fn default() -> Self { - unsafe { std::mem::zeroed() } - } -} - -extern "C" { - #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] - pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef; -} - // skipped Py_HASH_CUTOFF pub const Py_HASH_EXTERNAL: c_int = 0; From dc4a817be241bef15b15b986acc37caf2b4ca7fb Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Fri, 25 Apr 2025 11:38:49 +0200 Subject: [PATCH 4/5] Update changelog --- newsfragments/5086.added.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/newsfragments/5086.added.md b/newsfragments/5086.added.md index 9e8394e95c5..b79e62d77fc 100644 --- a/newsfragments/5086.added.md +++ b/newsfragments/5086.added.md @@ -1 +1,3 @@ -add `Py_HashBuffer` to `pyo3-ffi` +- add `Py_HashBuffer` to `pyo3-ffi` +- add `Py_HashPointer` to `pyo3-ffi` +- add `PyObject_GenericHash` to `pyo3-ffi` From a4d88a6f90ec9cd5cbcacae24f4a4882b16738c3 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Mon, 28 Apr 2025 10:15:59 +0200 Subject: [PATCH 5/5] Enable`Py_HashBuffer` compat on 3.14 abi3 --- pyo3-ffi/src/compat/py_3_14.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyo3-ffi/src/compat/py_3_14.rs b/pyo3-ffi/src/compat/py_3_14.rs index d8dab5a4c69..6fdaef17488 100644 --- a/pyo3-ffi/src/compat/py_3_14.rs +++ b/pyo3-ffi/src/compat/py_3_14.rs @@ -1,5 +1,5 @@ compat_function!( - originally_defined_for(Py_3_14); + originally_defined_for(all(Py_3_14, not(Py_LIMITED_API))); #[inline] pub unsafe fn Py_HashBuffer(