@@ -2339,6 +2339,17 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
23392339
23402340 Parameter = cls ._parameter_cls
23412341
2342+ # A real Python function has valid identifier names in co_varnames, so its
2343+ # parameters can be built without re-validating them. A function-like
2344+ # object (is_duck_function) carries an arbitrary code object whose
2345+ # co_varnames are not guaranteed to be valid identifiers, so it must go
2346+ # through the validating constructor.
2347+ if is_duck_function :
2348+ def make_param (name , kind , default , annotation , _P = Parameter ):
2349+ return _P (name , kind , default = default , annotation = annotation )
2350+ else :
2351+ make_param = Parameter ._from_valid_args
2352+
23422353 # Parameter information.
23432354 func_code = func .__code__
23442355 pos_count = func_code .co_argcount
@@ -2366,23 +2377,23 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
23662377 for name in positional [:non_default_count ]:
23672378 kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
23682379 annotation = annotations .get (name , _empty )
2369- parameters .append (Parameter . _from_valid_args (name , kind , _empty , annotation ))
2380+ parameters .append (make_param (name , kind , _empty , annotation ))
23702381 if posonly_left :
23712382 posonly_left -= 1
23722383
23732384 # ... w/ defaults.
23742385 for offset , name in enumerate (positional [non_default_count :]):
23752386 kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
23762387 annotation = annotations .get (name , _empty )
2377- parameters .append (Parameter . _from_valid_args (name , kind , defaults [offset ], annotation ))
2388+ parameters .append (make_param (name , kind , defaults [offset ], annotation ))
23782389 if posonly_left :
23792390 posonly_left -= 1
23802391
23812392 # *args
23822393 if func_code .co_flags & CO_VARARGS :
23832394 name = arg_names [pos_count + keyword_only_count ]
23842395 annotation = annotations .get (name , _empty )
2385- parameters .append (Parameter . _from_valid_args (name , _VAR_POSITIONAL , _empty , annotation ))
2396+ parameters .append (make_param (name , _VAR_POSITIONAL , _empty , annotation ))
23862397
23872398 # Keyword-only parameters.
23882399 for name in keyword_only :
@@ -2391,7 +2402,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
23912402 default = kwdefaults .get (name , _empty )
23922403
23932404 annotation = annotations .get (name , _empty )
2394- parameters .append (Parameter . _from_valid_args (name , _KEYWORD_ONLY , default , annotation ))
2405+ parameters .append (make_param (name , _KEYWORD_ONLY , default , annotation ))
23952406 # **kwargs
23962407 if func_code .co_flags & CO_VARKEYWORDS :
23972408 index = pos_count + keyword_only_count
@@ -2400,7 +2411,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
24002411
24012412 name = arg_names [index ]
24022413 annotation = annotations .get (name , _empty )
2403- parameters .append (Parameter . _from_valid_args (name , _VAR_KEYWORD , _empty , annotation ))
2414+ parameters .append (make_param (name , _VAR_KEYWORD , _empty , annotation ))
24042415
24052416 # Is 'func' is a pure Python function - don't validate the
24062417 # parameters list (for correct order and defaults), it should be OK.
0 commit comments