bpo-36350: inspect: Replace OrderedDict with dict. (GH-12412)

This commit is contained in:
Rémi Lapeyre 2020-01-28 13:47:03 +01:00 committed by Inada Naoki
parent 0be3246d4f
commit 2cca8efe46
4 changed files with 39 additions and 29 deletions

View File

@ -624,15 +624,18 @@ function.
.. attribute:: Signature.parameters
An ordered mapping of parameters' names to the corresponding
:class:`Parameter` objects. Parameters appear in strict definition
order, including keyword-only parameters.
An dictionary of :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"
@ -821,10 +824,9 @@ function.
.. attribute:: BoundArguments.arguments
An ordered, mutable mapping (:class:`collections.OrderedDict`) of
parameters' names to arguments' values. Contains only explicitly bound
arguments. Changes in :attr:`arguments` will reflect in :attr:`args` and
:attr:`kwargs`.
An ordered, 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`.
Should be used in conjunction with :attr:`Signature.parameters` for any
argument processing purposes.
@ -836,6 +838,10 @@ function.
However, if needed, use :meth:`BoundArguments.apply_defaults` to add
them.
.. versionchanged:: 3.9
:attr:`arguments` is now of type :class:`dict`. Formerly, it was of
type :class:`collections.OrderedDict`.
.. attribute:: BoundArguments.args
A tuple of positional arguments values. Dynamically computed from the
@ -866,7 +872,7 @@ function.
>>> ba = inspect.signature(foo).bind('spam')
>>> ba.apply_defaults()
>>> ba.arguments
OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())])
{'a': 'spam', 'b': 'ham', 'args': ()}
.. versionadded:: 3.5

View File

@ -48,7 +48,7 @@ import warnings
import functools
import builtins
from operator import attrgetter
from collections import namedtuple, OrderedDict
from collections import namedtuple
# Create constants for the compiler flags in Include/code.h
# We try to get them from dis to avoid duplication
@ -1727,7 +1727,7 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
"""
old_params = wrapped_sig.parameters
new_params = OrderedDict(old_params.items())
new_params = {}
partial_args = partial.args or ()
partial_keywords = partial.keywords or {}
@ -1743,6 +1743,7 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
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]
@ -1752,7 +1753,6 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
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:
@ -1771,28 +1771,26 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
# multiple values.
transform_to_kwonly = True
# Set the new default value
new_params[param_name] = param.replace(default=arg_value)
param = 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
new_params[param_name] = param.replace(default=arg_value)
param = param.replace(default=arg_value)
if transform_to_kwonly:
assert param.kind is not _POSITIONAL_ONLY
if param.kind is _POSITIONAL_OR_KEYWORD:
new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY)
new_params[param_name] = new_param
new_params.move_to_end(param_name)
kwonly_params[param_name] = param.replace(kind=_KEYWORD_ONLY)
elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD):
new_params.move_to_end(param_name)
elif param.kind is _VAR_POSITIONAL:
new_params.pop(param.name)
kwonly_params[param_name] = param
else:
new_params[param_name] = param
new_params.update(kwonly_params)
return wrapped_sig.replace(parameters=new_params.values())
@ -2602,7 +2600,7 @@ class BoundArguments:
Has the following public attributes:
* arguments : OrderedDict
* arguments : dict
An ordered mutable mapping of parameters' names to arguments' values.
Does not contain arguments' default values.
* signature : Signature
@ -2702,7 +2700,7 @@ class BoundArguments:
# Signature.bind_partial().
continue
new_arguments.append((name, val))
self.arguments = OrderedDict(new_arguments)
self.arguments = dict(new_arguments)
def __eq__(self, other):
if self is other:
@ -2733,7 +2731,7 @@ class Signature:
A Signature object has the following public attributes and methods:
* parameters : OrderedDict
* parameters : dict
An ordered mapping of parameters' names to the corresponding
Parameter objects (keyword-only arguments are in the same order
as listed in `code.co_varnames`).
@ -2763,14 +2761,14 @@ class Signature:
"""
if parameters is None:
params = OrderedDict()
params = {}
else:
if __validate_parameters__:
params = OrderedDict()
params = {}
top_kind = _POSITIONAL_ONLY
kind_defaults = False
for idx, param in enumerate(parameters):
for param in parameters:
kind = param.kind
name = param.name
@ -2805,8 +2803,7 @@ class Signature:
params[name] = param
else:
params = OrderedDict(((param.name, param)
for param in parameters))
params = {param.name: param for param in parameters}
self._parameters = types.MappingProxyType(params)
self._return_annotation = return_annotation
@ -2888,7 +2885,7 @@ class Signature:
def _bind(self, args, kwargs, *, partial=False):
"""Private method. Don't use directly."""
arguments = OrderedDict()
arguments = {}
parameters = iter(self.parameters.values())
parameters_ex = ()

View File

@ -2077,6 +2077,7 @@ class TestSignatureObject(unittest.TestCase):
P = inspect.Parameter
self.assertEqual(str(S()), '()')
self.assertEqual(repr(S().parameters), 'mappingproxy({})')
def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
pass
@ -3681,6 +3682,10 @@ class TestBoundArguments(unittest.TestCase):
ba.apply_defaults()
self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
def test_signature_bound_arguments_arguments_type(self):
def foo(a): pass
ba = inspect.signature(foo).bind(1)
self.assertIs(type(ba.arguments), dict)
class TestSignaturePrivateHelpers(unittest.TestCase):
def test_signature_get_bound_param(self):

View File

@ -0,0 +1,2 @@
`inspect.Signature.parameters` and `inspect.BoundArguments.arguments` are
now dicts instead of OrderedDicts. Patch contributed by Rémi Lapeyre.