@@ -18,9 +18,9 @@ enum ParameterKind {
1818impl ParameterKind {
1919 fn from_ident ( ident : & Ident ) -> Option < ParameterKind > {
2020 match ident. to_string ( ) . as_str ( ) {
21- "positional_only " => Some ( ParameterKind :: PositionalOnly ) ,
22- "positional_or_keyword " => Some ( ParameterKind :: PositionalOrKeyword ) ,
23- "keyword_only " => Some ( ParameterKind :: KeywordOnly ) ,
21+ "positional " => Some ( ParameterKind :: PositionalOnly ) ,
22+ "any " => Some ( ParameterKind :: PositionalOrKeyword ) ,
23+ "named " => Some ( ParameterKind :: KeywordOnly ) ,
2424 "flatten" => Some ( ParameterKind :: Flatten ) ,
2525 _ => None ,
2626 }
@@ -29,9 +29,10 @@ impl ParameterKind {
2929
3030struct ArgAttribute {
3131 kind : ParameterKind ,
32- default : Option < Expr > ,
33- optional : bool ,
32+ default : Option < DefaultValue > ,
3433}
34+ // None == quote!(Default::default())
35+ type DefaultValue = Option < Expr > ;
3536
3637impl ArgAttribute {
3738 fn from_attribute ( attr : & Attribute ) -> Option < Result < ArgAttribute , Diagnostic > > {
@@ -54,24 +55,19 @@ impl ArgAttribute {
5455 err_span ! (
5556 first_arg,
5657 "The first argument to #[pyarg()] must be the parameter type, either \
57- 'positional_only ', 'positional_or_keyword ', 'keyword_only ', or 'flatten'."
58+ 'positional ', 'any ', 'named ', or 'flatten'."
5859 )
5960 } ) ?;
6061
6162 let mut attribute = ArgAttribute {
6263 kind,
6364 default : None ,
64- optional : false ,
6565 } ;
6666
6767 for arg in iter {
6868 attribute. parse_argument ( arg) ?;
6969 }
7070
71- if attribute. default . is_some ( ) && attribute. optional {
72- bail_span ! ( attr, "Can't set both a default value and optional" ) ;
73- }
74-
7571 Ok ( attribute)
7672 }
7773 _ => bail_span ! ( attr, "pyarg must be a list, like #[pyarg(...)]" ) ,
@@ -85,43 +81,24 @@ impl ArgAttribute {
8581 }
8682 match arg {
8783 NestedMeta :: Meta ( Meta :: Path ( path) ) => {
88- if path_eq ( & path, "default" ) {
89- if self . default . is_some ( ) {
90- bail_span ! ( path , "Default already set" ) ;
84+ if path_eq ( & path, "default" ) || path_eq ( & path , "optional" ) {
85+ if self . default . is_none ( ) {
86+ self . default = Some ( None ) ;
9187 }
92- let expr = parse_quote ! ( Default :: default ( ) ) ;
93- self . default = Some ( expr) ;
94- } else if path_eq ( & path, "optional" ) {
95- self . optional = true ;
9688 } else {
9789 bail_span ! ( path, "Unrecognised pyarg attribute" ) ;
9890 }
9991 }
10092 NestedMeta :: Meta ( Meta :: NameValue ( name_value) ) => {
10193 if path_eq ( & name_value. path , "default" ) {
102- if self . default . is_some ( ) {
94+ if matches ! ( self . default , Some ( Some ( _ ) ) ) {
10395 bail_span ! ( name_value, "Default already set" ) ;
10496 }
10597
10698 match name_value. lit {
107- Lit :: Str ( ref val) => {
108- let expr = val. parse :: < Expr > ( ) . map_err ( |_| {
109- err_span ! ( val, "Expected a valid expression for default argument" )
110- } ) ?;
111- self . default = Some ( expr) ;
112- }
99+ Lit :: Str ( ref val) => self . default = Some ( Some ( val. parse ( ) ?) ) ,
113100 _ => bail_span ! ( name_value, "Expected string value for default argument" ) ,
114101 }
115- } else if path_eq ( & name_value. path , "optional" ) {
116- match name_value. lit {
117- Lit :: Bool ( ref val) => {
118- self . optional = val. value ;
119- }
120- _ => bail_span ! (
121- name_value. lit,
122- "Expected boolean value for optional argument"
123- ) ,
124- }
125102 } else {
126103 bail_span ! ( name_value, "Unrecognised pyarg attribute" ) ;
127104 }
@@ -143,7 +120,6 @@ fn generate_field(field: &Field) -> Result<TokenStream2, Diagnostic> {
143120 ArgAttribute {
144121 kind : ParameterKind :: PositionalOrKeyword ,
145122 default : None ,
146- optional : false ,
147123 }
148124 } else if pyarg_attrs. len ( ) == 1 {
149125 pyarg_attrs. remove ( 0 )
@@ -168,21 +144,18 @@ fn generate_field(field: &Field) -> Result<TokenStream2, Diagnostic> {
168144 . map( |x| :: rustpython_vm:: pyobject:: TryFromObject :: try_from_object( vm, x) ) . transpose( ) ?
169145 } ;
170146 let ending = if let Some ( default) = attr. default {
147+ let default = default. unwrap_or_else ( || parse_quote ! ( :: std:: default :: Default :: default ( ) ) ) ;
171148 quote ! {
149+ . map( :: rustpython_vm:: function:: FromArgOptional :: from_inner)
172150 . unwrap_or_else( || #default )
173151 }
174- } else if attr. optional {
175- quote ! {
176- . map( :: rustpython_vm:: function:: OptionalArg :: Present )
177- . unwrap_or( :: rustpython_vm:: function:: OptionalArg :: Missing )
178- }
179152 } else {
180153 let err = match attr. kind {
181154 ParameterKind :: PositionalOnly | ParameterKind :: PositionalOrKeyword => quote ! {
182155 :: rustpython_vm:: function:: ArgumentError :: TooFewArgs
183156 } ,
184157 ParameterKind :: KeywordOnly => quote ! {
185- :: rustpython_vm:: function:: ArgumentError :: RequiredKeywordArgument ( tringify !( #name) )
158+ :: rustpython_vm:: function:: ArgumentError :: RequiredKeywordArgument ( stringify !( #name) )
186159 } ,
187160 ParameterKind :: Flatten => unreachable ! ( ) ,
188161 } ;
0 commit comments