From d8effb24e80136a313bdc6550330fa408fff74b0 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 7 Mar 2020 09:59:49 +0000 Subject: [PATCH] Refactor CallbackConverter code Now shorter and allows use of the ? operator inside callback code --- pyo3-derive-backend/src/method.rs | 2 +- pyo3-derive-backend/src/module.rs | 12 +- pyo3-derive-backend/src/pymethod.rs | 163 ++++++------ pyo3-derive-backend/src/utils.rs | 17 +- src/callback.rs | 175 ++++++------- src/class/basic.rs | 92 +++---- src/class/buffer.rs | 34 ++- src/class/descr.rs | 9 +- src/class/iter.rs | 34 +-- src/class/macros.rs | 388 +++++++++++++--------------- src/class/mapping.rs | 11 +- src/class/number.rs | 211 +++------------ src/class/pyasync.rs | 41 +-- src/class/sequence.rs | 136 ++++------ src/err.rs | 15 +- src/lib.rs | 1 + src/python.rs | 3 +- 17 files changed, 519 insertions(+), 825 deletions(-) diff --git a/pyo3-derive-backend/src/method.rs b/pyo3-derive-backend/src/method.rs index 20b06c61..aa02a90b 100644 --- a/pyo3-derive-backend/src/method.rs +++ b/pyo3-derive-backend/src/method.rs @@ -63,7 +63,7 @@ impl<'a> FnSpec<'a> { let is_mut = self .self_ .expect("impl_borrow_self is called for non-self fn"); - crate::utils::borrow_self(is_mut, true) + crate::utils::borrow_self(is_mut) } /// Parser function signature and function attributes diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index bd9d601a..d6180c5b 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -221,13 +221,15 @@ fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>) -> TokenStream { const _LOCATION: &'static str = concat!(stringify!(#name), "()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::callback::convert(_py, _result) + }) } } } diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs index d590d2b2..729384c0 100644 --- a/pyo3-derive-backend/src/pymethod.rs +++ b/pyo3-derive-backend/src/pymethod.rs @@ -83,10 +83,7 @@ pub fn impl_wrap_pyslf( }; let slf = quote! { let _cell = _py.from_borrowed_ptr::>(_slf); - let _slf: #self_ty = match std::convert::TryFrom::try_from(_cell) { - Ok(_slf) => _slf, - Err(e) => return pyo3::PyErr::from(e).restore_and_null(_py), - }; + let _slf: #self_ty = std::convert::TryFrom::try_from(_cell)?; }; impl_wrap_common(cls, spec, noargs, slf, body) } @@ -109,13 +106,11 @@ fn impl_wrap_common( const _LOCATION: &'static str = concat!( stringify!(#cls), ".", stringify!(#python_name), "()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - #slf - let _result = { - pyo3::derive_utils::IntoPyResult::into_py_result(#body) - }; - - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + #slf + pyo3::callback::convert(_py, #body) + }) } } } else { @@ -130,14 +125,16 @@ fn impl_wrap_common( const _LOCATION: &'static str = concat!( stringify!(#cls), ".", stringify!(#python_name), "()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - #slf - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + #slf + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::callback::convert(_py, _result) + }) } } } @@ -159,15 +156,17 @@ pub fn impl_proto_wrap(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream { { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _slf = _py.from_borrowed_ptr::>(_slf); - #borrow_self - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _slf = _py.from_borrowed_ptr::>(_slf); + #borrow_self + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::callback::convert(_py, _result) + }) } } } @@ -195,16 +194,16 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - match _result.and_then(|init| pyo3::PyClassInitializer::from(init).create_cell(_py)) { - Ok(slf) => slf as _, - Err(e) => e.restore_and_null(_py), - } + let cell = pyo3::PyClassInitializer::from(_result?).create_cell(_py)?; + Ok(cell as *mut pyo3::ffi::PyObject) + }) } } } @@ -227,14 +226,16 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream { { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject); - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject); + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::callback::convert(_py, _result) + }) } } } @@ -257,13 +258,15 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream { { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _args = _py.from_borrowed_ptr::(_args); - let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _args = _py.from_borrowed_ptr::(_args); + let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); - #body + #body - pyo3::callback::cb_obj_convert(_py, _result) + pyo3::callback::convert(_py, _result) + }) } } } @@ -305,7 +308,7 @@ pub(crate) fn impl_wrap_getter( PropertyType::Function(spec) => (spec.python_name.clone(), impl_call_getter(&spec)?), }; - let borrow_self = crate::utils::borrow_self(false, true); + let borrow_self = crate::utils::borrow_self(false); Ok(quote! { unsafe extern "C" fn __wrap( _slf: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> *mut pyo3::ffi::PyObject @@ -313,16 +316,12 @@ pub(crate) fn impl_wrap_getter( const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _slf = _py.from_borrowed_ptr::>(_slf); - #borrow_self - - let result = pyo3::derive_utils::IntoPyResult::into_py_result(#getter_impl); - - match result { - Ok(val) => pyo3::IntoPyPointer::into_ptr(pyo3::IntoPy::::into_py(val, _py)), - Err(e) => e.restore_and_null(_py), - } + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _slf = _py.from_borrowed_ptr::>(_slf); + #borrow_self + pyo3::callback::convert(_py, #getter_impl) + }) } }) } @@ -344,9 +343,9 @@ fn impl_call_setter(spec: &FnSpec) -> syn::Result { let name = &spec.name; let fncall = if py_arg.is_some() { - quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_py, _val))) + quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_py, _val))?;) } else { - quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val))) + quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val))?;) }; Ok(fncall) @@ -360,12 +359,12 @@ pub(crate) fn impl_wrap_setter( let (python_name, setter_impl) = match property_type { PropertyType::Descriptor(field) => { let name = field.ident.as_ref().unwrap(); - (name.unraw(), quote!({ _slf.#name = _val; Ok(()) })) + (name.unraw(), quote!(_slf.#name = _val;)) } PropertyType::Function(spec) => (spec.python_name.clone(), impl_call_setter(&spec)?), }; - let borrow_self = crate::utils::borrow_self(true, false); + let borrow_self = crate::utils::borrow_self(true); Ok(quote! { #[allow(unused_mut)] unsafe extern "C" fn __wrap( @@ -374,21 +373,14 @@ pub(crate) fn impl_wrap_setter( { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()"); let _py = pyo3::Python::assume_gil_acquired(); - let _pool = pyo3::GILPool::new(_py); - let _slf = _py.from_borrowed_ptr::>(_slf); - #borrow_self - let _value = _py.from_borrowed_ptr(_value); - - let _result = match pyo3::FromPyObject::extract(_value) { - Ok(_val) => { - #setter_impl - } - Err(e) => Err(e) - }; - match _result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(_py), - } + pyo3::run_callback(_py, || { + let _pool = pyo3::GILPool::new(_py); + let _slf = _py.from_borrowed_ptr::>(_slf); + #borrow_self + let _value = _py.from_borrowed_ptr::(_value); + let _val = pyo3::FromPyObject::extract(_value)?; + pyo3::callback::convert(_py, {#setter_impl}) + }) } }) } @@ -462,22 +454,19 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre let mut _args = _args; let mut _kwargs = _kwargs; - // Workaround to use the question mark operator without rewriting everything - let _result = (|| { - let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args( - Some(_LOCATION), - PARAMS, - _args, - _kwargs, - #accept_args, - #accept_kwargs, - &mut output - )?; + let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args( + Some(_LOCATION), + PARAMS, + _args, + _kwargs, + #accept_args, + #accept_kwargs, + &mut output + )?; - #(#param_conversion)* + #(#param_conversion)* - #into_result(#body) - })(); + let _result = #into_result(#body); } } diff --git a/pyo3-derive-backend/src/utils.rs b/pyo3-derive-backend/src/utils.rs index 32b66b25..d051a634 100644 --- a/pyo3-derive-backend/src/utils.rs +++ b/pyo3-derive-backend/src/utils.rs @@ -4,25 +4,14 @@ use proc_macro2::TokenStream; use quote::quote; use std::fmt::Display; -pub(crate) fn borrow_self(is_mut: bool, return_null: bool) -> TokenStream { - let ret = if return_null { - quote! { restore_and_null } - } else { - quote! { restore_and_minus1 } - }; +pub(crate) fn borrow_self(is_mut: bool) -> TokenStream { if is_mut { quote! { - let mut _slf = match _slf.try_borrow_mut() { - Ok(ref_) => ref_, - Err(e) => return pyo3::PyErr::from(e).#ret(_py), - }; + let mut _slf = _slf.try_borrow_mut()?; } } else { quote! { - let _slf = match _slf.try_borrow() { - Ok(ref_) => ref_, - Err(e) => return pyo3::PyErr::from(e).#ret(_py), - }; + let _slf = _slf.try_borrow()?; } } } diff --git a/src/callback.rs b/src/callback.rs index edeca66c..68603d30 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -7,89 +7,91 @@ use crate::exceptions::OverflowError; use crate::ffi::{self, Py_hash_t}; use crate::IntoPyPointer; use crate::{IntoPy, PyObject, Python}; +use std::isize; use std::os::raw::c_int; -use std::{isize, ptr}; + +/// A type which can be the return type of a python C-API callback +pub trait PyCallbackOutput: Copy { + /// The error value to return to python if the callback raised an exception + const ERR_VALUE: Self; +} + +impl PyCallbackOutput for *mut ffi::PyObject { + const ERR_VALUE: Self = std::ptr::null_mut(); +} + +impl PyCallbackOutput for libc::c_int { + const ERR_VALUE: Self = -1; +} + +impl PyCallbackOutput for ffi::Py_ssize_t { + const ERR_VALUE: Self = -1; +} + +impl PyCallbackOutput for () { + const ERR_VALUE: Self = (); +} /// Convert the result of callback function into the appropriate return value. -/// -/// Used by PyO3 macros. -pub trait CallbackConverter { - type Source; - type Result: Copy; - const ERR_VALUE: Self::Result; +pub trait IntoPyCallbackOutput { + fn convert(self, py: Python) -> PyResult; +} - fn convert(s: Self::Source, py: Python) -> Self::Result; - - #[inline] - fn convert_result(py: Python, value: PyResult) -> Self::Result { - match value { - Ok(val) => Self::convert(val, py), - Err(e) => { - e.restore(py); - Self::ERR_VALUE - } - } +impl IntoPyCallbackOutput for PyResult +where + T: IntoPyCallbackOutput, +{ + fn convert(self, py: Python) -> PyResult { + self.and_then(|t| t.convert(py)) } } -pub struct PyObjectCallbackConverter(pub std::marker::PhantomData); - -impl CallbackConverter for PyObjectCallbackConverter +impl IntoPyCallbackOutput<*mut ffi::PyObject> for T where T: IntoPy, { - type Source = T; - type Result = *mut ffi::PyObject; - const ERR_VALUE: Self::Result = ptr::null_mut(); - - fn convert(s: Self::Source, py: Python) -> Self::Result { - s.into_py(py).into_ptr() + fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> { + Ok(self.into_py(py).into_ptr()) } } -pub struct BoolCallbackConverter; +impl IntoPyCallbackOutput for *mut ffi::PyObject { + fn convert(self, _: Python) -> PyResult { + Ok(self) + } +} -impl CallbackConverter for BoolCallbackConverter { - type Source = bool; - type Result = c_int; - const ERR_VALUE: Self::Result = -1; +impl IntoPyCallbackOutput for () { + fn convert(self, _: Python) -> PyResult { + Ok(0) + } +} +impl IntoPyCallbackOutput for bool { + fn convert(self, _: Python) -> PyResult { + Ok(self as c_int) + } +} + +impl IntoPyCallbackOutput<()> for () { + fn convert(self, _: Python) -> PyResult<()> { + Ok(()) + } +} + +pub struct LenCallbackOutput(pub usize); + +impl IntoPyCallbackOutput for LenCallbackOutput { #[inline] - fn convert(s: Self::Source, _py: Python) -> Self::Result { - s as c_int - } -} - -pub struct LenResultConverter; - -impl CallbackConverter for LenResultConverter { - type Source = usize; - type Result = isize; - const ERR_VALUE: Self::Result = -1; - - fn convert(val: Self::Source, py: Python) -> Self::Result { - if val <= (isize::MAX as usize) { - val as isize + fn convert(self, _py: Python) -> PyResult { + if self.0 <= (isize::MAX as usize) { + Ok(self.0 as isize) } else { - OverflowError::py_err(()).restore(py); - -1 + Err(OverflowError::py_err(())) } } } -pub struct UnitCallbackConverter; - -impl CallbackConverter for UnitCallbackConverter { - type Source = (); - type Result = c_int; - const ERR_VALUE: Self::Result = -1; - - #[inline] - fn convert(_s: Self::Source, _py: Python) -> Self::Result { - 0 - } -} - pub trait WrappingCastTo { fn wrapping_cast(self) -> T; } @@ -115,50 +117,49 @@ wrapping_cast!(i32, Py_hash_t); wrapping_cast!(isize, Py_hash_t); wrapping_cast!(i64, Py_hash_t); -pub struct HashConverter(pub std::marker::PhantomData); +pub struct HashCallbackOutput(pub T); -impl CallbackConverter for HashConverter +impl IntoPyCallbackOutput for HashCallbackOutput where T: WrappingCastTo, { - type Source = T; - type Result = Py_hash_t; - const ERR_VALUE: Self::Result = -1; - #[inline] - fn convert(val: T, _py: Python) -> Py_hash_t { - let hash = val.wrapping_cast(); + fn convert(self, _py: Python) -> PyResult { + let hash = self.0.wrapping_cast(); if hash == -1 { - -2 + Ok(-2) } else { - hash + Ok(hash) } } } -// Short hands methods for macros +#[doc(hidden)] #[inline] -pub fn cb_convert(_c: C, py: Python, value: PyResult) -> C::Result +pub fn convert(py: Python, value: T) -> PyResult where - C: CallbackConverter, + T: IntoPyCallbackOutput, { - C::convert_result(py, value) + value.convert(py) } -// Same as cb_convert(PyObjectCallbackConverter, py, value) +#[doc(hidden)] #[inline] -pub fn cb_obj_convert>( - py: Python, - value: PyResult, -) -> as CallbackConverter>::Result { - PyObjectCallbackConverter::::convert_result(py, value) +pub fn callback_error() -> T +where + T: PyCallbackOutput, +{ + T::ERR_VALUE } -#[inline] -pub unsafe fn cb_err(_c: C, py: Python, err: impl Into) -> C::Result +#[doc(hidden)] +pub fn run_callback(py: Python, callback: F) -> T where - C: CallbackConverter, + F: FnOnce() -> PyResult, + T: PyCallbackOutput, { - err.into().restore(py); - C::ERR_VALUE + callback().unwrap_or_else(|e| { + e.restore(py); + T::ERR_VALUE + }) } diff --git a/src/class/basic.rs b/src/class/basic.rs index 722d5a31..2f1a16b5 100644 --- a/src/class/basic.rs +++ b/src/class/basic.rs @@ -8,11 +8,11 @@ //! Parts of the documentation are copied from the respective methods from the //! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html) -use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter}; +use crate::callback::HashCallbackOutput; use crate::class::methods::PyMethodDef; use crate::{ - exceptions, ffi, FromPyObject, IntoPy, IntoPyPointer, ObjectProtocol, PyAny, PyClass, PyErr, - PyObject, PyResult, Python, + callback, exceptions, ffi, run_callback, FromPyObject, GILPool, IntoPy, ObjectProtocol, PyAny, + PyCell, PyClass, PyErr, PyObject, PyResult, Python, }; use std::os::raw::c_int; @@ -219,27 +219,23 @@ where T: for<'p> PyObjectGetAttrProtocol<'p>, { let py = Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); + run_callback(py, || { + let _pool = GILPool::new(py); - // Behave like python's __getattr__ (as opposed to __getattribute__) and check - // for existing fields and methods first - let existing = ffi::PyObject_GenericGetAttr(slf, arg); - if existing.is_null() { - // PyObject_HasAttr also tries to get an object and clears the error if it fails - ffi::PyErr_Clear(); - } else { - return existing; - } + // Behave like python's __getattr__ (as opposed to __getattribute__) and check + // for existing fields and methods first + let existing = ffi::PyObject_GenericGetAttr(slf, arg); + if existing.is_null() { + // PyObject_HasAttr also tries to get an object and clears the error if it fails + ffi::PyErr_Clear(); + } else { + return Ok(existing); + } - let slf = py.from_borrowed_ptr::>(slf); - let arg = py.from_borrowed_ptr::(arg); - call_ref_with_converter!( - slf, - PyObjectCallbackConverter::(std::marker::PhantomData), - py, - __getattr__, - arg - ) + let slf = py.from_borrowed_ptr::>(slf); + let arg = py.from_borrowed_ptr::(arg); + callback::convert(py, call_ref!(slf, __getattr__, arg)) + }) } Some(wrap::) } @@ -357,11 +353,7 @@ where T: for<'p> PyObjectStrProtocol<'p>, { fn tp_str() -> Option { - py_unary_func!( - PyObjectStrProtocol, - T::__str__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyObjectStrProtocol, T::__str__) } } @@ -381,11 +373,7 @@ where T: for<'p> PyObjectReprProtocol<'p>, { fn tp_repr() -> Option { - py_unary_func!( - PyObjectReprProtocol, - T::__repr__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyObjectReprProtocol, T::__repr__) } } @@ -447,8 +435,8 @@ where py_unary_func!( PyObjectHashProtocol, T::__hash__, - HashConverter::(std::marker::PhantomData), - ffi::Py_hash_t + ffi::Py_hash_t, + HashCallbackOutput ) } } @@ -469,12 +457,7 @@ where T: for<'p> PyObjectBoolProtocol<'p>, { fn nb_bool() -> Option { - py_unary_func!( - PyObjectBoolProtocol, - T::__bool__, - BoolCallbackConverter, - c_int - ) + py_unary_func!(PyObjectBoolProtocol, T::__bool__, c_int) } } @@ -503,26 +486,17 @@ where T: for<'p> PyObjectRichcmpProtocol<'p>, { let py = Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); - let arg = py.from_borrowed_ptr::(arg); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); + let arg = py.from_borrowed_ptr::(arg); - match slf.try_borrow() { - Ok(borrowed_slf) => { - let res = match extract_op(op) { - Ok(op) => match arg.extract() { - Ok(arg) => borrowed_slf.__richcmp__(arg, op).into(), - Err(e) => Err(e), - }, - Err(e) => Err(e), - }; - match res { - Ok(val) => val.into_py(py).into_ptr(), - Err(e) => e.restore_and_null(py), - } - } - Err(e) => PyErr::from(e).restore_and_null(py), - } + let borrowed_slf = slf.try_borrow()?; + let op = extract_op(op)?; + let arg = arg.extract()?; + let result = borrowed_slf.__richcmp__(arg, op).into(); + callback::convert(py, result) + }) } Some(wrap::) } diff --git a/src/class/buffer.rs b/src/class/buffer.rs index 54e496a1..2177974f 100644 --- a/src/class/buffer.rs +++ b/src/class/buffer.rs @@ -4,9 +4,9 @@ //! //! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html) //! c-api -use crate::callback::UnitCallbackConverter; use crate::err::PyResult; -use crate::{ffi, PyClass, PyRefMut}; +use crate::gil::GILPool; +use crate::{callback, ffi, run_callback, PyCell, PyClass, PyRefMut, Python}; use std::os::raw::c_int; /// Buffer protocol interface @@ -91,14 +91,13 @@ where where T: for<'p> PyBufferGetBufferProtocol<'p>, { - let py = crate::Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); - let result = slf - .try_borrow_mut() - .map_err(crate::PyErr::from) - .and_then(|slf_mut| T::bf_getbuffer(slf_mut, arg1, arg2).into()); - crate::callback::cb_convert(UnitCallbackConverter, py, result) + let py = Python::assume_gil_acquired(); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); + let result = T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).into(); + callback::convert(py, result) + }) } Some(wrap::) } @@ -127,14 +126,13 @@ where where T: for<'p> PyBufferReleaseBufferProtocol<'p>, { - let py = crate::Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); - let result = slf - .try_borrow_mut() - .map_err(crate::PyErr::from) - .and_then(|slf_mut| T::bf_releasebuffer(slf_mut, arg1).into()); - crate::callback::cb_convert(UnitCallbackConverter, py, result); + let py = Python::assume_gil_acquired(); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); + let result = T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).into(); + crate::callback::convert(py, result) + }) } Some(wrap::) } diff --git a/src/class/descr.rs b/src/class/descr.rs index 61c2e51c..fb36b72a 100644 --- a/src/class/descr.rs +++ b/src/class/descr.rs @@ -5,7 +5,6 @@ //! [Python information]( //! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors) -use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter}; use crate::class::methods::PyMethodDef; use crate::err::PyResult; use crate::types::{PyAny, PyType}; @@ -84,11 +83,7 @@ where T: for<'p> PyDescrGetProtocol<'p>, { fn tp_descr_get() -> Option { - py_ternary_func!( - PyDescrGetProtocol, - T::__get__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_ternary_func!(PyDescrGetProtocol, T::__get__) } } @@ -108,7 +103,7 @@ where T: for<'p> PyDescrSetProtocol<'p>, { fn tp_descr_set() -> Option { - py_ternary_func!(PyDescrSetProtocol, T::__set__, UnitCallbackConverter, c_int) + py_ternary_func!(PyDescrSetProtocol, T::__set__, c_int) } } diff --git a/src/class/iter.rs b/src/class/iter.rs index 8d7522e3..0d011d2e 100644 --- a/src/class/iter.rs +++ b/src/class/iter.rs @@ -2,10 +2,9 @@ //! Python Iterator Interface. //! Trait and support implementation for implementing iterators -use crate::callback::{CallbackConverter, PyObjectCallbackConverter}; +use crate::callback::IntoPyCallbackOutput; use crate::err::PyResult; use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, PyRefMut, Python}; -use std::ptr; /// Python Iterator Interface. /// @@ -77,11 +76,7 @@ where { #[inline] fn tp_iter() -> Option { - py_unary_refmut_func!( - PyIterIterProtocol, - T::__iter__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_refmut_func!(PyIterIterProtocol, T::__iter__) } } @@ -104,31 +99,20 @@ where { #[inline] fn tp_iternext() -> Option { - py_unary_refmut_func!( - PyIterNextProtocol, - T::__next__, - IterNextConverter::(std::marker::PhantomData) - ) + py_unary_refmut_func!(PyIterNextProtocol, T::__next__, IterNextConverter) } } -struct IterNextConverter(std::marker::PhantomData); +struct IterNextConverter(Option); -impl CallbackConverter for IterNextConverter +impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextConverter where T: IntoPy, { - type Source = Option; - type Result = *mut ffi::PyObject; - const ERR_VALUE: Self::Result = ptr::null_mut(); - - fn convert(val: Self::Source, py: Python) -> Self::Result { - match val { - Some(val) => val.into_py(py).into_ptr(), - None => unsafe { - ffi::PyErr_SetNone(ffi::PyExc_StopIteration); - ptr::null_mut() - }, + fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> { + match self.0 { + Some(val) => Ok(val.into_py(py).into_ptr()), + None => Err(crate::exceptions::StopIteration::py_err(())), } } } diff --git a/src/class/macros.rs b/src/class/macros.rs index a7de4c9b..8d26cd03 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -3,51 +3,44 @@ #[macro_export] #[doc(hidden)] macro_rules! py_unary_func { - ($trait:ident, $class:ident :: $f:ident, $conv: expr) => { - py_unary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject); - }; - // Use call_ref! by default - ($trait:ident, $class:ident :: $f:ident, $conv: expr, $ret_type:ty) => { - py_unary_func!( - $trait, - $class::$f, - $conv, - $ret_type, - call_ref_with_converter - ); - }; - ($trait: ident, - $class:ident :: $f:ident, - $conv: expr, - $ret_type: ty, - $call: ident - ) => {{ + ($trait: ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty $(, $conv:expr)?) => {{ unsafe extern "C" fn wrap(slf: *mut $crate::ffi::PyObject) -> $ret_type where T: for<'p> $trait<'p>, { let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - $call!(slf, $conv, py, $f) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + $crate::callback::convert(py, $call!(slf, $f)$(.map($conv))?) + }) } Some(wrap::<$class>) }}; + // Use call_ref! by default + ($trait:ident, $class:ident :: $f:ident, $ret_type:ty $(, $conv:expr)?) => { + py_unary_func!($trait, $class::$f, call_ref, $ret_type $(, $conv)?); + }; + ($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => { + py_unary_func!($trait, $class::$f, call_ref, *mut $crate::ffi::PyObject $(, $conv)?); + }; } #[macro_export] #[doc(hidden)] macro_rules! py_unary_refmut_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ + ($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => {{ unsafe extern "C" fn wrap(slf: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject where T: for<'p> $trait<'p>, { let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let res = $class::$f(slf.borrow_mut()).into(); - $crate::callback::cb_convert($conv, py, res) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let res = $class::$f(slf.borrow_mut()).into(); + $crate::callback::convert(py, res $(.map($conv))?) + }) } Some(wrap::<$class>) }}; @@ -56,51 +49,48 @@ macro_rules! py_unary_refmut_func { #[macro_export] #[doc(hidden)] macro_rules! py_len_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ - unsafe extern "C" fn wrap(slf: *mut $crate::ffi::PyObject) -> $crate::ffi::Py_ssize_t - where - T: for<'p> $trait<'p>, - { - let py = Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let result = call_ref!(slf, $f); - $crate::callback::cb_convert($conv, py, result) - } - Some(wrap::<$class>) - }}; + ($trait:ident, $class:ident :: $f:ident) => { + py_unary_func!( + $trait, + $class::$f, + $crate::ffi::Py_ssize_t, + $crate::callback::LenCallbackOutput + ) + }; } #[macro_export] #[doc(hidden)] macro_rules! py_binary_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => { - py_binary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject) - }; // Use call_ref! by default - ($trait:ident, $class:ident :: $f:ident, $conv:expr, $return:ty) => {{ - py_binary_func!($trait, $class::$f, $conv, $return, call_ref_with_converter) - }}; - ($trait:ident, $class:ident :: $f:ident, $conv:expr, $return:ty, $call:ident) => {{ + ($trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident $(, $conv:expr)?) => {{ unsafe extern "C" fn wrap(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return where T: for<'p> $trait<'p>, { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); - $call!(slf, $conv, py, $f, arg) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); + $crate::callback::convert(py, $call!(slf, $f, arg)$(.map($conv))?) + }) } Some(wrap::<$class>) }}; + ($trait:ident, $class:ident :: $f:ident, $return:ty $(, $conv:expr)?) => { + py_binary_func!($trait, $class::$f, $return, call_ref $(, $conv)?) + }; + ($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => { + py_binary_func!($trait, $class::$f, *mut $crate::ffi::PyObject $(, $conv)?) + }; } #[macro_export] #[doc(hidden)] macro_rules! py_binary_num_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ + ($trait:ident, $class:ident :: $f:ident) => {{ unsafe extern "C" fn wrap( lhs: *mut ffi::PyObject, rhs: *mut ffi::PyObject, @@ -110,18 +100,14 @@ macro_rules! py_binary_num_func { { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs); - let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs); + let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs); - let result = match lhs.extract() { - Ok(lhs) => match rhs.extract() { - Ok(rhs) => $class::$f(lhs, rhs).into(), - Err(e) => Err(e.into()), - }, - Err(e) => Err(e.into()), - }; - $crate::callback::cb_convert($conv, py, result) + let result = $class::$f(lhs.extract()?, rhs.extract()?).into(); + $crate::callback::convert(py, result) + }) } Some(wrap::<$class>) }}; @@ -130,7 +116,7 @@ macro_rules! py_binary_num_func { #[macro_export] #[doc(hidden)] macro_rules! py_binary_reverse_num_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ + ($trait:ident, $class:ident :: $f:ident) => {{ unsafe extern "C" fn wrap( lhs: *mut ffi::PyObject, rhs: *mut ffi::PyObject, @@ -140,11 +126,16 @@ macro_rules! py_binary_reverse_num_func { { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - // Swap lhs <-> rhs - let slf = py.from_borrowed_ptr::<$crate::PyCell>(rhs); - let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs); - call_ref_with_converter!(slf, $conv, py, $f, arg) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + // Swap lhs <-> rhs + let slf = py.from_borrowed_ptr::<$crate::PyCell>(rhs); + let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs); + $crate::callback::convert( + py, + $class::$f(&*slf.try_borrow()?, arg.extract()?).into(), + ) + }) } Some(wrap::<$class>) }}; @@ -165,17 +156,14 @@ macro_rules! py_binary_self_func { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf_ = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); - let result = call_mut!(slf_, $f, arg); - match result { - Ok(_) => { - ffi::Py_INCREF(slf); - slf - } - Err(e) => e.restore_and_null(py), - } + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf_ = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); + call_mut!(slf_, $f, arg)?; + ffi::Py_INCREF(slf); + Ok(slf) + }) } Some(wrap::<$class>) }}; @@ -185,15 +173,10 @@ macro_rules! py_binary_self_func { #[doc(hidden)] macro_rules! py_ssizearg_func { // Use call_ref! by default - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => { - py_ssizearg_func!( - $trait, - $class::$f, - $conv, - call_ref_with_converter - ) + ($trait:ident, $class:ident :: $f:ident) => { + py_ssizearg_func!($trait, $class::$f, call_ref) }; - ($trait:ident, $class:ident :: $f:ident, $conv:expr, $call:ident) => {{ + ($trait:ident, $class:ident :: $f:ident, $call:ident) => {{ unsafe extern "C" fn wrap( slf: *mut ffi::PyObject, arg: $crate::ffi::Py_ssize_t, @@ -202,9 +185,11 @@ macro_rules! py_ssizearg_func { T: for<'p> $trait<'p>, { let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - $call!(slf, $conv, py, $f ;arg.into()) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + $crate::callback::convert(py, $call!(slf, $f; arg.into())) + }) } Some(wrap::<$class>) }}; @@ -213,10 +198,7 @@ macro_rules! py_ssizearg_func { #[macro_export] #[doc(hidden)] macro_rules! py_ternary_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => { - py_ternary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject); - }; - ($trait:ident, $class:ident :: $f:ident, $conv:expr, $return_type:ty) => {{ + ($trait:ident, $class:ident :: $f:ident, $return_type:ty) => {{ unsafe extern "C" fn wrap( slf: *mut $crate::ffi::PyObject, arg1: *mut $crate::ffi::PyObject, @@ -228,22 +210,31 @@ macro_rules! py_ternary_func { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let arg1 = py + .from_borrowed_ptr::<$crate::types::PyAny>(arg1) + .extract()?; + let arg2 = py + .from_borrowed_ptr::<$crate::types::PyAny>(arg2) + .extract()?; - call_ref_with_converter!(slf, $conv, py, $f, arg1, arg2) + $crate::callback::convert(py, slf.try_borrow()?.$f(arg1, arg2).into()) + }) } Some(wrap::) }}; + ($trait:ident, $class:ident :: $f:ident) => { + py_ternary_func!($trait, $class::$f, *mut $crate::ffi::PyObject); + }; } #[macro_export] #[doc(hidden)] macro_rules! py_ternary_num_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ + ($trait:ident, $class:ident :: $f:ident) => {{ unsafe extern "C" fn wrap( arg1: *mut $crate::ffi::PyObject, arg2: *mut $crate::ffi::PyObject, @@ -255,22 +246,21 @@ macro_rules! py_ternary_num_func { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2); - let arg3 = py.from_borrowed_ptr::<$crate::PyAny>(arg3); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let arg1 = py + .from_borrowed_ptr::<$crate::types::PyAny>(arg1) + .extract()?; + let arg2 = py + .from_borrowed_ptr::<$crate::types::PyAny>(arg2) + .extract()?; + let arg3 = py + .from_borrowed_ptr::<$crate::types::PyAny>(arg3) + .extract()?; - let result = match arg1.extract() { - Ok(arg1) => match arg2.extract() { - Ok(arg2) => match arg3.extract() { - Ok(arg3) => $class::$f(arg1, arg2, arg3).into(), - Err(e) => Err(e.into()), - }, - Err(e) => Err(e.into()), - }, - Err(e) => Err(e.into()), - }; - $crate::callback::cb_convert($conv, py, result) + let result = $class::$f(arg1, arg2, arg3).into(); + $crate::callback::convert(py, result) + }) } Some(wrap::) @@ -280,7 +270,7 @@ macro_rules! py_ternary_num_func { #[macro_export] #[doc(hidden)] macro_rules! py_ternary_reverse_num_func { - ($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{ + ($trait:ident, $class:ident :: $f:ident) => {{ unsafe extern "C" fn wrap( arg1: *mut $crate::ffi::PyObject, arg2: *mut $crate::ffi::PyObject, @@ -291,12 +281,16 @@ macro_rules! py_ternary_reverse_num_func { { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - // Swap lhs <-> rhs - let slf = py.from_borrowed_ptr::<$crate::PyCell>(arg2); - let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3); - call_ref_with_converter!(slf, $conv, py, $f, arg1, arg2) + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + // Swap lhs <-> rhs + let slf = py.from_borrowed_ptr::<$crate::PyCell>(arg2); + let slf = slf.try_borrow()?; + let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); + let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3); + let result = $class::$f(&*slf, arg1.extract()?, arg2.extract()?).into(); + $crate::callback::convert(py, result) + }) } Some(wrap::<$class>) }}; @@ -319,17 +313,14 @@ macro_rules! py_dummy_ternary_self_func { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf_ = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg1); - let result = call_mut!(slf_, $f, arg); - match result { - Ok(_) => { - ffi::Py_INCREF(slf); - slf - } - Err(e) => e.restore_and_null(py), - } + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf_cell = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); + call_mut!(slf_cell, $f, arg1)?; + ffi::Py_INCREF(slf); + Ok(slf) + }) } Some(wrap::<$class>) }}; @@ -348,25 +339,23 @@ macro_rules! py_func_set { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf); - let result = if value.is_null() { - Err($crate::PyErr::new::( - format!( - "Subscript deletion not supported by {:?}", - stringify!($generic) - ), - )) - } else { - let name = py.from_borrowed_ptr::<$crate::PyAny>(name); - let value = py.from_borrowed_ptr::<$crate::PyAny>(value); - call_mut!(slf, $fn_set, name, value) - }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + if value.is_null() { + Err($crate::PyErr::new::( + format!( + "Subscript deletion not supported by {:?}", + stringify!($generic) + ), + )) + } else { + let name = py.from_borrowed_ptr::<$crate::PyAny>(name); + let value = py.from_borrowed_ptr::<$crate::PyAny>(value); + crate::callback::convert(py, call_mut!(slf, $fn_set, name, value)) + } + }) } Some(wrap::<$generic>) @@ -386,22 +375,21 @@ macro_rules! py_func_del { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); - let result = if value.is_null() { - let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let name = py.from_borrowed_ptr::<$crate::PyAny>(name); - - call_mut!(slf, $fn_del, name) - } else { - Err(PyErr::new::( - "Subscript assignment not supported", - )) - }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + if value.is_null() { + let slf = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let name = py + .from_borrowed_ptr::<$crate::types::PyAny>(name) + .extract()?; + $crate::callback::convert(py, slf.try_borrow_mut()?.$fn_del(name).into()) + } else { + Err(PyErr::new::( + "Subscript assignment not supported", + )) + } + }) } Some(wrap::<$generic>) @@ -421,71 +409,43 @@ macro_rules! py_func_set_del { use $crate::ObjectProtocol; let py = $crate::Python::assume_gil_acquired(); - let _pool = $crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf); - let name = py.from_borrowed_ptr::<$crate::PyAny>(name); + $crate::run_callback(py, || { + let _pool = $crate::GILPool::new(py); + let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf); + let name = py.from_borrowed_ptr::<$crate::PyAny>(name); - let result = if value.is_null() { - call_mut!(slf, $fn_del, name) - } else { - let value = py.from_borrowed_ptr::<$crate::PyAny>(value); - call_mut!(slf, $fn_set, name, value) - }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + let result = if value.is_null() { + call_mut!(slf, $fn_del, name) + } else { + let value = py.from_borrowed_ptr::<$crate::PyAny>(value); + call_mut!(slf, $fn_set, name, value) + }; + $crate::callback::convert(py, result) + }) } Some(wrap::<$generic>) }}; } macro_rules! _call_impl { - ($slf: ident, $fn: ident $(; $args: expr)*) => { $slf.$fn($($args,)*).into() }; - ($slf: ident, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => { - match $raw_arg.extract() { - Ok(arg) => _call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;arg), - Err(e) => Err(e.into()), - } + ($slf: expr, $fn: ident $(; $args: expr)*) => { + $slf.$fn($($args,)*).into() + }; + ($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => { + _call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;$raw_arg.extract()?) }; } /// Call `slf.try_borrow()?.$fn(...)` macro_rules! call_ref { ($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { - match $slf.try_borrow() { - Ok(slf) => _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*), - Err(e) => Err(e.into()), - } - }; -} - -/// Call `slf.try_borrow()?.$fn(...)` and returns the result using the given CallbackConverter -macro_rules! call_ref_with_converter { - ($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { - match $slf.try_borrow() { - Ok(slf) => $crate::callback::cb_convert($conv, $py, _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*)), - Err(e) => $crate::callback::cb_err($conv, $py, e) - } + _call_impl!($slf.try_borrow()?, $fn $(,$raw_args)* $(;$args)*) }; } /// Call `slf.try_borrow_mut()?.$fn(...)` macro_rules! call_mut { ($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { - match $slf.try_borrow_mut() { - Ok(mut slf) => _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*), - Err(e) => Err(e.into()), - } - }; -} - -/// Call `slf.try_borrow_mut()?.$fn(...)` and returns the result using the given CallbackConverter -macro_rules! call_mut_with_converter { - ($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { - match $slf.try_borrow_mut() { - Ok(mut slf) => $crate::callback::cb_convert($conv, $py, _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*)), - Err(e) => $crate::callback::cb_err($conv, $py, e) - } + _call_impl!($slf.try_borrow_mut()?, $fn $(,$raw_args)* $(;$args)*) }; } diff --git a/src/class/mapping.rs b/src/class/mapping.rs index 39373134..4d82a9dd 100644 --- a/src/class/mapping.rs +++ b/src/class/mapping.rs @@ -3,10 +3,9 @@ //! Python Mapping Interface //! Trait and support implementation for implementing mapping support -use crate::callback::{LenResultConverter, PyObjectCallbackConverter}; use crate::class::methods::PyMethodDef; use crate::err::{PyErr, PyResult}; -use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject, Python}; +use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject}; /// Mapping interface #[allow(unused_variables)] @@ -141,7 +140,7 @@ where { #[inline] fn mp_length() -> Option { - py_len_func!(PyMappingLenProtocol, T::__len__, LenResultConverter) + py_len_func!(PyMappingLenProtocol, T::__len__) } } @@ -164,11 +163,7 @@ where { #[inline] fn mp_subscript() -> Option { - py_binary_func!( - PyMappingGetItemProtocol, - T::__getitem__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_func!(PyMappingGetItemProtocol, T::__getitem__) } } diff --git a/src/class/number.rs b/src/class/number.rs index b845d2e0..207a5b3a 100644 --- a/src/class/number.rs +++ b/src/class/number.rs @@ -3,7 +3,6 @@ //! Python Number Interface //! Trait and support implementation for implementing number protocol -use crate::callback::PyObjectCallbackConverter; use crate::class::basic::PyObjectProtocolImpl; use crate::class::methods::PyMethodDef; use crate::err::PyResult; @@ -761,11 +760,7 @@ where T: for<'p> PyNumberAddProtocol<'p>, { fn nb_add() -> Option { - py_binary_num_func!( - PyNumberAddProtocol, - T::__add__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberAddProtocol, T::__add__) } } @@ -787,11 +782,7 @@ where T: for<'p> PyNumberSubProtocol<'p>, { fn nb_subtract() -> Option { - py_binary_num_func!( - PyNumberSubProtocol, - T::__sub__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberSubProtocol, T::__sub__) } } @@ -813,11 +804,7 @@ where T: for<'p> PyNumberMulProtocol<'p>, { fn nb_multiply() -> Option { - py_binary_num_func!( - PyNumberMulProtocol, - T::__mul__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberMulProtocol, T::__mul__) } } @@ -839,11 +826,7 @@ where T: for<'p> PyNumberMatmulProtocol<'p>, { fn nb_matrix_multiply() -> Option { - py_binary_num_func!( - PyNumberMatmulProtocol, - T::__matmul__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberMatmulProtocol, T::__matmul__) } } @@ -865,11 +848,7 @@ where T: for<'p> PyNumberTruedivProtocol<'p>, { fn nb_true_divide() -> Option { - py_binary_num_func!( - PyNumberTruedivProtocol, - T::__truediv__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberTruedivProtocol, T::__truediv__) } } @@ -891,11 +870,7 @@ where T: for<'p> PyNumberFloordivProtocol<'p>, { fn nb_floor_divide() -> Option { - py_binary_num_func!( - PyNumberFloordivProtocol, - T::__floordiv__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberFloordivProtocol, T::__floordiv__) } } @@ -917,11 +892,7 @@ where T: for<'p> PyNumberModProtocol<'p>, { fn nb_remainder() -> Option { - py_binary_num_func!( - PyNumberModProtocol, - T::__mod__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberModProtocol, T::__mod__) } } @@ -943,11 +914,7 @@ where T: for<'p> PyNumberDivmodProtocol<'p>, { fn nb_divmod() -> Option { - py_binary_num_func!( - PyNumberDivmodProtocol, - T::__divmod__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberDivmodProtocol, T::__divmod__) } } @@ -969,11 +936,7 @@ where T: for<'p> PyNumberPowProtocol<'p>, { fn nb_power() -> Option { - py_ternary_num_func!( - PyNumberPowProtocol, - T::__pow__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_ternary_num_func!(PyNumberPowProtocol, T::__pow__) } } @@ -995,11 +958,7 @@ where T: for<'p> PyNumberLShiftProtocol<'p>, { fn nb_lshift() -> Option { - py_binary_num_func!( - PyNumberLShiftProtocol, - T::__lshift__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberLShiftProtocol, T::__lshift__) } } @@ -1021,11 +980,7 @@ where T: for<'p> PyNumberRShiftProtocol<'p>, { fn nb_rshift() -> Option { - py_binary_num_func!( - PyNumberRShiftProtocol, - T::__rshift__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberRShiftProtocol, T::__rshift__) } } @@ -1047,11 +1002,7 @@ where T: for<'p> PyNumberAndProtocol<'p>, { fn nb_and() -> Option { - py_binary_num_func!( - PyNumberAndProtocol, - T::__and__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberAndProtocol, T::__and__) } } @@ -1073,11 +1024,7 @@ where T: for<'p> PyNumberXorProtocol<'p>, { fn nb_xor() -> Option { - py_binary_num_func!( - PyNumberXorProtocol, - T::__xor__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberXorProtocol, T::__xor__) } } @@ -1099,11 +1046,7 @@ where T: for<'p> PyNumberOrProtocol<'p>, { fn nb_or() -> Option { - py_binary_num_func!( - PyNumberOrProtocol, - T::__or__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_num_func!(PyNumberOrProtocol, T::__or__) } } @@ -1426,11 +1369,7 @@ where T: for<'p> PyNumberRAddProtocol<'p>, { fn nb_add_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRAddProtocol, - T::__radd__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRAddProtocol, T::__radd__) } } @@ -1466,11 +1405,7 @@ where T: for<'p> PyNumberRSubProtocol<'p>, { fn nb_sub_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRSubProtocol, - T::__rsub__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRSubProtocol, T::__rsub__) } } @@ -1506,11 +1441,7 @@ where T: for<'p> PyNumberRMulProtocol<'p>, { fn nb_mul_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRMulProtocol, - T::__rmul__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRMulProtocol, T::__rmul__) } } @@ -1546,11 +1477,7 @@ where T: for<'p> PyNumberRMatmulProtocol<'p>, { fn nb_matmul_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRMatmulProtocol, - T::__rmatmul__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRMatmulProtocol, T::__rmatmul__) } } @@ -1586,11 +1513,7 @@ where T: for<'p> PyNumberRTruedivProtocol<'p>, { fn nb_truediv_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRTruedivProtocol, - T::__rtruediv__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRTruedivProtocol, T::__rtruediv__) } } @@ -1626,11 +1549,7 @@ where T: for<'p> PyNumberRFloordivProtocol<'p>, { fn nb_floordiv_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRFloordivProtocol, - T::__rfloordiv__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRFloordivProtocol, T::__rfloordiv__) } } @@ -1666,11 +1585,7 @@ where T: for<'p> PyNumberRModProtocol<'p>, { fn nb_mod_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRModProtocol, - T::__rmod__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRModProtocol, T::__rmod__) } } @@ -1706,11 +1621,7 @@ where T: for<'p> PyNumberRDivmodProtocol<'p>, { fn nb_divmod_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRDivmodProtocol, - T::__rdivmod__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRDivmodProtocol, T::__rdivmod__) } } @@ -1746,11 +1657,7 @@ where T: for<'p> PyNumberRPowProtocol<'p>, { fn nb_pow_fallback() -> Option { - py_ternary_reverse_num_func!( - PyNumberRPowProtocol, - T::__rpow__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_ternary_reverse_num_func!(PyNumberRPowProtocol, T::__rpow__) } } @@ -1786,11 +1693,7 @@ where T: for<'p> PyNumberRLShiftProtocol<'p>, { fn nb_lshift_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRLShiftProtocol, - T::__rlshift__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRLShiftProtocol, T::__rlshift__) } } @@ -1826,11 +1729,7 @@ where T: for<'p> PyNumberRRShiftProtocol<'p>, { fn nb_rshift_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRRShiftProtocol, - T::__rrshift__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRRShiftProtocol, T::__rrshift__) } } @@ -1866,11 +1765,7 @@ where T: for<'p> PyNumberRAndProtocol<'p>, { fn nb_and_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRAndProtocol, - T::__rand__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRAndProtocol, T::__rand__) } } @@ -1906,11 +1801,7 @@ where T: for<'p> PyNumberRXorProtocol<'p>, { fn nb_xor_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberRXorProtocol, - T::__rxor__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberRXorProtocol, T::__rxor__) } } @@ -1946,11 +1837,7 @@ where T: for<'p> PyNumberROrProtocol<'p>, { fn nb_or_fallback() -> Option { - py_binary_reverse_num_func!( - PyNumberROrProtocol, - T::__ror__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_reverse_num_func!(PyNumberROrProtocol, T::__ror__) } } @@ -1973,11 +1860,7 @@ where { #[inline] fn nb_negative() -> Option { - py_unary_func!( - PyNumberNegProtocol, - T::__neg__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberNegProtocol, T::__neg__) } } @@ -1999,11 +1882,7 @@ where T: for<'p> PyNumberPosProtocol<'p>, { fn nb_positive() -> Option { - py_unary_func!( - PyNumberPosProtocol, - T::__pos__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberPosProtocol, T::__pos__) } } @@ -2025,11 +1904,7 @@ where T: for<'p> PyNumberAbsProtocol<'p>, { fn nb_absolute() -> Option { - py_unary_func!( - PyNumberAbsProtocol, - T::__abs__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberAbsProtocol, T::__abs__) } } @@ -2051,11 +1926,7 @@ where T: for<'p> PyNumberInvertProtocol<'p>, { fn nb_invert() -> Option { - py_unary_func!( - PyNumberInvertProtocol, - T::__invert__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberInvertProtocol, T::__invert__) } } @@ -2077,11 +1948,7 @@ where T: for<'p> PyNumberIntProtocol<'p>, { fn nb_int() -> Option { - py_unary_func!( - PyNumberIntProtocol, - T::__int__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberIntProtocol, T::__int__) } } @@ -2103,11 +1970,7 @@ where T: for<'p> PyNumberFloatProtocol<'p>, { fn nb_float() -> Option { - py_unary_func!( - PyNumberFloatProtocol, - T::__float__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberFloatProtocol, T::__float__) } } @@ -2129,11 +1992,7 @@ where T: for<'p> PyNumberIndexProtocol<'p>, { fn nb_index() -> Option { - py_unary_func!( - PyNumberIndexProtocol, - T::__index__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyNumberIndexProtocol, T::__index__) } } diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs index 3a423ffa..a43dc57c 100644 --- a/src/class/pyasync.rs +++ b/src/class/pyasync.rs @@ -8,7 +8,6 @@ //! [PEP-0492](https://www.python.org/dev/peps/pep-0492/) //! -use crate::callback::PyObjectCallbackConverter; use crate::class::methods::PyMethodDef; use crate::err::PyResult; use crate::{ffi, PyClass, PyObject}; @@ -150,11 +149,7 @@ where { #[inline] fn am_await() -> Option { - py_unary_func!( - PyAsyncAwaitProtocol, - T::__await__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyAsyncAwaitProtocol, T::__await__) } } @@ -177,11 +172,7 @@ where { #[inline] fn am_aiter() -> Option { - py_unary_func!( - PyAsyncAiterProtocol, - T::__aiter__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_unary_func!(PyAsyncAiterProtocol, T::__aiter__) } } @@ -200,30 +191,22 @@ where mod anext { use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl}; - use crate::callback::CallbackConverter; + use crate::callback::IntoPyCallbackOutput; + use crate::err::PyResult; use crate::IntoPyPointer; use crate::Python; use crate::{ffi, IntoPy, PyObject}; - use std::marker::PhantomData; - use std::ptr; - struct IterANextResultConverter(PhantomData); + struct IterANextOutput(Option); - impl CallbackConverter for IterANextResultConverter + impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput where T: IntoPy, { - type Source = Option; - type Result = *mut ffi::PyObject; - const ERR_VALUE: Self::Result = ptr::null_mut(); - - fn convert(val: Self::Source, py: Python) -> Self::Result { - match val { - Some(val) => val.into_py(py).into_ptr(), - None => unsafe { - ffi::PyErr_SetNone(ffi::PyExc_StopAsyncIteration); - ptr::null_mut() - }, + fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> { + match self.0 { + Some(val) => Ok(val.into_py(py).into_ptr()), + None => Err(crate::exceptions::StopAsyncIteration::py_err(())), } } } @@ -237,9 +220,9 @@ mod anext { py_unary_func!( PyAsyncAnextProtocol, T::__anext__, - IterANextResultConverter::(std::marker::PhantomData), + call_mut, *mut crate::ffi::PyObject, - call_mut_with_converter + IterANextOutput ) } } diff --git a/src/class/sequence.rs b/src/class/sequence.rs index 498844b7..eeb23600 100644 --- a/src/class/sequence.rs +++ b/src/class/sequence.rs @@ -3,10 +3,11 @@ //! Python Sequence Interface //! Trait and support implementation for implementing sequence -use crate::callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter}; +use crate::conversion::{FromPyObject, IntoPy}; use crate::err::{PyErr, PyResult}; +use crate::gil::GILPool; use crate::objectprotocol::ObjectProtocol; -use crate::{exceptions, ffi, FromPyObject, IntoPy, PyAny, PyClass, PyObject, Python}; +use crate::{callback, exceptions, ffi, run_callback, PyAny, PyCell, PyClass, PyObject, Python}; use std::os::raw::c_int; /// Sequence interface @@ -176,7 +177,7 @@ where T: for<'p> PySequenceLenProtocol<'p>, { fn sq_length() -> Option { - py_len_func!(PySequenceLenProtocol, T::__len__, LenResultConverter) + py_len_func!(PySequenceLenProtocol, T::__len__) } } @@ -198,11 +199,7 @@ where T: for<'p> PySequenceGetItemProtocol<'p>, { fn sq_item() -> Option { - py_ssizearg_func!( - PySequenceGetItemProtocol, - T::__getitem__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_ssizearg_func!(PySequenceGetItemProtocol, T::__getitem__) } } @@ -260,31 +257,23 @@ mod sq_ass_item_impl { T: for<'p> PySequenceSetItemProtocol<'p>, { let py = Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); - if value.is_null() { - return PyErr::new::(format!( - "Item deletion is not supported by {:?}", - stringify!(T) - )) - .restore_and_minus1(py); - } - - let result = match slf.try_borrow_mut() { - Ok(mut slf) => { - let value = py.from_borrowed_ptr::(value); - match value.extract() { - Ok(value) => slf.__setitem__(key.into(), value).into(), - Err(e) => e.into(), - } + if value.is_null() { + return Err(PyErr::new::(format!( + "Item deletion is not supported by {:?}", + stringify!(T) + ))); } - Err(e) => Err(PyErr::from(e)), - }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + + let mut slf = slf.try_borrow_mut()?; + let value = py.from_borrowed_ptr::(value); + let value = value.extract()?; + let result = slf.__setitem__(key.into(), value).into(); + callback::convert(py, result) + }) } Some(wrap::) } @@ -317,22 +306,21 @@ mod sq_ass_item_impl { T: for<'p> PySequenceDelItemProtocol<'p>, { let py = Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); - let result = if value.is_null() { - slf.borrow_mut().__delitem__(key.into()).into() - } else { - Err(PyErr::new::(format!( - "Item assignment not supported by {:?}", - stringify!(T) - ))) - }; + let result = if value.is_null() { + slf.borrow_mut().__delitem__(key.into()).into() + } else { + Err(PyErr::new::(format!( + "Item assignment not supported by {:?}", + stringify!(T) + ))) + }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + callback::convert(py, result) + }) } Some(wrap::) } @@ -365,25 +353,20 @@ mod sq_ass_item_impl { T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>, { let py = Python::assume_gil_acquired(); - let _pool = crate::GILPool::new(py); - let slf = py.from_borrowed_ptr::>(slf); + run_callback(py, || { + let _pool = GILPool::new(py); + let slf = py.from_borrowed_ptr::>(slf); - let result = if value.is_null() { - call_mut!(slf, __delitem__; key.into()) - } else { - let value = py.from_borrowed_ptr::(value); - match slf.try_borrow_mut() { - Ok(mut slf_) => match value.extract() { - Ok(value) => slf_.__setitem__(key.into(), value).into(), - Err(e) => Err(e), - }, - Err(e) => Err(e.into()), - } - }; - match result { - Ok(_) => 0, - Err(e) => e.restore_and_minus1(py), - } + let result = if value.is_null() { + call_mut!(slf, __delitem__; key.into()) + } else { + let value = py.from_borrowed_ptr::(value); + let mut slf_ = slf.try_borrow_mut()?; + let value = value.extract()?; + slf_.__setitem__(key.into(), value).into() + }; + callback::convert(py, result) + }) } Some(wrap::) } @@ -408,12 +391,7 @@ where T: for<'p> PySequenceContainsProtocol<'p>, { fn sq_contains() -> Option { - py_binary_func!( - PySequenceContainsProtocol, - T::__contains__, - BoolCallbackConverter, - c_int - ) + py_binary_func!(PySequenceContainsProtocol, T::__contains__, c_int) } } @@ -435,11 +413,7 @@ where T: for<'p> PySequenceConcatProtocol<'p>, { fn sq_concat() -> Option { - py_binary_func!( - PySequenceConcatProtocol, - T::__concat__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_binary_func!(PySequenceConcatProtocol, T::__concat__) } } @@ -461,11 +435,7 @@ where T: for<'p> PySequenceRepeatProtocol<'p>, { fn sq_repeat() -> Option { - py_ssizearg_func!( - PySequenceRepeatProtocol, - T::__repeat__, - PyObjectCallbackConverter::(std::marker::PhantomData) - ) + py_ssizearg_func!(PySequenceRepeatProtocol, T::__repeat__) } } @@ -490,9 +460,8 @@ where py_binary_func!( PySequenceInplaceConcatProtocol, T::__inplace_concat__, - PyObjectCallbackConverter::(std::marker::PhantomData), - *mut crate::ffi::PyObject, - call_mut_with_converter + *mut ffi::PyObject, + call_mut ) } } @@ -518,8 +487,7 @@ where py_ssizearg_func!( PySequenceInplaceRepeatProtocol, T::__inplace_repeat__, - PyObjectCallbackConverter::(std::marker::PhantomData), - call_mut_with_converter + call_mut ) } } diff --git a/src/err.rs b/src/err.rs index cc0dbcd7..2cdfcac3 100644 --- a/src/err.rs +++ b/src/err.rs @@ -1,15 +1,12 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use crate::instance::Py; -use crate::object::PyObject; use crate::type_object::PyTypeObject; -use crate::types::{PyAny, PyType}; -use crate::AsPyPointer; -use crate::IntoPyPointer; -use crate::Python; -use crate::{exceptions, IntoPy}; -use crate::{ffi, FromPy}; -use crate::{ToBorrowedObject, ToPyObject}; +use crate::types::PyType; +use crate::{exceptions, ffi}; +use crate::{ + AsPyPointer, FromPy, IntoPy, IntoPyPointer, Py, PyAny, PyObject, Python, ToBorrowedObject, + ToPyObject, +}; use libc::c_int; use std::ffi::CString; use std::io; diff --git a/src/lib.rs b/src/lib.rs index 422700ef..81e84fa8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,6 +133,7 @@ //! } //! ``` +pub use crate::callback::run_callback; pub use crate::class::*; pub use crate::conversion::{ AsPyPointer, FromPy, FromPyObject, FromPyPointer, IntoPy, IntoPyPointer, PyTryFrom, PyTryInto, diff --git a/src/python.rs b/src/python.rs index 0d9b479c..6c4f4d89 100644 --- a/src/python.rs +++ b/src/python.rs @@ -9,8 +9,7 @@ use crate::instance::AsPyRef; use crate::object::PyObject; use crate::type_object::{PyDowncastImpl, PyTypeInfo, PyTypeObject}; use crate::types::{PyAny, PyDict, PyModule, PyType}; -use crate::AsPyPointer; -use crate::{FromPyPointer, IntoPyPointer, PyTryFrom}; +use crate::{AsPyPointer, FromPyPointer, IntoPyPointer, PyTryFrom}; use std::ffi::CString; use std::marker::PhantomData; use std::os::raw::c_int;