@@ -184,16 +184,18 @@ def create_function(func_signature, # type: Union[str, Signature]
184
184
raise TypeError ("Invalid type for `func_signature`: %s" % type (func_signature ))
185
185
186
186
# extract all information needed from the `Signature`
187
- posonly_names , kwonly_names , varpos_names , varkw_names , unrestricted_names = get_signature_params (func_signature )
188
- params_names = posonly_names + unrestricted_names + varpos_names + kwonly_names + varkw_names
187
+ params_to_kw_assignment_mode = get_signature_params (func_signature )
188
+ params_names = list ( params_to_kw_assignment_mode . keys ())
189
189
190
190
# Note: in decorator the annotations were extracted using getattr(func_impl, '__annotations__') instead.
191
191
# This seems equivalent but more general (provided by the signature, not the function), but to check
192
192
annotations , defaults , kwonlydefaults = get_signature_details (func_signature )
193
193
194
194
# create the body of the function to compile
195
- assignments = posonly_names + [("%s=%s" % (k , k )) if k [0 ] != '*' else k
196
- for k in unrestricted_names + varpos_names + kwonly_names + varkw_names ]
195
+ # The generated function body should dispatch its received arguments to the inner function.
196
+ # For this we will pass as much as possible the arguments as keywords.
197
+ # However if there are varpositional arguments we cannot
198
+ assignments = [("%s=%s" % (k , k )) if is_kw else k for k , is_kw in params_to_kw_assignment_mode .items ()]
197
199
params_str = ', ' .join (assignments )
198
200
if inject_as_first_arg :
199
201
params_str = "%s, %s" % (func_name , params_str )
@@ -433,22 +435,26 @@ def get_signature_params(s):
433
435
:param s:
434
436
:return:
435
437
"""
436
- posonly_names , kwonly_names , varpos_names , varkw_names , unrestricted_names = [], [], [], [], []
438
+ # this ordered dictionary will contain parameters and True/False whether we should use keyword assignment or not
439
+ params_to_assignment_mode = OrderedDict ()
437
440
for p_name , p in s .parameters .items ():
438
441
if p .kind is Parameter .POSITIONAL_ONLY :
439
- posonly_names . append ( p_name )
442
+ params_to_assignment_mode [ p_name ] = False
440
443
elif p .kind is Parameter .KEYWORD_ONLY :
441
- kwonly_names . append ( p_name )
444
+ params_to_assignment_mode [ p_name ] = True
442
445
elif p .kind is Parameter .POSITIONAL_OR_KEYWORD :
443
- unrestricted_names . append ( p_name )
446
+ params_to_assignment_mode [ p_name ] = True
444
447
elif p .kind is Parameter .VAR_POSITIONAL :
445
- varpos_names .append ("*" + p_name )
448
+ # We have to pass all the arguments that were here in previous positions, as positional too.
449
+ for k in params_to_assignment_mode .keys ():
450
+ params_to_assignment_mode [k ] = False
451
+ params_to_assignment_mode ["*" + p_name ] = False
446
452
elif p .kind is Parameter .VAR_KEYWORD :
447
- varkw_names . append ( "**" + p_name )
453
+ params_to_assignment_mode [ "**" + p_name ] = False
448
454
else :
449
455
raise ValueError ("Unknown kind: %s" % p .kind )
450
456
451
- return posonly_names , kwonly_names , varpos_names , varkw_names , unrestricted_names
457
+ return params_to_assignment_mode
452
458
453
459
454
460
def get_signature_details (s ):
0 commit comments