.. attribute:: Signature.parameters
- An dictionary of :class:`Parameter` objects. Parameters appear in strict
- definition order, including keyword-only parameters.
+ An ordered mapping of parameters' names to the corresponding
+ :class:`Parameter` objects. Parameters appear in strict definition
+ order, including keyword-only parameters.
.. versionchanged:: 3.7
Python only explicitly guaranteed that it preserved the declaration
order of keyword-only parameters as of version 3.7, although in practice
this order had always been preserved in Python 3.
- .. versionchanged:: 3.9
- :attr:`parameters` is now of type :class:`dict`. Formerly, it was of
- type :class:`collections.OrderedDict`.
-
.. attribute:: Signature.return_annotation
The "return" annotation for the callable. If the callable has no "return"
.. attribute:: BoundArguments.arguments
- An ordered, mutable mapping of parameters' names to arguments' values.
+ A mutable mapping of parameters' names to arguments' values.
Contains only explicitly bound arguments. Changes in :attr:`arguments`
will reflect in :attr:`args` and :attr:`kwargs`.
import functools
import builtins
from operator import attrgetter
-from collections import namedtuple
+from collections import namedtuple, OrderedDict
# Create constants for the compiler flags in Include/code.h
# We try to get them from dis to avoid duplication
"""
old_params = wrapped_sig.parameters
- new_params = {}
+ new_params = OrderedDict(old_params.items())
partial_args = partial.args or ()
partial_keywords = partial.keywords or {}
transform_to_kwonly = False
- kwonly_params = {} # Keyword only parameters are moved to end.
for param_name, param in old_params.items():
try:
arg_value = ba.arguments[param_name]
if param.kind is _POSITIONAL_ONLY:
# If positional-only parameter is bound by partial,
# it effectively disappears from the signature
+ new_params.pop(param_name)
continue
if param.kind is _POSITIONAL_OR_KEYWORD:
# multiple values.
transform_to_kwonly = True
# Set the new default value
- param = param.replace(default=arg_value)
+ new_params[param_name] = param.replace(default=arg_value)
else:
# was passed as a positional argument
+ new_params.pop(param.name)
continue
if param.kind is _KEYWORD_ONLY:
# Set the new default value
- param = param.replace(default=arg_value)
+ new_params[param_name] = param.replace(default=arg_value)
if transform_to_kwonly:
assert param.kind is not _POSITIONAL_ONLY
if param.kind is _POSITIONAL_OR_KEYWORD:
- kwonly_params[param_name] = param.replace(kind=_KEYWORD_ONLY)
+ new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY)
+ new_params[param_name] = new_param
+ new_params.move_to_end(param_name)
elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD):
- kwonly_params[param_name] = param
- else:
- new_params[param_name] = param
+ new_params.move_to_end(param_name)
+ elif param.kind is _VAR_POSITIONAL:
+ new_params.pop(param.name)
- new_params.update(kwonly_params)
return wrapped_sig.replace(parameters=new_params.values())