diff --git a/newsfragments/4461.added.md b/newsfragments/4461.added.md new file mode 100644 index 00000000000..c151664c843 --- /dev/null +++ b/newsfragments/4461.added.md @@ -0,0 +1 @@ +Add FFI definitions `compat::PyObject_CallNoArgs` and `compat::PyObject_CallMethodNoArgs`. diff --git a/pyo3-ffi/src/compat/mod.rs b/pyo3-ffi/src/compat/mod.rs index db41c834b3d..11f2912848e 100644 --- a/pyo3-ffi/src/compat/mod.rs +++ b/pyo3-ffi/src/compat/mod.rs @@ -52,6 +52,8 @@ macro_rules! compat_function { mod py_3_10; mod py_3_13; +mod py_3_9; pub use self::py_3_10::*; pub use self::py_3_13::*; +pub use self::py_3_9::*; diff --git a/pyo3-ffi/src/compat/py_3_9.rs b/pyo3-ffi/src/compat/py_3_9.rs new file mode 100644 index 00000000000..285f2b2ae7e --- /dev/null +++ b/pyo3-ffi/src/compat/py_3_9.rs @@ -0,0 +1,21 @@ +compat_function!( + originally_defined_for(all( + not(PyPy), + not(GraalPy), + any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10 + )); + + #[inline] + pub unsafe fn PyObject_CallNoArgs(obj: *mut crate::PyObject) -> *mut crate::PyObject { + crate::PyObject_CallObject(obj, std::ptr::null_mut()) + } +); + +compat_function!( + originally_defined_for(all(Py_3_9, not(any(Py_LIMITED_API, PyPy, GraalPy)))); + + #[inline] + pub unsafe fn PyObject_CallMethodNoArgs(obj: *mut crate::PyObject, name: *mut crate::PyObject) -> *mut crate::PyObject { + crate::PyObject_CallMethodObjArgs(obj, name, std::ptr::null_mut::()) + } +); diff --git a/src/types/any.rs b/src/types/any.rs index e7c7c578e3e..6dff9a1264d 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -1180,20 +1180,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { } fn call0(&self) -> PyResult> { - cfg_if::cfg_if! { - if #[cfg(all( - not(PyPy), - not(GraalPy), - any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // PyObject_CallNoArgs was added to python in 3.9 but to limited API in 3.10 - ))] { - // Optimized path on python 3.9+ - unsafe { - ffi::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) - } - } else { - self.call((), None) - } - } + unsafe { ffi::compat::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) } } fn call1(&self, args: impl IntoPy>) -> PyResult> { @@ -1218,18 +1205,11 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { where N: IntoPy>, { - cfg_if::cfg_if! { - if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy, GraalPy))))] { - let py = self.py(); - - // Optimized path on python 3.9+ - unsafe { - let name = name.into_py(py).into_bound(py); - ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()).assume_owned_or_err(py) - } - } else { - self.call_method(name, (), None) - } + let py = self.py(); + let name = name.into_py(py).into_bound(py); + unsafe { + ffi::compat::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()) + .assume_owned_or_err(py) } }