Convert callback_body_without_convert function to handle_panic function

This commit is contained in:
konstin 2021-03-01 12:42:19 +01:00
parent 593be05b83
commit f97c3a9479
4 changed files with 63 additions and 48 deletions

View File

@ -25,7 +25,7 @@ pub fn py_init(fnname: &Ident, name: &Ident, doc: syn::LitStr) -> TokenStream {
const NAME: &'static str = concat!(stringify!(#name), "\0");
static MODULE_DEF: ModuleDef = unsafe { ModuleDef::new(NAME) };
pyo3::callback_body!(_py, { MODULE_DEF.make_module(#doc, #fnname) })
pyo3::callback::handle_panic(|_py| { MODULE_DEF.make_module(#doc, #fnname) })
}
}
}
@ -229,14 +229,14 @@ fn function_c_wrapper(
let slf_module;
if pass_module {
cb = quote! {
#name(_slf, #(#names),*)
pyo3::callback::convert(_py, #name(_slf, #(#names),*))
};
slf_module = Some(quote! {
let _slf = _py.from_borrowed_ptr::<pyo3::types::PyModule>(_slf);
});
} else {
cb = quote! {
#name(#(#names),*)
pyo3::callback::convert(_py, #name(#(#names),*))
};
slf_module = None;
};
@ -248,7 +248,7 @@ fn function_c_wrapper(
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#name), "()");
pyo3::callback_body!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf_module
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);

View File

@ -121,9 +121,9 @@ fn impl_wrap_common(
{
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf
pyo3::callback::convert(_py, #body)
#body
})
}
}
@ -138,12 +138,12 @@ fn impl_wrap_common(
{
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::callback::convert(_py, #body)
#body
})
}
}
@ -165,12 +165,12 @@ pub fn impl_proto_wrap(cls: &syn::Type, spec: &FnSpec<'_>, self_ty: &SelfType) -
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::callback::convert(_py, #body)
#body
})
}
}
@ -196,7 +196,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
use std::convert::TryFrom;
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -213,7 +213,7 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let name = &spec.name;
let python_name = &spec.python_name;
let names: Vec<syn::Ident> = get_arg_names(&spec);
let cb = quote! { #cls::#name(&_cls, #(#names),*) };
let cb = quote! { pyo3::callback::convert(_py, #cls::#name(&_cls, #(#names),*)) };
let body = impl_arg_params(spec, Some(cls), cb);
@ -225,12 +225,12 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::callback::convert(_py, #body)
#body
})
}
}
@ -241,7 +241,7 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let name = &spec.name;
let python_name = &spec.python_name;
let names: Vec<syn::Ident> = get_arg_names(&spec);
let cb = quote! { #cls::#name(#(#names),*) };
let cb = quote! { pyo3::callback::convert(_py, #cls::#name(#(#names),*)) };
let body = impl_arg_params(spec, Some(cls), cb);
@ -253,11 +253,11 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::callback::convert(_py, #body)
#body
})
}
}
@ -319,7 +319,7 @@ pub(crate) fn impl_wrap_getter(
_slf: *mut pyo3::ffi::PyObject, _: *mut std::os::raw::c_void) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf
pyo3::callback::convert(_py, #getter_impl)
})
@ -371,7 +371,7 @@ pub(crate) fn impl_wrap_setter(
_value: *mut pyo3::ffi::PyObject, _: *mut std::os::raw::c_void) -> std::os::raw::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
pyo3::callback_body_without_convert!(_py, {
pyo3::callback::handle_panic(|_py| {
#slf
let _value = _py.from_borrowed_ptr::<pyo3::types::PyAny>(_value);
let _val = pyo3::FromPyObject::extract(_value)?;
@ -392,7 +392,7 @@ pub fn get_arg_names(spec: &FnSpec) -> Vec<syn::Ident> {
fn impl_call(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let fname = &spec.name;
let names = get_arg_names(spec);
quote! { #cls::#fname(_slf, #(#names),*) }
quote! { pyo3::callback::convert(_py, #cls::#fname(_slf, #(#names),*)) }
}
pub fn impl_arg_params(

View File

@ -9,6 +9,7 @@ use crate::IntoPyPointer;
use crate::{IntoPy, PyObject, Python};
use std::isize;
use std::os::raw::c_int;
use std::panic::UnwindSafe;
/// A type which can be the return type of a python C-API callback
pub trait PyCallbackOutput: Copy {
@ -194,9 +195,9 @@ where
#[doc(hidden)]
#[macro_export]
macro_rules! callback_body {
($py:ident, $body:expr) => {{
$crate::callback_body_without_convert!($py, $crate::callback::convert($py, $body))
}};
($py:ident, $body:expr) => {
$crate::callback::handle_panic(|$py| $crate::callback::convert($py, $body))
};
}
/// Variant of the above which does not perform the callback conversion. This allows the callback
@ -210,10 +211,10 @@ macro_rules! callback_body {
/// }
/// ```
///
/// It is wrapped in proc macros with callback_body_without_convert like so:
/// It is wrapped in proc macros with handle_panic like so:
///
/// ```ignore
/// pyo3::callback_body_without_convert!(py, {
/// pyo3::callback::handle_panic(|_py| {
/// let _slf = #slf;
/// pyo3::callback::convert(py, #foo)
/// })
@ -231,33 +232,33 @@ macro_rules! callback_body {
/// Then this will fail to compile, because the result of #foo borrows _slf, but _slf drops when
/// the block passed to the macro ends.
#[doc(hidden)]
#[macro_export]
macro_rules! callback_body_without_convert {
($py:ident, $body:expr) => {{
let pool = $crate::GILPool::new();
let unwind_safe_py = std::panic::AssertUnwindSafe(pool.python());
let result = match std::panic::catch_unwind(move || -> $crate::PyResult<_> {
let $py = *unwind_safe_py;
$body
}) {
pub unsafe fn handle_panic<
R: PyCallbackOutput,
F: FnOnce(Python) -> crate::PyResult<R> + UnwindSafe,
>(
body: F,
) -> R {
let pool = crate::GILPool::new();
let unwind_safe_py = std::panic::AssertUnwindSafe(pool.python());
let result =
match std::panic::catch_unwind(move || -> crate::PyResult<_> { body(*unwind_safe_py) }) {
Ok(result) => result,
Err(e) => {
// Try to format the error in the same way panic does
if let Some(string) = e.downcast_ref::<String>() {
Err($crate::panic::PanicException::new_err((string.clone(),)))
Err(crate::panic::PanicException::new_err((string.clone(),)))
} else if let Some(s) = e.downcast_ref::<&str>() {
Err($crate::panic::PanicException::new_err((s.to_string(),)))
Err(crate::panic::PanicException::new_err((s.to_string(),)))
} else {
Err($crate::panic::PanicException::new_err((
Err(crate::panic::PanicException::new_err((
"panic from Rust code",
)))
}
}
};
result.unwrap_or_else(|e| {
e.restore(pool.python());
$crate::callback::callback_error()
})
}};
result.unwrap_or_else(|e| {
e.restore(pool.python());
crate::callback::callback_error()
})
}

View File

@ -1,11 +1,25 @@
error[E0597]: `pool` does not live long enough
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'p` due to conflicting requirements
--> $DIR/static_ref.rs:4:1
|
4 | #[pyfunction]
| ^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| `pool` dropped here while still borrowed
| cast requires that `pool` is borrowed for `'static`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 4:1...
--> $DIR/static_ref.rs:4:1
|
4 | #[pyfunction]
| ^^^^^^^^^^^^^
note: ...so that the types are compatible
--> $DIR/static_ref.rs:4:1
|
4 | #[pyfunction]
| ^^^^^^^^^^^^^
= note: expected `pyo3::Python<'_>`
found `pyo3::Python<'_>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
--> $DIR/static_ref.rs:4:1
|
4 | #[pyfunction]
| ^^^^^^^^^^^^^
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)