From 585487c3c1085c37ad4c1f6d0b23b8212b5c79c2 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 28 Aug 2021 16:02:43 +0200 Subject: [PATCH] more macro hygiene cleanup: test the FromPyObject derive macro --- pyo3-macros-backend/src/from_pyobject.rs | 66 ++++++++++++------------ tests/test_proc_macro_hygiene.rs | 21 ++++++++ 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/pyo3-macros-backend/src/from_pyobject.rs b/pyo3-macros-backend/src/from_pyobject.rs index 460349df..43e1c55b 100644 --- a/pyo3-macros-backend/src/from_pyobject.rs +++ b/pyo3-macros-backend/src/from_pyobject.rs @@ -55,15 +55,15 @@ impl<'a> Enum<'a> { for (i, var) in self.variants.iter().enumerate() { let struct_derive = var.build(); let ext = quote!( - let maybe_ret = || -> pyo3::PyResult { + let maybe_ret = || -> ::pyo3::PyResult { #struct_derive }(); match maybe_ret { - ok @ Ok(_) => return ok, - Err(inner) => { - let py = pyo3::PyNativeType::py(obj); - err_reasons.push_str(&format!("{}\n", inner.instance(py).str().unwrap())); + ok @ ::std::result::Result::Ok(_) => return ok, + ::std::result::Result::Err(inner) => { + let py = ::pyo3::PyNativeType::py(obj); + err_reasons.push_str(&::std::format!("{}\n", inner.instance(py).str().unwrap())); } } ); @@ -81,13 +81,13 @@ impl<'a> Enum<'a> { }; let ty_name = self.enum_ident.to_string(); quote!( - let mut err_reasons = String::new(); + let mut err_reasons = ::std::string::String::new(); #(#var_extracts)* - let err_msg = format!("failed to extract enum {} ('{}')\n{}", + let err_msg = ::std::format!("failed to extract enum {} ('{}')\n{}", #ty_name, #error_names, &err_reasons); - Err(pyo3::exceptions::PyTypeError::new_err(err_msg)) + ::std::result::Result::Err(::pyo3::exceptions::PyTypeError::new_err(err_msg)) ) } } @@ -211,10 +211,10 @@ impl<'a> Container<'a> { quote!(#ident) ); quote!( - Ok(#self_ty{#ident: obj.extract().map_err(|inner| { - let py = pyo3::PyNativeType::py(obj); - let new_err = pyo3::exceptions::PyTypeError::new_err(#error_msg); - new_err.set_cause(py, Some(inner)); + ::std::result::Result::Ok(#self_ty{#ident: obj.extract().map_err(|inner| { + let py = ::pyo3::PyNativeType::py(obj); + let new_err = ::pyo3::exceptions::PyTypeError::new_err(#error_msg); + new_err.set_cause(py, ::std::option::Option::Some(inner)); new_err })?}) ) @@ -226,12 +226,12 @@ impl<'a> Container<'a> { format!("failed to extract inner field of {}", quote!(#self_ty)) }; quote!( - Ok(#self_ty(obj.extract().map_err(|inner| { - let py = pyo3::PyNativeType::py(obj); - let err_msg = format!("{}: {}", + ::std::result::Result::Ok(#self_ty(obj.extract().map_err(|inner| { + let py = ::pyo3::PyNativeType::py(obj); + let err_msg = ::std::format!("{}: {}", #error_msg, inner.instance(py).str().unwrap()); - pyo3::exceptions::PyTypeError::new_err(err_msg) + ::pyo3::exceptions::PyTypeError::new_err(err_msg) })?)) ) } @@ -243,15 +243,15 @@ impl<'a> Container<'a> { for i in 0..len { let error_msg = format!("failed to extract field {}.{}", quote!(#self_ty), i); fields.push(quote!( - s.get_item(#i).and_then(PyAny::extract).map_err(|inner| { - let py = pyo3::PyNativeType::py(obj); - let new_err = pyo3::exceptions::PyTypeError::new_err(#error_msg); - new_err.set_cause(py, Some(inner)); + s.get_item(#i).and_then(::pyo3::types::PyAny::extract).map_err(|inner| { + let py = ::pyo3::PyNativeType::py(obj); + let new_err = ::pyo3::exceptions::PyTypeError::new_err(#error_msg); + new_err.set_cause(py, ::std::option::Option::Some(inner)); new_err })?)); } let msg = if self.is_enum_variant { - quote!(format!( + quote!(::std::format!( "expected tuple of length {}, but got length {}", #len, s.len() @@ -260,11 +260,11 @@ impl<'a> Container<'a> { quote!("") }; quote!( - let s = ::try_from(obj)?; + let s = <::pyo3::types::PyTuple as ::pyo3::conversion::PyTryFrom>::try_from(obj)?; if s.len() != #len { - return Err(pyo3::exceptions::PyValueError::new_err(#msg)) + return ::std::result::Result::Err(::pyo3::exceptions::PyValueError::new_err(#msg)) } - Ok(#self_ty(#fields)) + ::std::result::Result::Ok(#self_ty(#fields)) ) } @@ -284,16 +284,16 @@ impl<'a> Container<'a> { let extractor = match &attrs.from_py_with { None => quote!( #get_field.extract().map_err(|inner| { - let py = pyo3::PyNativeType::py(obj); - let new_err = pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg); - new_err.set_cause(py, Some(inner)); + let py = ::pyo3::PyNativeType::py(obj); + let new_err = ::pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg); + new_err.set_cause(py, ::std::option::Option::Some(inner)); new_err })?), Some(FromPyWithAttribute(expr_path)) => quote! ( #expr_path(#get_field).map_err(|inner| { - let py = pyo3::PyNativeType::py(obj); - let new_err = pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg); - new_err.set_cause(py, Some(inner)); + let py = ::pyo3::PyNativeType::py(obj); + let new_err = ::pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg); + new_err.set_cause(py, ::std::option::Option::Some(inner)); new_err })? ), @@ -301,7 +301,7 @@ impl<'a> Container<'a> { fields.push(quote!(#ident: #extractor)); } - quote!(Ok(#self_ty{#fields})) + quote!(::std::result::Result::Ok(#self_ty{#fields})) } } @@ -527,8 +527,8 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result { let ident = &tokens.ident; Ok(quote!( #[automatically_derived] - impl#trait_generics pyo3::FromPyObject<#lt_param> for #ident#generics #where_clause { - fn extract(obj: &#lt_param pyo3::PyAny) -> pyo3::PyResult { + impl#trait_generics ::pyo3::FromPyObject<#lt_param> for #ident#generics #where_clause { + fn extract(obj: &#lt_param ::pyo3::PyAny) -> ::pyo3::PyResult { #derives } } diff --git a/tests/test_proc_macro_hygiene.rs b/tests/test_proc_macro_hygiene.rs index ac54e557..72d6444d 100644 --- a/tests/test_proc_macro_hygiene.rs +++ b/tests/test_proc_macro_hygiene.rs @@ -1,5 +1,26 @@ #![no_implicit_prelude] +#[derive(::pyo3::prelude::FromPyObject)] +struct Derive1(i32); // newtype case + +#[derive(::pyo3::prelude::FromPyObject)] +#[allow(dead_code)] +struct Derive2(i32, i32); // tuple case + +#[derive(::pyo3::prelude::FromPyObject)] +#[allow(dead_code)] +struct Derive3 { + f: i32, + g: i32, +} // struct case + +#[derive(::pyo3::prelude::FromPyObject)] +#[allow(dead_code)] +enum Derive4 { + A(i32), + B { f: i32 }, +} // enum case + #[::pyo3::proc_macro::pyclass] #[derive(::std::clone::Clone)] pub struct Foo;