From 5667a095d61189c6bf95cd75965a077dc62c5382 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Fri, 27 Jan 2023 06:34:12 +0000 Subject: [PATCH 1/2] hygiene: fix `#[pymethods(crate = "...")]` --- newsfragments/2923.fixed.md | 1 + pyo3-macros/src/lib.rs | 15 ++++++++++++--- src/test_hygiene/pymethods.rs | 8 ++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 newsfragments/2923.fixed.md diff --git a/newsfragments/2923.fixed.md b/newsfragments/2923.fixed.md new file mode 100644 index 00000000..d61f5b01 --- /dev/null +++ b/newsfragments/2923.fixed.md @@ -0,0 +1 @@ +Fix `#[pymethods(crate = "...")]` option being ignored. diff --git a/pyo3-macros/src/lib.rs b/pyo3-macros/src/lib.rs index 730aaf65..38793431 100644 --- a/pyo3-macros/src/lib.rs +++ b/pyo3-macros/src/lib.rs @@ -109,13 +109,13 @@ pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream { /// [10]: https://pyo3.rs/latest/class.html#method-arguments /// [11]: https://pyo3.rs/latest/class.html#object-properties-using-pyo3get-set #[proc_macro_attribute] -pub fn pymethods(_: TokenStream, input: TokenStream) -> TokenStream { +pub fn pymethods(attr: TokenStream, input: TokenStream) -> TokenStream { let methods_type = if cfg!(feature = "multiple-pymethods") { PyClassMethodsType::Inventory } else { PyClassMethodsType::Specialization }; - pymethods_impl(input, methods_type) + pymethods_impl(attr, input, methods_type) } /// A proc macro used to expose Rust functions to Python. @@ -191,8 +191,17 @@ fn pyclass_enum_impl( .into() } -fn pymethods_impl(input: TokenStream, methods_type: PyClassMethodsType) -> TokenStream { +fn pymethods_impl( + attr: TokenStream, + input: TokenStream, + methods_type: PyClassMethodsType, +) -> TokenStream { let mut ast = parse_macro_input!(input as syn::ItemImpl); + // Apply all options as a #[pyo3] attribute on the ItemImpl + // e.g. #[pymethods(crate = "crate")] impl Foo { } + // -> #[pyo3(crate = "crate")] impl Foo { } + let attr: TokenStream2 = attr.into(); + ast.attrs.push(syn::parse_quote!( #[pyo3(#attr)] )); let expanded = build_py_methods(&mut ast, methods_type).unwrap_or_compile_error(); quote!( diff --git a/src/test_hygiene/pymethods.rs b/src/test_hygiene/pymethods.rs index eb0b12f7..ba0fcdff 100644 --- a/src/test_hygiene/pymethods.rs +++ b/src/test_hygiene/pymethods.rs @@ -807,3 +807,11 @@ impl Dummy { // PyGcProtocol // Buffer protocol? } + +// Ensure that crate argument is also accepted inline + +#[crate::pyclass(crate = "crate")] +struct Dummy2; + +#[crate::pymethods(crate = "crate")] +impl Dummy2 {} From 1a4153f71831f8b7955efa93005ae2c960503e46 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Fri, 27 Jan 2023 08:20:03 +0000 Subject: [PATCH 2/2] remove unneeded into_iter calls --- benches/bench_set.rs | 2 +- pyo3-macros-backend/src/frompyobject.rs | 1 - pyo3-macros-backend/src/pymethod.rs | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/benches/bench_set.rs b/benches/bench_set.rs index d59e3e57..58abc956 100644 --- a/benches/bench_set.rs +++ b/benches/bench_set.rs @@ -9,7 +9,7 @@ fn set_new(b: &mut Bencher<'_>) { const LEN: usize = 100_000; // Create Python objects up-front, so that the benchmark doesn't need to include // the cost of allocating LEN Python integers - let elements: Vec = (0..LEN).into_iter().map(|i| i.into_py(py)).collect(); + let elements: Vec = (0..LEN).map(|i| i.into_py(py)).collect(); b.iter(|| { let pool = unsafe { py.new_pool() }; PySet::new(py, &elements).unwrap(); diff --git a/pyo3-macros-backend/src/frompyobject.rs b/pyo3-macros-backend/src/frompyobject.rs index ba365efe..831aed25 100644 --- a/pyo3-macros-backend/src/frompyobject.rs +++ b/pyo3-macros-backend/src/frompyobject.rs @@ -278,7 +278,6 @@ impl<'a> Container<'a> { let self_ty = &self.path; let struct_name = &self.name(); let field_idents: Vec<_> = (0..struct_fields.len()) - .into_iter() .map(|i| format_ident!("arg{}", i)) .collect(); let fields = struct_fields.iter().zip(&field_idents).enumerate().map(|(index, (field, ident))| { diff --git a/pyo3-macros-backend/src/pymethod.rs b/pyo3-macros-backend/src/pymethod.rs index fa81c6d4..3807a1fd 100644 --- a/pyo3-macros-backend/src/pymethod.rs +++ b/pyo3-macros-backend/src/pymethod.rs @@ -1109,7 +1109,6 @@ impl SlotDef { let py = syn::Ident::new("_py", Span::call_site()); let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect(); let arg_idents: &Vec<_> = &(0..arguments.len()) - .into_iter() .map(|i| format_ident!("arg{}", i)) .collect(); let wrapper_ident = format_ident!("__pymethod_{}__", method_name); @@ -1220,7 +1219,6 @@ impl SlotFragmentDef { let py = syn::Ident::new("_py", Span::call_site()); let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect(); let arg_idents: &Vec<_> = &(0..arguments.len()) - .into_iter() .map(|i| format_ident!("arg{}", i)) .collect(); let body = generate_method_body(cls, spec, &py, arguments, *extract_error_mode, None)?;