[Python-checkins] bpo-36350: inspect: Replace OrderedDict with dict. (GH-12412)

Inada Naoki webhook-mailer at python.org
Tue Jan 28 07:47:23 EST 2020


https://github.com/python/cpython/commit/2cca8efe46935c39c445f585bce54954fad2485b
commit: 2cca8efe46935c39c445f585bce54954fad2485b
branch: master
author: Rémi Lapeyre <remi.lapeyre at henki.fr>
committer: Inada Naoki <songofacandy at gmail.com>
date: 2020-01-28T21:47:03+09:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2019-03-18-16-17-59.bpo-36350.udRSWE.rst
M Doc/library/inspect.rst
M Lib/inspect.py
M Lib/test/test_inspect.py

diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index bab2c41e4e224..9b9bc99f43d48 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -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
 
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 608ca9551160e..950bdb221798d 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -48,7 +48,7 @@
 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 @@ def apply_defaults(self):
                     # 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 @@ def __init__(self, parameters=None, *, return_annotation=_empty,
         """
 
         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 @@ def __init__(self, parameters=None, *, return_annotation=_empty,
 
                     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 @@ def __eq__(self, other):
     def _bind(self, args, kwargs, *, partial=False):
         """Private method. Don't use directly."""
 
-        arguments = OrderedDict()
+        arguments = {}
 
         parameters = iter(self.parameters.values())
         parameters_ex = ()
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index d95e742c8dd64..8a2efc879323f 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -2077,6 +2077,7 @@ def test_signature_object(self):
         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 @@ def foo(a='spam'): pass
         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):
diff --git a/Misc/NEWS.d/next/Library/2019-03-18-16-17-59.bpo-36350.udRSWE.rst b/Misc/NEWS.d/next/Library/2019-03-18-16-17-59.bpo-36350.udRSWE.rst
new file mode 100644
index 0000000000000..43363fce1652c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-03-18-16-17-59.bpo-36350.udRSWE.rst
@@ -0,0 +1,2 @@
+`inspect.Signature.parameters` and `inspect.BoundArguments.arguments` are
+now dicts instead of OrderedDicts. Patch contributed by Rémi Lapeyre.



More information about the Python-checkins mailing list