Skip to content

Commit

Permalink
update extract_argument to use Bound APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Feb 5, 2024
1 parent 1d1aa0a commit 5591f9b
Show file tree
Hide file tree
Showing 15 changed files with 382 additions and 170 deletions.
4 changes: 2 additions & 2 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,7 @@ impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a
type Holder = ::std::option::Option<pyo3::PyRef<'py, MyClass>>;

#[inline]
fn extract(obj: &'py pyo3::PyAny, holder: &'a mut Self::Holder) -> pyo3::PyResult<Self> {
fn extract(obj: pyo3::impl_::extract_argument::PyArg<'py>, holder: &'a mut Self::Holder) -> pyo3::PyResult<Self> {
pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder)
}
}
Expand All @@ -1233,7 +1233,7 @@ impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a
type Holder = ::std::option::Option<pyo3::PyRefMut<'py, MyClass>>;

#[inline]
fn extract(obj: &'py pyo3::PyAny, holder: &'a mut Self::Holder) -> pyo3::PyResult<Self> {
fn extract(obj: pyo3::impl_::extract_argument::PyArg<'py>, holder: &'a mut Self::Holder) -> pyo3::PyResult<Self> {
pyo3::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder)
}
}
Expand Down
8 changes: 4 additions & 4 deletions pyo3-benches/benches/bench_comparisons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ impl OrderedRichcmp {

fn bench_ordered_dunder_methods(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let obj1 = Py::new(py, OrderedDunderMethods(0)).unwrap().into_ref(py);
let obj2 = Py::new(py, OrderedDunderMethods(1)).unwrap().into_ref(py);
let obj1 = &Bound::new(py, OrderedDunderMethods(0)).unwrap().into_any();
let obj2 = &Bound::new(py, OrderedDunderMethods(1)).unwrap().into_any();

b.iter(|| obj2.gt(obj1).unwrap());
});
}

fn bench_ordered_richcmp(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let obj1 = Py::new(py, OrderedRichcmp(0)).unwrap().into_ref(py);
let obj2 = Py::new(py, OrderedRichcmp(1)).unwrap().into_ref(py);
let obj1 = &Bound::new(py, OrderedRichcmp(0)).unwrap().into_any();
let obj2 = &Bound::new(py, OrderedRichcmp(1)).unwrap().into_any();

b.iter(|| obj2.gt(obj1).unwrap());
});
Expand Down
2 changes: 1 addition & 1 deletion pyo3-macros-backend/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ impl SelfType {
});
error_mode.handle_error(quote_spanned! { *span =>
_pyo3::impl_::extract_argument::#method::<#cls>(
#py.from_borrowed_ptr::<_pyo3::PyAny>(#slf),
_pyo3::impl_::extract_argument::PyArg::from_ptr(#py, #slf),
&mut #holder,
)
})
Expand Down
12 changes: 7 additions & 5 deletions pyo3-macros-backend/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub fn impl_arg_params(
.collect::<Result<_>>()?;
return Ok((
quote! {
let _args = py.from_borrowed_ptr::<_pyo3::types::PyTuple>(_args);
let _kwargs: ::std::option::Option<&_pyo3::types::PyDict> = py.from_borrowed_ptr_or_opt(_kwargs);
let _args = _pyo3::impl_::extract_argument::PyArg::from_ptr(py, _args);
let _kwargs = _pyo3::impl_::extract_argument::PyArg::from_ptr_or_opt(py, _kwargs);
},
arg_convert,
));
Expand Down Expand Up @@ -132,7 +132,7 @@ pub fn impl_arg_params(
keyword_only_parameters: &[#(#keyword_only_parameters),*],
};
let mut #args_array = [::std::option::Option::None; #num_params];
let (_args, _kwargs) = #extract_expression;
let (_args, _kwargs) = &#extract_expression;
},
param_conversion,
))
Expand Down Expand Up @@ -180,7 +180,8 @@ fn impl_arg_param(
let holder = push_holder();
return Ok(quote_arg_span! {
_pyo3::impl_::extract_argument::extract_argument(
_args,
#[allow(clippy::useless_conversion)]
::std::convert::From::from(_args),
&mut #holder,
#name_str
)?
Expand All @@ -193,7 +194,8 @@ fn impl_arg_param(
let holder = push_holder();
return Ok(quote_arg_span! {
_pyo3::impl_::extract_argument::extract_optional_argument(
_kwargs.map(::std::convert::AsRef::as_ref),
#[allow(clippy::useless_conversion, clippy::redundant_closure)]
_kwargs.as_ref().map(|kwargs| ::std::convert::From::from(kwargs)),
&mut #holder,
#name_str,
|| ::std::option::Option::None
Expand Down
6 changes: 3 additions & 3 deletions pyo3-macros-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,7 @@ impl<'a> PyClassImplsBuilder<'a> {
type Holder = ::std::option::Option<_pyo3::PyRef<'py, #cls>>;

#[inline]
fn extract(obj: &'py _pyo3::PyAny, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
fn extract(obj: _pyo3::impl_::extract_argument::PyArg<'py>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
_pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder)
}
}
Expand All @@ -1381,7 +1381,7 @@ impl<'a> PyClassImplsBuilder<'a> {
type Holder = ::std::option::Option<_pyo3::PyRef<'py, #cls>>;

#[inline]
fn extract(obj: &'py _pyo3::PyAny, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
fn extract(obj: _pyo3::impl_::extract_argument::PyArg<'py>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
_pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder)
}
}
Expand All @@ -1391,7 +1391,7 @@ impl<'a> PyClassImplsBuilder<'a> {
type Holder = ::std::option::Option<_pyo3::PyRefMut<'py, #cls>>;

#[inline]
fn extract(obj: &'py _pyo3::PyAny, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
fn extract(obj: _pyo3::impl_::extract_argument::PyArg<'py>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
_pyo3::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder)
}
}
Expand Down
28 changes: 10 additions & 18 deletions pyo3-macros-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,39 +930,31 @@ impl Ty {
extract_error_mode,
holders,
&name_str,
quote! {
py.from_borrowed_ptr::<_pyo3::PyAny>(#ident)
},
quote! { #ident },
),
Ty::MaybeNullObject => extract_object(
extract_error_mode,
holders,
&name_str,
quote! {
py.from_borrowed_ptr::<_pyo3::PyAny>(
if #ident.is_null() {
_pyo3::ffi::Py_None()
} else {
#ident
}
)
if #ident.is_null() {
_pyo3::ffi::Py_None()
} else {
#ident
}
},
),
Ty::NonNullObject => extract_object(
extract_error_mode,
holders,
&name_str,
quote! {
py.from_borrowed_ptr::<_pyo3::PyAny>(#ident.as_ptr())
},
quote! { #ident.as_ptr() },
),
Ty::IPowModulo => extract_object(
extract_error_mode,
holders,
&name_str,
quote! {
#ident.to_borrowed_any(py)
},
quote! { #ident.as_ptr() },
),
Ty::CompareOp => extract_error_mode.handle_error(
quote! {
Expand All @@ -988,7 +980,7 @@ fn extract_object(
extract_error_mode: ExtractErrorMode,
holders: &mut Vec<TokenStream>,
name: &str,
source: TokenStream,
source_ptr: TokenStream,
) -> TokenStream {
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), Span::call_site());
holders.push(quote! {
Expand All @@ -997,7 +989,7 @@ fn extract_object(
});
extract_error_mode.handle_error(quote! {
_pyo3::impl_::extract_argument::extract_argument(
#source,
_pyo3::impl_::extract_argument::PyArg::from_ptr(py, #source_ptr),
&mut #holder,
#name
)
Expand Down
3 changes: 2 additions & 1 deletion pyo3-macros-backend/src/quotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub(crate) fn ok_wrap(obj: TokenStream) -> TokenStream {

pub(crate) fn map_result_into_ptr(result: TokenStream) -> TokenStream {
quote! {
_pyo3::impl_::wrap::map_result_into_ptr(py, #result)
let result = _pyo3::impl_::wrap::map_result_into_ptr(py, #result);
result
}
}
74 changes: 39 additions & 35 deletions pytests/src/pyfunctions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,66 @@ use pyo3::types::{PyDict, PyTuple};
#[pyfunction(signature = ())]
fn none() {}

type Any<'py> = Bound<'py, PyAny>;
type Dict<'py> = Bound<'py, PyDict>;
type Tuple<'py> = Bound<'py, PyTuple>;

#[pyfunction(signature = (a, b = None, *, c = None))]
fn simple<'a>(
a: &'a PyAny,
b: Option<&'a PyAny>,
c: Option<&'a PyAny>,
) -> (&'a PyAny, Option<&'a PyAny>, Option<&'a PyAny>) {
fn simple<'py>(
a: Any<'py>,
b: Option<Any<'py>>,
c: Option<Any<'py>>,
) -> (Any<'py>, Option<Any<'py>>, Option<Any<'py>>) {
(a, b, c)
}

#[pyfunction(signature = (a, b = None, *args, c = None))]
fn simple_args<'a>(
a: &'a PyAny,
b: Option<&'a PyAny>,
args: &'a PyTuple,
c: Option<&'a PyAny>,
) -> (&'a PyAny, Option<&'a PyAny>, &'a PyTuple, Option<&'a PyAny>) {
fn simple_args<'py>(
a: Any<'py>,
b: Option<Any<'py>>,
args: Tuple<'py>,
c: Option<Any<'py>>,
) -> (Any<'py>, Option<Any<'py>>, Tuple<'py>, Option<Any<'py>>) {
(a, b, args, c)
}

#[pyfunction(signature = (a, b = None, c = None, **kwargs))]
fn simple_kwargs<'a>(
a: &'a PyAny,
b: Option<&'a PyAny>,
c: Option<&'a PyAny>,
kwargs: Option<&'a PyDict>,
fn simple_kwargs<'py>(
a: Any<'py>,
b: Option<Any<'py>>,
c: Option<Any<'py>>,
kwargs: Option<Dict<'py>>,
) -> (
&'a PyAny,
Option<&'a PyAny>,
Option<&'a PyAny>,
Option<&'a PyDict>,
Any<'py>,
Option<Any<'py>>,
Option<Any<'py>>,
Option<Dict<'py>>,
) {
(a, b, c, kwargs)
}

#[pyfunction(signature = (a, b = None, *args, c = None, **kwargs))]
fn simple_args_kwargs<'a>(
a: &'a PyAny,
b: Option<&'a PyAny>,
args: &'a PyTuple,
c: Option<&'a PyAny>,
kwargs: Option<&'a PyDict>,
fn simple_args_kwargs<'py>(
a: Any<'py>,
b: Option<Any<'py>>,
args: Tuple<'py>,
c: Option<Any<'py>>,
kwargs: Option<Dict<'py>>,
) -> (
&'a PyAny,
Option<&'a PyAny>,
&'a PyTuple,
Option<&'a PyAny>,
Option<&'a PyDict>,
Any<'py>,
Option<Any<'py>>,
Tuple<'py>,
Option<Any<'py>>,
Option<Dict<'py>>,
) {
(a, b, args, c, kwargs)
}

#[pyfunction(signature = (*args, **kwargs))]
fn args_kwargs<'a>(
args: &'a PyTuple,
kwargs: Option<&'a PyDict>,
) -> (&'a PyTuple, Option<&'a PyDict>) {
fn args_kwargs<'py>(
args: Tuple<'py>,
kwargs: Option<Dict<'py>>,
) -> (Tuple<'py>, Option<Dict<'py>>) {
(args, kwargs)
}

Expand Down
48 changes: 28 additions & 20 deletions src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
exceptions::{self, PyBaseException},
ffi,
};
use crate::{IntoPy, Py, PyAny, PyNativeType, PyObject, Python, ToPyObject};
use crate::{Borrowed, IntoPy, Py, PyAny, PyNativeType, PyObject, Python, ToPyObject};
use std::borrow::Cow;
use std::cell::UnsafeCell;
use std::ffi::CString;
Expand Down Expand Up @@ -46,34 +46,47 @@ unsafe impl Sync for PyErr {}
pub type PyResult<T> = Result<T, PyErr>;

/// Error that indicates a failure to convert a PyAny to a more specific Python type.
#[derive(Debug)]
pub struct PyDowncastError<'a> {
from: &'a PyAny,
to: Cow<'static, str>,
}
pub struct PyDowncastError<'py>(DowncastError<'py, 'py>);

impl<'a> PyDowncastError<'a> {
/// Create a new `PyDowncastError` representing a failure to convert the object
/// `from` into the type named in `to`.
pub fn new(from: &'a PyAny, to: impl Into<Cow<'static, str>>) -> Self {
PyDowncastError {
from,
to: to.into(),
}
PyDowncastError(DowncastError::new_from_borrowed(from.as_borrowed(), to))
}
}

impl std::fmt::Debug for PyDowncastError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PyDowncastError")
.field("from", &self.0.from)
.field("to", &self.0.to)
.finish()
}
}

/// Error that indicates a failure to convert a PyAny to a more specific Python type.
#[derive(Debug)]
pub struct DowncastError<'a, 'py> {
from: &'a Bound<'py, PyAny>,
from: Borrowed<'a, 'py, PyAny>,
to: Cow<'static, str>,
}

impl<'a, 'py> DowncastError<'a, 'py> {
/// Create a new `PyDowncastError` representing a failure to convert the object
/// `from` into the type named in `to`.
pub fn new(from: &'a Bound<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {
DowncastError {
from: from.as_borrowed(),
to: to.into(),
}
}

/// Similar to [`DowncastError::new`], but from a `Borrowed` instead of a `Bound`.
pub(crate) fn new_from_borrowed(
from: Borrowed<'a, 'py, PyAny>,
to: impl Into<Cow<'static, str>>,
) -> Self {
DowncastError {
from,
to: to.into(),
Expand Down Expand Up @@ -829,20 +842,15 @@ impl PyErrArguments for PyDowncastErrorArguments {
/// Convert `PyDowncastError` to Python `TypeError`.
impl<'a> std::convert::From<PyDowncastError<'a>> for PyErr {
fn from(err: PyDowncastError<'_>) -> PyErr {
let args = PyDowncastErrorArguments {
from: err.from.get_type().into(),
to: err.to,
};

exceptions::PyTypeError::new_err(args)
PyErr::from(err.0)
}
}

impl<'a> std::error::Error for PyDowncastError<'a> {}

impl<'a> std::fmt::Display for PyDowncastError<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
display_downcast_error(f, &self.from.as_borrowed(), &self.to)
self.0.fmt(f)
}
}

Expand Down Expand Up @@ -882,13 +890,13 @@ impl std::error::Error for DowncastIntoError<'_> {}

impl std::fmt::Display for DowncastIntoError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
display_downcast_error(f, &self.from, &self.to)
display_downcast_error(f, self.from.as_borrowed(), &self.to)
}
}

fn display_downcast_error(
f: &mut std::fmt::Formatter<'_>,
from: &Bound<'_, PyAny>,
from: Borrowed<'_, '_, PyAny>,
to: &str,
) -> std::fmt::Result {
write!(
Expand Down
Loading

0 comments on commit 5591f9b

Please sign in to comment.