@@ -8,6 +8,7 @@ use crate::attributes::{
8
8
use crate :: deprecations:: Deprecations ;
9
9
use crate :: konst:: { ConstAttributes , ConstSpec } ;
10
10
use crate :: method:: { FnArg , FnSpec , PyArg , RegularArg } ;
11
+ use crate :: pyfunction:: SignatureAttribute ;
11
12
use crate :: pyimpl:: { gen_py_const, PyClassMethodsType } ;
12
13
use crate :: pymethod:: {
13
14
impl_py_getter_def, impl_py_setter_def, MethodAndMethodDef , MethodAndSlotDef , PropertyType ,
@@ -622,17 +623,21 @@ struct PyClassEnumVariantNamedField<'a> {
622
623
/// `#[pyo3()]` options for pyclass enum variants
623
624
struct EnumVariantPyO3Options {
624
625
name : Option < NameAttribute > ,
626
+ signature : Option < SignatureAttribute > ,
625
627
}
626
628
627
629
enum EnumVariantPyO3Option {
628
630
Name ( NameAttribute ) ,
631
+ Signature ( SignatureAttribute ) ,
629
632
}
630
633
631
634
impl Parse for EnumVariantPyO3Option {
632
635
fn parse ( input : ParseStream < ' _ > ) -> Result < Self > {
633
636
let lookahead = input. lookahead1 ( ) ;
634
637
if lookahead. peek ( attributes:: kw:: name) {
635
638
input. parse ( ) . map ( EnumVariantPyO3Option :: Name )
639
+ } else if lookahead. peek ( attributes:: kw:: signature) {
640
+ input. parse ( ) . map ( EnumVariantPyO3Option :: Signature )
636
641
} else {
637
642
Err ( lookahead. error ( ) )
638
643
}
@@ -641,7 +646,10 @@ impl Parse for EnumVariantPyO3Option {
641
646
642
647
impl EnumVariantPyO3Options {
643
648
fn take_pyo3_options ( attrs : & mut Vec < syn:: Attribute > ) -> Result < Self > {
644
- let mut options = EnumVariantPyO3Options { name : None } ;
649
+ let mut options = EnumVariantPyO3Options {
650
+ name : None ,
651
+ signature : None ,
652
+ } ;
645
653
646
654
for option in take_pyo3_options ( attrs) ? {
647
655
match option {
@@ -652,6 +660,13 @@ impl EnumVariantPyO3Options {
652
660
) ;
653
661
options. name = Some ( name) ;
654
662
}
663
+ EnumVariantPyO3Option :: Signature ( signature) => {
664
+ ensure_spanned ! (
665
+ options. signature. is_none( ) ,
666
+ signature. span( ) => "`signature` may only be specified once"
667
+ ) ;
668
+ options. signature = Some ( signature) ;
669
+ }
655
670
}
656
671
}
657
672
@@ -691,19 +706,20 @@ fn impl_simple_enum(
691
706
692
707
let ( default_repr, default_repr_slot) = {
693
708
let variants_repr = variants. iter ( ) . map ( |variant| {
709
+ ensure_spanned ! ( variant. options. signature. is_none( ) , variant. options. signature. span( ) => "`signature` can't be used on a simple enum variant" ) ;
694
710
let variant_name = variant. ident ;
695
711
// Assuming all variants are unit variants because they are the only type we support.
696
712
let repr = format ! (
697
713
"{}.{}" ,
698
714
get_class_python_name( cls, args) ,
699
715
variant. get_python_name( args) ,
700
716
) ;
701
- quote ! { #cls:: #variant_name => #repr, }
702
- } ) ;
717
+ Ok ( quote ! { #cls:: #variant_name => #repr, } )
718
+ } ) . collect :: < Result < TokenStream > > ( ) ? ;
703
719
let mut repr_impl: syn:: ImplItemFn = syn:: parse_quote! {
704
720
fn __pyo3__repr__( & self ) -> & ' static str {
705
721
match self {
706
- #( # variants_repr) *
722
+ #variants_repr
707
723
}
708
724
}
709
725
} ;
@@ -889,7 +905,7 @@ fn impl_complex_enum(
889
905
let mut variant_cls_pytypeinfos = vec ! [ ] ;
890
906
let mut variant_cls_pyclass_impls = vec ! [ ] ;
891
907
let mut variant_cls_impls = vec ! [ ] ;
892
- for variant in & variants {
908
+ for variant in variants {
893
909
let variant_cls = gen_complex_enum_variant_class_ident ( cls, variant. get_ident ( ) ) ;
894
910
895
911
let variant_cls_zst = quote ! {
@@ -908,11 +924,11 @@ fn impl_complex_enum(
908
924
let variant_cls_pytypeinfo = impl_pytypeinfo ( & variant_cls, & variant_args, None , ctx) ;
909
925
variant_cls_pytypeinfos. push ( variant_cls_pytypeinfo) ;
910
926
911
- let variant_new = complex_enum_variant_new ( cls, variant, ctx) ?;
912
-
913
- let ( variant_cls_impl, field_getters) = impl_complex_enum_variant_cls ( cls, variant, ctx) ?;
927
+ let ( variant_cls_impl, field_getters) = impl_complex_enum_variant_cls ( cls, & variant, ctx) ?;
914
928
variant_cls_impls. push ( variant_cls_impl) ;
915
929
930
+ let variant_new = complex_enum_variant_new ( cls, variant, ctx) ?;
931
+
916
932
let pyclass_impl = PyClassImplsBuilder :: new (
917
933
& variant_cls,
918
934
& variant_args,
@@ -1120,7 +1136,7 @@ pub fn gen_complex_enum_variant_attr(
1120
1136
1121
1137
fn complex_enum_variant_new < ' a > (
1122
1138
cls : & ' a syn:: Ident ,
1123
- variant : & ' a PyClassEnumVariant < ' a > ,
1139
+ variant : PyClassEnumVariant < ' a > ,
1124
1140
ctx : & Ctx ,
1125
1141
) -> Result < MethodAndSlotDef > {
1126
1142
match variant {
@@ -1132,7 +1148,7 @@ fn complex_enum_variant_new<'a>(
1132
1148
1133
1149
fn complex_enum_struct_variant_new < ' a > (
1134
1150
cls : & ' a syn:: Ident ,
1135
- variant : & ' a PyClassEnumStructVariant < ' a > ,
1151
+ variant : PyClassEnumStructVariant < ' a > ,
1136
1152
ctx : & Ctx ,
1137
1153
) -> Result < MethodAndSlotDef > {
1138
1154
let Ctx { pyo3_path } = ctx;
@@ -1162,7 +1178,12 @@ fn complex_enum_struct_variant_new<'a>(
1162
1178
}
1163
1179
args
1164
1180
} ;
1165
- let signature = crate :: pyfunction:: FunctionSignature :: from_arguments ( args) ?;
1181
+
1182
+ let signature = if let Some ( signature) = variant. options . signature {
1183
+ crate :: pyfunction:: FunctionSignature :: from_arguments_and_attribute ( args, signature) ?
1184
+ } else {
1185
+ crate :: pyfunction:: FunctionSignature :: from_arguments ( args) ?
1186
+ } ;
1166
1187
1167
1188
let spec = FnSpec {
1168
1189
tp : crate :: method:: FnType :: FnNew ,
0 commit comments