Skip to content

Commit 0ce3193

Browse files
committed
Simplify callback code using callback_body! macro
1 parent c4e68e6 commit 0ce3193

File tree

10 files changed

+97
-169
lines changed

10 files changed

+97
-169
lines changed

pyo3-derive-backend/src/module.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,13 @@ fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>) -> TokenStream {
219219
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
220220
{
221221
const _LOCATION: &'static str = concat!(stringify!(#name), "()");
222-
223-
let _pool = pyo3::GILPool::new();
224-
let _py = _pool.python();
225-
pyo3::run_callback(_py, || {
222+
pyo3::callback_body!(_py, {
226223
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
227224
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
228225

229226
#body
230227

231-
pyo3::callback::convert(_py, _result)
228+
_result
232229
})
233230
}
234231
}

pyo3-derive-backend/src/pymethod.rs

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,9 @@ fn impl_wrap_common(
105105
{
106106
const _LOCATION: &'static str = concat!(
107107
stringify!(#cls), ".", stringify!(#python_name), "()");
108-
let _pool = pyo3::GILPool::new();
109-
let _py = _pool.python();
110-
pyo3::run_callback(_py, || {
108+
pyo3::callback_body!(_py, {
111109
#slf
112-
pyo3::callback::convert(_py, #body)
110+
#body
113111
})
114112
}
115113
}
@@ -124,16 +122,14 @@ fn impl_wrap_common(
124122
{
125123
const _LOCATION: &'static str = concat!(
126124
stringify!(#cls), ".", stringify!(#python_name), "()");
127-
let _pool = pyo3::GILPool::new();
128-
let _py = _pool.python();
129-
pyo3::run_callback(_py, || {
125+
pyo3::callback_body!(_py, {
130126
#slf
131127
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
132128
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
133129

134130
#body
135131

136-
pyo3::callback::convert(_py, _result)
132+
_result
137133
})
138134
}
139135
}
@@ -155,17 +151,15 @@ pub fn impl_proto_wrap(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
155151
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
156152
{
157153
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
158-
let _pool = pyo3::GILPool::new();
159-
let _py = _pool.python();
160-
pyo3::run_callback(_py, || {
154+
pyo3::callback_body!(_py, {
161155
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
162156
#borrow_self
163157
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
164158
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
165159

166160
#body
167161

168-
pyo3::callback::convert(_py, _result)
162+
_result
169163
})
170164
}
171165
}
@@ -193,9 +187,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
193187
use pyo3::type_object::PyTypeInfo;
194188

195189
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
196-
let _pool = pyo3::GILPool::new();
197-
let _py = _pool.python();
198-
pyo3::run_callback(_py, || {
190+
pyo3::callback_body!(_py, {
199191
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
200192
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
201193

@@ -225,16 +217,14 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
225217
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
226218
{
227219
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
228-
let _pool = pyo3::GILPool::new();
229-
let _py = _pool.python();
230-
pyo3::run_callback(_py, || {
220+
pyo3::callback_body!(_py, {
231221
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
232222
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
233223
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
234224

235225
#body
236226

237-
pyo3::callback::convert(_py, _result)
227+
_result
238228
})
239229
}
240230
}
@@ -257,15 +247,13 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
257247
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
258248
{
259249
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
260-
let _pool = pyo3::GILPool::new();
261-
let _py = _pool.python();
262-
pyo3::run_callback(_py, || {
250+
pyo3::callback_body!(_py, {
263251
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
264252
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
265253

266254
#body
267255

268-
pyo3::callback::convert(_py, _result)
256+
_result
269257
})
270258
}
271259
}
@@ -314,13 +302,10 @@ pub(crate) fn impl_wrap_getter(
314302
_slf: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> *mut pyo3::ffi::PyObject
315303
{
316304
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
317-
318-
let _pool = pyo3::GILPool::new();
319-
let _py = _pool.python();
320-
pyo3::run_callback(_py, || {
305+
pyo3::callback_body!(_py, {
321306
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
322307
#borrow_self
323-
pyo3::callback::convert(_py, #getter_impl)
308+
#getter_impl
324309
})
325310
}
326311
})
@@ -372,14 +357,13 @@ pub(crate) fn impl_wrap_setter(
372357
_value: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> pyo3::libc::c_int
373358
{
374359
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
375-
let _pool = pyo3::GILPool::new();
376-
let _py = _pool.python();
377-
pyo3::run_callback(_py, || {
360+
pyo3::callback_body!(_py, {
378361
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
379362
#borrow_self
380363
let _value = _py.from_borrowed_ptr::<pyo3::types::PyAny>(_value);
381364
let _val = pyo3::FromPyObject::extract(_value)?;
382-
pyo3::callback::convert(_py, {#setter_impl})
365+
366+
#setter_impl
383367
})
384368
}
385369
})

src/callback.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,26 @@ where
152152
T::ERR_VALUE
153153
}
154154

155+
/// Use this macro for all internal callback functions which Python will call.
156+
///
157+
/// It sets up the GILPool and converts the output into a Python object. It also restores
158+
/// any python error returned as an Err variant from the body.
159+
///
160+
/// # Safety
161+
/// This macro assumes the GIL is held. (It makes use of unsafe code, so usage of it is only
162+
/// possible inside unsafe blocks.)
155163
#[doc(hidden)]
156-
pub fn run_callback<T, F>(py: Python, callback: F) -> T
157-
where
158-
F: FnOnce() -> PyResult<T>,
159-
T: PyCallbackOutput,
160-
{
161-
callback().unwrap_or_else(|e| {
162-
e.restore(py);
163-
T::ERR_VALUE
164-
})
164+
#[macro_export]
165+
macro_rules! callback_body {
166+
($py:ident, $body:expr) => {{
167+
let pool = $crate::GILPool::new();
168+
169+
let $py = pool.python();
170+
let callback = move || -> $crate::PyResult<_> { $crate::callback::convert($py, $body) };
171+
172+
callback().unwrap_or_else(|e| {
173+
e.restore(pool.python());
174+
$crate::callback::callback_error()
175+
})
176+
}};
165177
}

src/class/basic.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
use crate::callback::HashCallbackOutput;
1212
use crate::class::methods::PyMethodDef;
1313
use crate::{
14-
callback, exceptions, ffi, run_callback, FromPyObject, GILPool, IntoPy, ObjectProtocol, PyAny,
15-
PyCell, PyClass, PyErr, PyObject, PyResult,
14+
exceptions, ffi, FromPyObject, IntoPy, ObjectProtocol, PyAny, PyCell, PyClass, PyErr, PyObject,
15+
PyResult,
1616
};
1717
use std::os::raw::c_int;
1818

@@ -218,9 +218,7 @@ where
218218
where
219219
T: for<'p> PyObjectGetAttrProtocol<'p>,
220220
{
221-
let pool = GILPool::new();
222-
let py = pool.python();
223-
run_callback(py, || {
221+
crate::callback_body!(py, {
224222
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
225223
// for existing fields and methods first
226224
let existing = ffi::PyObject_GenericGetAttr(slf, arg);
@@ -233,7 +231,7 @@ where
233231

234232
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
235233
let arg = py.from_borrowed_ptr::<PyAny>(arg);
236-
callback::convert(py, call_ref!(slf, __getattr__, arg))
234+
call_ref!(slf, __getattr__, arg)
237235
})
238236
}
239237
Some(wrap::<T>)
@@ -484,17 +482,14 @@ where
484482
where
485483
T: for<'p> PyObjectRichcmpProtocol<'p>,
486484
{
487-
let pool = GILPool::new();
488-
let py = pool.python();
489-
run_callback(py, || {
485+
crate::callback_body!(py, {
490486
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
491487
let arg = py.from_borrowed_ptr::<PyAny>(arg);
492488

493-
let borrowed_slf = slf.try_borrow()?;
494489
let op = extract_op(op)?;
495490
let arg = arg.extract()?;
496-
let result = borrowed_slf.__richcmp__(arg, op).into();
497-
callback::convert(py, result)
491+
492+
slf.try_borrow()?.__richcmp__(arg, op).into()
498493
})
499494
}
500495
Some(wrap::<T>)

src/class/buffer.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
//! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
66
//! c-api
77
use crate::err::PyResult;
8-
use crate::gil::GILPool;
9-
use crate::{callback, ffi, run_callback, PyCell, PyClass, PyRefMut};
8+
use crate::{ffi, PyCell, PyClass, PyRefMut};
109
use std::os::raw::c_int;
1110

1211
/// Buffer protocol interface
@@ -91,12 +90,9 @@ where
9190
where
9291
T: for<'p> PyBufferGetBufferProtocol<'p>,
9392
{
94-
let pool = GILPool::new();
95-
let py = pool.python();
96-
run_callback(py, || {
93+
crate::callback_body!(py, {
9794
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
98-
let result = T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).into();
99-
callback::convert(py, result)
95+
T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).into()
10096
})
10197
}
10298
Some(wrap::<T>)
@@ -126,12 +122,9 @@ where
126122
where
127123
T: for<'p> PyBufferReleaseBufferProtocol<'p>,
128124
{
129-
let pool = GILPool::new();
130-
let py = pool.python();
131-
run_callback(py, || {
125+
crate::callback_body!(py, {
132126
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
133-
let result = T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).into();
134-
crate::callback::convert(py, result)
127+
T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).into()
135128
})
136129
}
137130
Some(wrap::<T>)

0 commit comments

Comments
 (0)