2923: hygiene: fix `#[pymethods(crate = "...")]` r=davidhewitt a=davidhewitt

Got to the bottom of the hygiene issue in test of #2914 

Turns out that `#[pymethods] #[pyo3(crate = "...")]` works, but `#[pymethods(crate = "...")]` was ignoring the argument.

Added a tweak to fix this and a snippet in the hygiene test (which fails on `main`). 

2924: remove unneeded into_iter calls r=davidhewitt a=davidhewitt

Clippy complaining about these to me this morning locally.

Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
This commit is contained in:
bors[bot] 2023-01-27 09:31:20 +00:00 committed by GitHub
commit d118ee3a73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 22 additions and 7 deletions

View file

@ -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<PyObject> = (0..LEN).into_iter().map(|i| i.into_py(py)).collect();
let elements: Vec<PyObject> = (0..LEN).map(|i| i.into_py(py)).collect();
b.iter(|| {
let pool = unsafe { py.new_pool() };
PySet::new(py, &elements).unwrap();

View file

@ -0,0 +1 @@
Fix `#[pymethods(crate = "...")]` option being ignored.

View file

@ -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))| {

View file

@ -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)?;

View file

@ -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!(

View file

@ -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 {}