Skip to content

Commit a6d6367

Browse files
authored
Merge pull request #1837 from davidhewitt/more-proc-macro-hygiene
pyo3-macros-backend: more tests for macro hygiene
2 parents 667865e + 3136109 commit a6d6367

File tree

6 files changed

+80
-56
lines changed

6 files changed

+80
-56
lines changed

pyo3-macros-backend/src/method.rs

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ impl FnType {
103103
}
104104
FnType::FnClass => {
105105
quote! {
106-
let _slf = pyo3::types::PyType::from_type_ptr(_py, _slf as *mut pyo3::ffi::PyTypeObject);
106+
let _slf = ::pyo3::types::PyType::from_type_ptr(_py, _slf as *mut ::pyo3::ffi::PyTypeObject);
107107
}
108108
}
109109
FnType::FnModule => {
110110
quote! {
111-
let _slf = _py.from_borrowed_ptr::<pyo3::types::PyModule>(_slf);
111+
let _slf = _py.from_borrowed_ptr::<::pyo3::types::PyModule>(_slf);
112112
}
113113
}
114114
}
@@ -455,17 +455,17 @@ impl<'a> FnSpec<'a> {
455455
quote!(#func_name)
456456
};
457457
let rust_call =
458-
quote! { pyo3::callback::convert(#py, #rust_name(#self_arg #(#arg_names),*)) };
458+
quote! { ::pyo3::callback::convert(#py, #rust_name(#self_arg #(#arg_names),*)) };
459459
Ok(match self.convention {
460460
CallingConvention::Noargs => {
461461
quote! {
462462
unsafe extern "C" fn #ident (
463-
_slf: *mut pyo3::ffi::PyObject,
464-
_args: *mut pyo3::ffi::PyObject,
465-
) -> *mut pyo3::ffi::PyObject
463+
_slf: *mut ::pyo3::ffi::PyObject,
464+
_args: *mut ::pyo3::ffi::PyObject,
465+
) -> *mut ::pyo3::ffi::PyObject
466466
{
467467
#deprecations
468-
pyo3::callback::handle_panic(|#py| {
468+
::pyo3::callback::handle_panic(|#py| {
469469
#self_conversion
470470
#rust_call
471471
})
@@ -476,23 +476,24 @@ impl<'a> FnSpec<'a> {
476476
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, true)?;
477477
quote! {
478478
unsafe extern "C" fn #ident (
479-
_slf: *mut pyo3::ffi::PyObject,
480-
_args: *const *mut pyo3::ffi::PyObject,
481-
_nargs: pyo3::ffi::Py_ssize_t,
482-
_kwnames: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
479+
_slf: *mut ::pyo3::ffi::PyObject,
480+
_args: *const *mut ::pyo3::ffi::PyObject,
481+
_nargs: ::pyo3::ffi::Py_ssize_t,
482+
_kwnames: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
483483
{
484484
#deprecations
485-
pyo3::callback::handle_panic(|#py| {
485+
::pyo3::callback::handle_panic(|#py| {
486486
#self_conversion
487-
let _kwnames: Option<&pyo3::types::PyTuple> = #py.from_borrowed_ptr_or_opt(_kwnames);
487+
use ::std::option::Option;
488+
let _kwnames: Option<&::pyo3::types::PyTuple> = #py.from_borrowed_ptr_or_opt(_kwnames);
488489
// Safety: &PyAny has the same memory layout as `*mut ffi::PyObject`
489-
let _args = _args as *const &pyo3::PyAny;
490-
let _kwargs = if let Some(kwnames) = _kwnames {
491-
std::slice::from_raw_parts(_args.offset(_nargs), kwnames.len())
490+
let _args = _args as *const &::pyo3::PyAny;
491+
let _kwargs = if let Option::Some(kwnames) = _kwnames {
492+
::std::slice::from_raw_parts(_args.offset(_nargs), kwnames.len())
492493
} else {
493494
&[]
494495
};
495-
let _args = std::slice::from_raw_parts(_args, _nargs as usize);
496+
let _args = ::std::slice::from_raw_parts(_args, _nargs as usize);
496497

497498
#arg_convert_and_rust_call
498499
})
@@ -503,15 +504,15 @@ impl<'a> FnSpec<'a> {
503504
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, false)?;
504505
quote! {
505506
unsafe extern "C" fn #ident (
506-
_slf: *mut pyo3::ffi::PyObject,
507-
_args: *mut pyo3::ffi::PyObject,
508-
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
507+
_slf: *mut ::pyo3::ffi::PyObject,
508+
_args: *mut ::pyo3::ffi::PyObject,
509+
_kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
509510
{
510511
#deprecations
511-
pyo3::callback::handle_panic(|#py| {
512+
::pyo3::callback::handle_panic(|#py| {
512513
#self_conversion
513-
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
514-
let _kwargs: Option<&pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
514+
let _args = #py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args);
515+
let _kwargs: ::std::option::Option<&::pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
515516

516517
#arg_convert_and_rust_call
517518
})
@@ -523,20 +524,20 @@ impl<'a> FnSpec<'a> {
523524
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, false)?;
524525
quote! {
525526
unsafe extern "C" fn #ident (
526-
subtype: *mut pyo3::ffi::PyTypeObject,
527-
_args: *mut pyo3::ffi::PyObject,
528-
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
527+
subtype: *mut ::pyo3::ffi::PyTypeObject,
528+
_args: *mut ::pyo3::ffi::PyObject,
529+
_kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
529530
{
530531
#deprecations
531-
use pyo3::callback::IntoPyCallbackOutput;
532-
pyo3::callback::handle_panic(|#py| {
533-
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
534-
let _kwargs: Option<&pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
532+
use ::pyo3::callback::IntoPyCallbackOutput;
533+
::pyo3::callback::handle_panic(|#py| {
534+
let _args = #py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args);
535+
let _kwargs: ::std::option::Option<&::pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
535536

536537
let result = #arg_convert_and_rust_call;
537-
let initializer: pyo3::PyClassInitializer::<#cls> = result.convert(#py)?;
538+
let initializer: ::pyo3::PyClassInitializer::<#cls> = result.convert(#py)?;
538539
let cell = initializer.create_cell_from_subtype(#py, subtype)?;
539-
Ok(cell as *mut pyo3::ffi::PyObject)
540+
Ok(cell as *mut ::pyo3::ffi::PyObject)
540541
})
541542
}
542543
}
@@ -551,23 +552,23 @@ impl<'a> FnSpec<'a> {
551552
let doc = &self.doc;
552553
match self.convention {
553554
CallingConvention::Noargs => quote! {
554-
pyo3::class::methods::PyMethodDef::noargs(
555+
::pyo3::class::methods::PyMethodDef::noargs(
555556
#python_name,
556-
pyo3::class::methods::PyCFunction(#wrapper),
557+
::pyo3::class::methods::PyCFunction(#wrapper),
557558
#doc,
558559
)
559560
},
560561
CallingConvention::Fastcall => quote! {
561-
pyo3::class::methods::PyMethodDef::fastcall_cfunction_with_keywords(
562+
::pyo3::class::methods::PyMethodDef::fastcall_cfunction_with_keywords(
562563
#python_name,
563-
pyo3::class::methods::PyCFunctionFastWithKeywords(#wrapper),
564+
::pyo3::class::methods::PyCFunctionFastWithKeywords(#wrapper),
564565
#doc,
565566
)
566567
},
567568
CallingConvention::Varargs => quote! {
568-
pyo3::class::methods::PyMethodDef::cfunction_with_keywords(
569+
::pyo3::class::methods::PyMethodDef::cfunction_with_keywords(
569570
#python_name,
570-
pyo3::class::methods::PyCFunctionWithKeywords(#wrapper),
571+
::pyo3::class::methods::PyCFunctionWithKeywords(#wrapper),
571572
#doc,
572573
)
573574
},

pyo3-macros-backend/src/module.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,15 @@ pub fn py_init(fnname: &Ident, options: PyModuleOptions, doc: syn::LitStr) -> To
7373
#[allow(non_snake_case)]
7474
/// This autogenerated function is called by the python interpreter when importing
7575
/// the module.
76-
pub unsafe extern "C" fn #cb_name() -> *mut pyo3::ffi::PyObject {
77-
use pyo3::derive_utils::ModuleDef;
76+
pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject {
77+
use ::pyo3::derive_utils::ModuleDef;
7878
static NAME: &str = concat!(stringify!(#name), "\0");
7979
static DOC: &str = #doc;
8080
static MODULE_DEF: ModuleDef = unsafe { ModuleDef::new(NAME, DOC) };
8181

8282
#deprecations
8383

84-
pyo3::callback::handle_panic(|_py| { MODULE_DEF.make_module(_py, #fnname) })
84+
::pyo3::callback::handle_panic(|_py| { MODULE_DEF.make_module(_py, #fnname) })
8585
}
8686
}
8787
}

pyo3-macros-backend/src/params.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ pub fn impl_arg_params(
123123
let (accept_args, accept_kwargs) = accept_args_kwargs(&spec.attrs);
124124

125125
let cls_name = if let Some(cls) = self_ {
126-
quote! { Some(<#cls as pyo3::type_object::PyTypeInfo>::NAME) }
126+
quote! { ::std::option::Option::Some(<#cls as pyo3::type_object::PyTypeInfo>::NAME) }
127127
} else {
128-
quote! { None }
128+
quote! { ::std::option::Option::None }
129129
};
130130
let python_name = &spec.python_name;
131131

@@ -134,8 +134,9 @@ pub fn impl_arg_params(
134134
// keyword names of the keyword args in _kwargs
135135
(
136136
// need copied() for &&PyAny -> &PyAny
137-
quote! { _args.iter().copied() },
137+
quote! { ::std::iter::Iterator::copied(_args.iter()) },
138138
quote! { _kwnames.map(|kwnames| {
139+
use ::std::iter::Iterator;
139140
kwnames.as_slice().iter().copied().zip(_kwargs.iter().copied())
140141
}) },
141142
)
@@ -149,7 +150,7 @@ pub fn impl_arg_params(
149150

150151
// create array of arguments, and then parse
151152
Ok(quote! {{
152-
const DESCRIPTION: pyo3::derive_utils::FunctionDescription = pyo3::derive_utils::FunctionDescription {
153+
const DESCRIPTION: ::pyo3::derive_utils::FunctionDescription = ::pyo3::derive_utils::FunctionDescription {
153154
cls_name: #cls_name,
154155
func_name: stringify!(#python_name),
155156
positional_parameter_names: &[#(#positional_parameter_names),*],
@@ -161,7 +162,7 @@ pub fn impl_arg_params(
161162
accept_varkeywords: #accept_kwargs,
162163
};
163164

164-
let mut #args_array = [None; #num_params];
165+
let mut #args_array = [::std::option::Option::None; #num_params];
165166
let (_args, _kwargs) = DESCRIPTION.extract_arguments(
166167
#py,
167168
#args_to_extract,
@@ -201,7 +202,7 @@ fn impl_arg_param(
201202
let ty = arg.ty;
202203
let name = arg.name;
203204
let transform_error = quote! {
204-
|e| pyo3::derive_utils::argument_extraction_error(#py, stringify!(#name), e)
205+
|e| ::pyo3::derive_utils::argument_extraction_error(#py, stringify!(#name), e)
205206
};
206207

207208
if is_args(&spec.attrs, name) {

pyo3-macros-backend/src/pyfunction.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,9 @@ pub fn impl_wrap_pyfunction(
433433
let wrapped_pyfunction = quote! {
434434
#wrapper
435435
pub(crate) fn #function_wrapper_ident<'a>(
436-
args: impl Into<pyo3::derive_utils::PyFunctionArguments<'a>>
437-
) -> pyo3::PyResult<&'a pyo3::types::PyCFunction> {
438-
pyo3::types::PyCFunction::internal_new(#methoddef, args.into())
436+
args: impl ::std::convert::Into<::pyo3::derive_utils::PyFunctionArguments<'a>>
437+
) -> ::pyo3::PyResult<&'a ::pyo3::types::PyCFunction> {
438+
::pyo3::types::PyCFunction::internal_new(#methoddef, args.into())
439439
}
440440
};
441441
Ok((function_wrapper_ident, wrapped_pyfunction))

src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,13 @@ pub mod proc_macro {
358358
#[macro_export]
359359
macro_rules! wrap_pyfunction {
360360
($function_name: ident) => {{
361-
&|py| pyo3::paste::expr! { [<__pyo3_get_function_ $function_name>] }(py)
361+
&|py| $crate::paste::expr! { [<__pyo3_get_function_ $function_name>] }(py)
362362
}};
363363

364364
($function_name: ident, $arg: expr) => {
365-
pyo3::wrap_pyfunction!($function_name)(pyo3::derive_utils::PyFunctionArguments::from($arg))
365+
$crate::wrap_pyfunction!($function_name)(
366+
<$crate::derive_utils::PyFunctionArguments as ::std::convert::From<_>>::from($arg),
367+
)
366368
};
367369
}
368370

@@ -372,8 +374,8 @@ macro_rules! wrap_pyfunction {
372374
#[macro_export]
373375
macro_rules! wrap_pymodule {
374376
($module_name:ident) => {{
375-
pyo3::paste::expr! {
376-
&|py| unsafe { pyo3::PyObject::from_owned_ptr(py, [<PyInit_ $module_name>]()) }
377+
$crate::paste::expr! {
378+
&|py| unsafe { $crate::PyObject::from_owned_ptr(py, [<PyInit_ $module_name>]()) }
377379
}
378380
}};
379381
}
@@ -479,14 +481,15 @@ macro_rules! py_run_impl {
479481
$crate::py_run_impl!($py, *d, $code)
480482
}};
481483
($py:expr, *$dict:expr, $code:expr) => {{
482-
if let Err(e) = $py.run($code, None, Some($dict)) {
484+
use ::std::option::Option::*;
485+
if let ::std::result::Result::Err(e) = $py.run($code, None, Some($dict)) {
483486
e.print($py);
484487
// So when this c api function the last line called printed the error to stderr,
485488
// the output is only written into a buffer which is never flushed because we
486489
// panic before flushing. This is where this hack comes into place
487490
$py.run("import sys; sys.stderr.flush()", None, None)
488491
.unwrap();
489-
panic!("{}", $code)
492+
::std::panic!("{}", $code)
490493
}
491494
}};
492495
}

tests/test_proc_macro_hygiene.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,22 @@ impl ::pyo3::class::gc::PyGCProtocol for Bar {
4242
self.c = ::std::option::Option::None;
4343
}
4444
}
45+
46+
#[::pyo3::proc_macro::pyfunction]
47+
fn do_something(x: i32) -> ::pyo3::PyResult<i32> {
48+
::std::result::Result::Ok(x)
49+
}
50+
51+
#[::pyo3::proc_macro::pymodule]
52+
fn my_module(_py: ::pyo3::Python, m: &::pyo3::types::PyModule) -> ::pyo3::PyResult<()> {
53+
m.add_function(::pyo3::wrap_pyfunction!(do_something, m)?)?;
54+
::std::result::Result::Ok(())
55+
}
56+
57+
#[test]
58+
fn invoke_wrap_pyfunction() {
59+
::pyo3::Python::with_gil(|py| {
60+
let func = ::pyo3::wrap_pyfunction!(do_something)(py).unwrap();
61+
::pyo3::py_run!(py, func, r#"func(5)"#);
62+
});
63+
}

0 commit comments

Comments
 (0)