diff --git a/CHANGELOG.md b/CHANGELOG.md index d8410117..f654661a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009) - Add `PyCapsule`, exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980) -- All PyO3 proc-macros except the deprecated `#[pyproto]` now accept a supplemental attribute `#[pyo3(pyo3_path = "some::path")]` that specifies +- All PyO3 proc-macros except the deprecated `#[pyproto]` now accept a supplemental attribute `#[pyo3(crate = "some::path")]` that specifies where to find the `pyo3` crate, in case it has been renamed or is re-exported and not found at the crate root. [#2022](https://github.com/PyO3/pyo3/pull/2022) ### Changed diff --git a/guide/src/faq.md b/guide/src/faq.md index c3ad931d..42cb5b27 100644 --- a/guide/src/faq.md +++ b/guide/src/faq.md @@ -149,13 +149,13 @@ crate. However, when the dependency is renamed, or your crate only indirectly depends on `pyo3`, you need to let the macro code know where to find the crate. This is -done with the `pyo3_path` attribute: +done with the `crate` attribute: ```rust # use pyo3::prelude::*; # pub extern crate pyo3; # mod reexported { pub use ::pyo3; } #[pyclass] -#[pyo3(pyo3_path = "reexported::pyo3")] +#[pyo3(crate = "reexported::pyo3")] struct MyClass; ``` diff --git a/pyo3-macros-backend/src/attributes.rs b/pyo3-macros-backend/src/attributes.rs index 3971b05f..16c1c611 100644 --- a/pyo3-macros-backend/src/attributes.rs +++ b/pyo3-macros-backend/src/attributes.rs @@ -17,7 +17,6 @@ pub mod kw { syn::custom_keyword!(signature); syn::custom_keyword!(text_signature); syn::custom_keyword!(transparent); - syn::custom_keyword!(pyo3_path); } #[derive(Clone, Debug, PartialEq)] @@ -50,7 +49,7 @@ pub struct PyO3PathAttribute(pub Path); impl Parse for PyO3PathAttribute { fn parse(input: ParseStream) -> Result { - let _: kw::pyo3_path = input.parse()?; + let _: Token![crate] = input.parse()?; let _: Token![=] = input.parse()?; let string_literal: LitStr = input.parse()?; string_literal.parse().map(PyO3PathAttribute) diff --git a/pyo3-macros-backend/src/from_pyobject.rs b/pyo3-macros-backend/src/from_pyobject.rs index 661ee9f7..c896532c 100644 --- a/pyo3-macros-backend/src/from_pyobject.rs +++ b/pyo3-macros-backend/src/from_pyobject.rs @@ -334,7 +334,7 @@ impl Parse for ContainerPyO3Attribute { let _: attributes::kw::annotation = input.parse()?; let _: Token![=] = input.parse()?; input.parse().map(ContainerPyO3Attribute::ErrorAnnotation) - } else if lookahead.peek(attributes::kw::pyo3_path) { + } else if lookahead.peek(Token![crate]) { input.parse().map(ContainerPyO3Attribute::PyO3Path) } else { Err(lookahead.error()) diff --git a/pyo3-macros-backend/src/module.rs b/pyo3-macros-backend/src/module.rs index 2475f8d6..8873982d 100644 --- a/pyo3-macros-backend/src/module.rs +++ b/pyo3-macros-backend/src/module.rs @@ -170,7 +170,7 @@ impl Parse for PyModulePyO3Option { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(PyModulePyO3Option::Name) - } else if lookahead.peek(attributes::kw::pyo3_path) { + } else if lookahead.peek(syn::Token![crate]) { input.parse().map(PyModulePyO3Option::PyO3Path) } else { Err(lookahead.error()) diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index c1bb2a44..c2cabc18 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -201,7 +201,7 @@ impl Parse for PyClassPyO3Option { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::text_signature) { input.parse().map(PyClassPyO3Option::TextSignature) - } else if lookahead.peek(attributes::kw::pyo3_path) { + } else if lookahead.peek(Token![crate]) { input.parse().map(PyClassPyO3Option::PyO3Path) } else { Err(lookahead.error()) diff --git a/pyo3-macros-backend/src/pyfunction.rs b/pyo3-macros-backend/src/pyfunction.rs index 9f6f5bf3..4b5f31f6 100644 --- a/pyo3-macros-backend/src/pyfunction.rs +++ b/pyo3-macros-backend/src/pyfunction.rs @@ -257,7 +257,7 @@ impl Parse for PyFunctionOptions { if !input.is_empty() { let _: Comma = input.parse()?; } - } else if lookahead.peek(attributes::kw::pyo3_path) { + } else if lookahead.peek(syn::Token![crate]) { // TODO needs duplicate check? options.pyo3_path = Some(input.parse()?); } else { @@ -292,7 +292,7 @@ impl Parse for PyFunctionOption { input.parse().map(PyFunctionOption::Signature) } else if lookahead.peek(attributes::kw::text_signature) { input.parse().map(PyFunctionOption::TextSignature) - } else if lookahead.peek(attributes::kw::pyo3_path) { + } else if lookahead.peek(syn::Token![crate]) { input.parse().map(PyFunctionOption::PyO3Path) } else { Err(lookahead.error()) diff --git a/pyo3-macros-backend/src/pyimpl.rs b/pyo3-macros-backend/src/pyimpl.rs index ce2e775f..72320f1e 100644 --- a/pyo3-macros-backend/src/pyimpl.rs +++ b/pyo3-macros-backend/src/pyimpl.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use crate::{ - attributes::{self, take_pyo3_options, PyO3PathAttribute}, + attributes::{take_pyo3_options, PyO3PathAttribute}, konst::{ConstAttributes, ConstSpec}, pyfunction::PyFunctionOptions, pymethod::{self, is_proto_method}, @@ -32,7 +32,7 @@ enum PyImplPyO3Option { impl Parse for PyImplPyO3Option { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); - if lookahead.peek(attributes::kw::pyo3_path) { + if lookahead.peek(syn::Token![crate]) { input.parse().map(PyImplPyO3Option::PyO3Path) } else { Err(lookahead.error()) diff --git a/src/test_hygiene/misc.rs b/src/test_hygiene/misc.rs index 75fe8fb8..eb49718e 100644 --- a/src/test_hygiene/misc.rs +++ b/src/test_hygiene/misc.rs @@ -1,16 +1,16 @@ #![no_implicit_prelude] #[derive(crate::FromPyObject)] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] struct Derive1(i32); // newtype case #[derive(crate::FromPyObject)] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] #[allow(dead_code)] struct Derive2(i32, i32); // tuple case #[derive(crate::FromPyObject)] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] #[allow(dead_code)] struct Derive3 { f: i32, @@ -18,7 +18,7 @@ struct Derive3 { } // struct case #[derive(crate::FromPyObject)] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] #[allow(dead_code)] enum Derive4 { A(i32), diff --git a/src/test_hygiene/pyclass.rs b/src/test_hygiene/pyclass.rs index 9649c4b7..adadc08c 100644 --- a/src/test_hygiene/pyclass.rs +++ b/src/test_hygiene/pyclass.rs @@ -2,12 +2,12 @@ #![allow(unused_variables)] #[crate::pyclass] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] #[derive(::std::clone::Clone)] pub struct Foo; #[crate::pyclass] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] pub struct Foo2; #[crate::pyclass( @@ -19,7 +19,7 @@ pub struct Foo2; extends = crate::types::PyAny, module = "Spam" )] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] pub struct Bar { #[pyo3(get, set)] a: u8, diff --git a/src/test_hygiene/pyfunction.rs b/src/test_hygiene/pyfunction.rs index b9534589..9a7d515e 100644 --- a/src/test_hygiene/pyfunction.rs +++ b/src/test_hygiene/pyfunction.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] #[crate::pyfunction] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } diff --git a/src/test_hygiene/pymethods.rs b/src/test_hygiene/pymethods.rs index fe4f792e..832e7239 100644 --- a/src/test_hygiene/pymethods.rs +++ b/src/test_hygiene/pymethods.rs @@ -2,15 +2,15 @@ #![allow(unused_variables)] #[crate::pyclass] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] pub struct Dummy; #[crate::pyclass] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] pub struct DummyIter; #[crate::pymethods] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] impl Dummy { ////////////////////// // Basic customization diff --git a/src/test_hygiene/pymodule.rs b/src/test_hygiene/pymodule.rs index d6427512..478cea3a 100644 --- a/src/test_hygiene/pymodule.rs +++ b/src/test_hygiene/pymodule.rs @@ -2,19 +2,19 @@ #![allow(unused_variables)] #[crate::pyfunction] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[crate::pymodule] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] fn foo(_py: crate::Python, _m: &crate::types::PyModule) -> crate::PyResult<()> { ::std::result::Result::Ok(()) } #[crate::pymodule] -#[pyo3(pyo3_path = "crate")] +#[pyo3(crate = "crate")] fn my_module(_py: crate::Python, m: &crate::types::PyModule) -> crate::PyResult<()> { m.add_function(crate::wrap_pyfunction!(do_something, m)?)?; m.add_wrapped(crate::wrap_pymodule!(foo))?; diff --git a/tests/ui/invalid_frompy_derive.stderr b/tests/ui/invalid_frompy_derive.stderr index e989a9ea..04280d73 100644 --- a/tests/ui/invalid_frompy_derive.stderr +++ b/tests/ui/invalid_frompy_derive.stderr @@ -132,7 +132,7 @@ error: only one of `attribute` or `item` can be provided 118 | #[pyo3(item, attribute)] | ^ -error: expected one of: `transparent`, `annotation`, `pyo3_path` +error: expected one of: `transparent`, `annotation`, `crate` --> tests/ui/invalid_frompy_derive.rs:123:8 | 123 | #[pyo3(unknown = "should not work")]