diff --git a/pyo3-macros-backend/src/attributes.rs b/pyo3-macros-backend/src/attributes.rs index e91b3b8d9a2..d9c805aa3fa 100644 --- a/pyo3-macros-backend/src/attributes.rs +++ b/pyo3-macros-backend/src/attributes.rs @@ -12,6 +12,7 @@ pub mod kw { syn::custom_keyword!(annotation); syn::custom_keyword!(attribute); syn::custom_keyword!(cancel_handle); + syn::custom_keyword!(constructor); syn::custom_keyword!(dict); syn::custom_keyword!(extends); syn::custom_keyword!(freelist); diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index ff87075b376..2939941d2a8 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -8,7 +8,7 @@ use crate::attributes::{ use crate::deprecations::Deprecations; use crate::konst::{ConstAttributes, ConstSpec}; use crate::method::{FnArg, FnSpec, PyArg, RegularArg}; -use crate::pyfunction::SignatureAttribute; +use crate::pyfunction::ConstructorAttribute; use crate::pyimpl::{gen_py_const, PyClassMethodsType}; use crate::pymethod::{ impl_py_getter_def, impl_py_setter_def, MethodAndMethodDef, MethodAndSlotDef, PropertyType, @@ -623,12 +623,12 @@ struct PyClassEnumVariantNamedField<'a> { /// `#[pyo3()]` options for pyclass enum variants struct EnumVariantPyO3Options { name: Option, - signature: Option, + constructor: Option, } enum EnumVariantPyO3Option { Name(NameAttribute), - Signature(SignatureAttribute), + Constructor(ConstructorAttribute), } impl Parse for EnumVariantPyO3Option { @@ -636,8 +636,8 @@ impl Parse for EnumVariantPyO3Option { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(EnumVariantPyO3Option::Name) - } else if lookahead.peek(attributes::kw::signature) { - input.parse().map(EnumVariantPyO3Option::Signature) + } else if lookahead.peek(attributes::kw::constructor) { + input.parse().map(EnumVariantPyO3Option::Constructor) } else { Err(lookahead.error()) } @@ -648,7 +648,7 @@ impl EnumVariantPyO3Options { fn take_pyo3_options(attrs: &mut Vec) -> Result { let mut options = EnumVariantPyO3Options { name: None, - signature: None, + constructor: None, }; for option in take_pyo3_options(attrs)? { @@ -660,12 +660,12 @@ impl EnumVariantPyO3Options { ); options.name = Some(name); } - EnumVariantPyO3Option::Signature(signature) => { + EnumVariantPyO3Option::Constructor(constructor) => { ensure_spanned!( - options.signature.is_none(), - signature.span() => "`signature` may only be specified once" + options.constructor.is_none(), + constructor.span() => "`constructor` may only be specified once" ); - options.signature = Some(signature); + options.constructor = Some(constructor); } } } @@ -706,7 +706,7 @@ fn impl_simple_enum( let (default_repr, default_repr_slot) = { let variants_repr = variants.iter().map(|variant| { - ensure_spanned!(variant.options.signature.is_none(), variant.options.signature.span() => "`signature` can't be used on a simple enum variant"); + ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => "`constructor` can't be used on a simple enum variant"); let variant_name = variant.ident; // Assuming all variants are unit variants because they are the only type we support. let repr = format!( @@ -1179,8 +1179,11 @@ fn complex_enum_struct_variant_new<'a>( args }; - let signature = if let Some(signature) = variant.options.signature { - crate::pyfunction::FunctionSignature::from_arguments_and_attribute(args, signature)? + let signature = if let Some(constructor) = variant.options.constructor { + crate::pyfunction::FunctionSignature::from_arguments_and_attribute( + args, + constructor.into_signature(), + )? } else { crate::pyfunction::FunctionSignature::from_arguments(args)? }; diff --git a/pyo3-macros-backend/src/pyfunction.rs b/pyo3-macros-backend/src/pyfunction.rs index 7c355533b83..e259f0e2c1e 100644 --- a/pyo3-macros-backend/src/pyfunction.rs +++ b/pyo3-macros-backend/src/pyfunction.rs @@ -18,7 +18,7 @@ use syn::{ mod signature; -pub use self::signature::{FunctionSignature, SignatureAttribute}; +pub use self::signature::{ConstructorAttribute, FunctionSignature, SignatureAttribute}; #[derive(Clone, Debug)] pub struct PyFunctionArgPyO3Attributes { diff --git a/pyo3-macros-backend/src/pyfunction/signature.rs b/pyo3-macros-backend/src/pyfunction/signature.rs index 3daa79c89f5..b73b96a3d59 100644 --- a/pyo3-macros-backend/src/pyfunction/signature.rs +++ b/pyo3-macros-backend/src/pyfunction/signature.rs @@ -195,6 +195,16 @@ impl ToTokens for SignatureItemPosargsSep { } pub type SignatureAttribute = KeywordAttribute; +pub type ConstructorAttribute = KeywordAttribute; + +impl ConstructorAttribute { + pub fn into_signature(self) -> SignatureAttribute { + SignatureAttribute { + kw: kw::signature(self.kw.span), + value: self.value, + } + } +} #[derive(Default)] pub struct PythonSignature { diff --git a/pytests/src/enums.rs b/pytests/src/enums.rs index bef0e0bc7f4..68a5fc93dfe 100644 --- a/pytests/src/enums.rs +++ b/pytests/src/enums.rs @@ -54,7 +54,7 @@ pub enum ComplexEnum { b: f64, c: bool, }, - #[pyo3(signature = (a = 42, b = None))] + #[pyo3(constructor = (a = 42, b = None))] VariantWithDefault { a: i32, b: Option, diff --git a/tests/ui/invalid_pyclass_enum.rs b/tests/ui/invalid_pyclass_enum.rs index f057bbf5873..116b8968da8 100644 --- a/tests/ui/invalid_pyclass_enum.rs +++ b/tests/ui/invalid_pyclass_enum.rs @@ -29,7 +29,7 @@ enum NoTupleVariants { #[pyclass] enum SimpleNoSignature { - #[pyo3(signature = (a, b))] + #[pyo3(constructor = (a, b))] A, B, } diff --git a/tests/ui/invalid_pyclass_enum.stderr b/tests/ui/invalid_pyclass_enum.stderr index 75aafa7e0f7..e9ba9806da8 100644 --- a/tests/ui/invalid_pyclass_enum.stderr +++ b/tests/ui/invalid_pyclass_enum.stderr @@ -32,8 +32,8 @@ error: Tuple variant `TupleVariant` is not yet supported in a complex enum 27 | TupleVariant(i32), | ^^^^^^^^^^^^ -error: `signature` can't be used on a simple enum variant +error: `constructor` can't be used on a simple enum variant --> tests/ui/invalid_pyclass_enum.rs:32:12 | -32 | #[pyo3(signature = (a, b))] - | ^^^^^^^^^ +32 | #[pyo3(constructor = (a, b))] + | ^^^^^^^^^^^