remove internal APIs from pyo3-ffi (#4201)

* remove internal APIs from pyo3-ffi

* fix formating

* add conditional import

* remove _Py_c_neg/abs/pow

* fix formating

* adding changelog

* expose PyAnyMethods::neg/pos/abs and use them

* Update src/types/any.rs

Co-authored-by: David Hewitt <mail@davidhewitt.dev>

* Update src/types/any.rs

Co-authored-by: David Hewitt <mail@davidhewitt.dev>

* Adding details to changelog

* update docs

* remove PyREsultExt import for GraalPy

---------

Co-authored-by: David Hewitt <mail@davidhewitt.dev>
This commit is contained in:
Cheuk Ting Ho 2024-06-05 22:21:44 +01:00 committed by GitHub
parent 93ef056711
commit 37a5f6a94e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 42 deletions

View File

@ -0,0 +1 @@
Remove CPython internal ffi call for complex number including: add, sub, mul, div, neg, abs, pow. Added PyAnyMethods::{abs, pos, neg}

View File

@ -1127,6 +1127,21 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
where where
O: ToPyObject; O: ToPyObject;
/// Computes the negative of self.
///
/// Equivalent to the Python expression `-self`.
fn neg(&self) -> PyResult<Bound<'py, PyAny>>;
/// Computes the positive of self.
///
/// Equivalent to the Python expression `+self`.
fn pos(&self) -> PyResult<Bound<'py, PyAny>>;
/// Computes the absolute of self.
///
/// Equivalent to the Python expression `abs(self)`.
fn abs(&self) -> PyResult<Bound<'py, PyAny>>;
/// Tests whether this object is less than another. /// Tests whether this object is less than another.
/// ///
/// This is equivalent to the Python expression `self < other`. /// This is equivalent to the Python expression `self < other`.
@ -1862,6 +1877,26 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
inner(self, other.to_object(py).into_bound(py), compare_op) inner(self, other.to_object(py).into_bound(py), compare_op)
} }
fn neg(&self) -> PyResult<Bound<'py, PyAny>> {
unsafe { ffi::PyNumber_Negative(self.as_ptr()).assume_owned_or_err(self.py()) }
}
fn pos(&self) -> PyResult<Bound<'py, PyAny>> {
fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {
unsafe { ffi::PyNumber_Positive(any.as_ptr()).assume_owned_or_err(any.py()) }
}
inner(self)
}
fn abs(&self) -> PyResult<Bound<'py, PyAny>> {
fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {
unsafe { ffi::PyNumber_Absolute(any.as_ptr()).assume_owned_or_err(any.py()) }
}
inner(self)
}
fn lt<O>(&self, other: O) -> PyResult<bool> fn lt<O>(&self, other: O) -> PyResult<bool>
where where
O: ToPyObject, O: ToPyObject,

View File

@ -1,3 +1,5 @@
#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
use crate::py_result_ext::PyResultExt;
#[cfg(feature = "gil-refs")] #[cfg(feature = "gil-refs")]
use crate::PyNativeType; use crate::PyNativeType;
use crate::{ffi, types::any::PyAnyMethods, Bound, PyAny, Python}; use crate::{ffi, types::any::PyAnyMethods, Bound, PyAny, Python};
@ -59,7 +61,6 @@ impl PyComplex {
#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
mod not_limited_impls { mod not_limited_impls {
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::Borrowed; use crate::Borrowed;
use super::*; use super::*;
@ -77,27 +78,17 @@ mod not_limited_impls {
} }
} }
#[inline(always)]
pub(super) unsafe fn complex_operation<'py>(
l: Borrowed<'_, 'py, PyComplex>,
r: Borrowed<'_, 'py, PyComplex>,
operation: unsafe extern "C" fn(ffi::Py_complex, ffi::Py_complex) -> ffi::Py_complex,
) -> *mut ffi::PyObject {
let l_val = (*l.as_ptr().cast::<ffi::PyComplexObject>()).cval;
let r_val = (*r.as_ptr().cast::<ffi::PyComplexObject>()).cval;
ffi::PyComplex_FromCComplex(operation(l_val, r_val))
}
macro_rules! bin_ops { macro_rules! bin_ops {
($trait:ident, $fn:ident, $op:tt, $ffi:path) => { ($trait:ident, $fn:ident, $op:tt) => {
impl<'py> $trait for Borrowed<'_, 'py, PyComplex> { impl<'py> $trait for Borrowed<'_, 'py, PyComplex> {
type Output = Bound<'py, PyComplex>; type Output = Bound<'py, PyComplex>;
fn $fn(self, other: Self) -> Self::Output { fn $fn(self, other: Self) -> Self::Output {
unsafe { PyAnyMethods::$fn(self.as_any(), other)
complex_operation(self, other, $ffi) .downcast_into().expect(
.assume_owned(self.py()) concat!("Complex method ",
.downcast_into_unchecked() stringify!($fn),
} " failed.")
)
} }
} }
@ -139,10 +130,10 @@ mod not_limited_impls {
}; };
} }
bin_ops!(Add, add, +, ffi::_Py_c_sum); bin_ops!(Add, add, +);
bin_ops!(Sub, sub, -, ffi::_Py_c_diff); bin_ops!(Sub, sub, -);
bin_ops!(Mul, mul, *, ffi::_Py_c_prod); bin_ops!(Mul, mul, *);
bin_ops!(Div, div, /, ffi::_Py_c_quot); bin_ops!(Div, div, /);
#[cfg(feature = "gil-refs")] #[cfg(feature = "gil-refs")]
impl<'py> Neg for &'py PyComplex { impl<'py> Neg for &'py PyComplex {
@ -155,12 +146,9 @@ mod not_limited_impls {
impl<'py> Neg for Borrowed<'_, 'py, PyComplex> { impl<'py> Neg for Borrowed<'_, 'py, PyComplex> {
type Output = Bound<'py, PyComplex>; type Output = Bound<'py, PyComplex>;
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
unsafe { PyAnyMethods::neg(self.as_any())
let val = (*self.as_ptr().cast::<ffi::PyComplexObject>()).cval; .downcast_into()
ffi::PyComplex_FromCComplex(ffi::_Py_c_neg(val)) .expect("Complex method __neg__ failed.")
.assume_owned(self.py())
.downcast_into_unchecked()
}
} }
} }
@ -289,24 +277,20 @@ impl<'py> PyComplexMethods<'py> for Bound<'py, PyComplex> {
#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
fn abs(&self) -> c_double { fn abs(&self) -> c_double {
unsafe { PyAnyMethods::abs(self.as_any())
let val = (*self.as_ptr().cast::<ffi::PyComplexObject>()).cval; .downcast_into()
ffi::_Py_c_abs(val) .expect("Complex method __abs__ failed.")
} .extract()
.expect("Failed to extract to c double.")
} }
#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {
use crate::ffi_ptr_ext::FfiPtrExt; Python::with_gil(|py| {
unsafe { PyAnyMethods::pow(self.as_any(), other, py.None())
not_limited_impls::complex_operation( .downcast_into()
self.as_borrowed(), .expect("Complex method __pow__ failed.")
other.as_borrowed(), })
ffi::_Py_c_pow,
)
.assume_owned(self.py())
.downcast_into_unchecked()
}
} }
} }