[Python-checkins] cpython: Issue #25486: Resurrect inspect.getargspec in 3.6. Backout a565aad5d6e1.

yury.selivanov python-checkins at python.org
Mon Jan 11 15:16:05 EST 2016


https://hg.python.org/cpython/rev/32c8bdcd66cc
changeset:   99853:32c8bdcd66cc
parent:      99849:927fd0e14d49
user:        Yury Selivanov <yselivanov at sprymix.com>
date:        Mon Jan 11 15:15:01 2016 -0500
summary:
  Issue #25486: Resurrect inspect.getargspec in 3.6. Backout a565aad5d6e1.

The decision is that we shouldn't remove popular APIs (however long they
are depreacted) from Python 3, while 2.7 is still around and supported.

files:
  Doc/library/inspect.rst  |  18 ++++++++++++
  Doc/whatsnew/3.6.rst     |   3 --
  Lib/inspect.py           |  25 +++++++++++++++++
  Lib/test/test_inspect.py |  40 ++++++++++++++++++++++++---
  Misc/NEWS                |   3 +-
  5 files changed, 79 insertions(+), 10 deletions(-)


diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -796,6 +796,24 @@
    classes using multiple inheritance and their descendants will appear multiple
    times.
 
+
+.. function:: getargspec(func)
+
+   Get the names and default values of a Python function's arguments. A
+   :term:`named tuple` ``ArgSpec(args, varargs, keywords, defaults)`` is
+   returned. *args* is a list of the argument names. *varargs* and *keywords*
+   are the names of the ``*`` and ``**`` arguments or ``None``. *defaults* is a
+   tuple of default argument values or ``None`` if there are no default
+   arguments; if this tuple has *n* elements, they correspond to the last
+   *n* elements listed in *args*.
+
+   .. deprecated:: 3.0
+      Use :func:`signature` and
+      :ref:`Signature Object <inspect-signature-object>`, which provide a
+      better introspecting API for callables.  This function will be removed
+      in Python 3.6.
+
+
 .. function:: getfullargspec(func)
 
    Get the names and default values of a Python function's arguments.  A
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -218,9 +218,6 @@
 API and Feature Removals
 ------------------------
 
-* ``inspect.getargspec()`` was removed (was deprecated since CPython 3.0).
-  :func:`inspect.getfullargspec` is an almost drop in replacement.
-
 * ``inspect.getmoduleinfo()`` was removed (was deprecated since CPython 3.3).
   :func:`inspect.getmodulename` should be used for obtaining the module
   name for a given path.
diff --git a/Lib/inspect.py b/Lib/inspect.py
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -1004,6 +1004,31 @@
         varkw = co.co_varnames[nargs]
     return args, varargs, kwonlyargs, varkw
 
+
+ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
+
+def getargspec(func):
+    """Get the names and default values of a function's arguments.
+
+    A tuple of four things is returned: (args, varargs, keywords, defaults).
+    'args' is a list of the argument names, including keyword-only argument names.
+    'varargs' and 'keywords' are the names of the * and ** arguments or None.
+    'defaults' is an n-tuple of the default values of the last n arguments.
+
+    Use the getfullargspec() API for Python 3 code, as annotations
+    and keyword arguments are supported. getargspec() will raise ValueError
+    if the func has either annotations or keyword arguments.
+    """
+    warnings.warn("inspect.getargspec() is deprecated, "
+                  "use inspect.signature() instead", DeprecationWarning,
+                  stacklevel=2)
+    args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
+        getfullargspec(func)
+    if kwonlyargs or ann:
+        raise ValueError("Function has keyword-only arguments or annotations"
+                         ", use getfullargspec() API which can support them")
+    return ArgSpec(args, varargs, varkw, defaults)
+
 FullArgSpec = namedtuple('FullArgSpec',
     'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations')
 
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -628,6 +628,18 @@
         got = inspect.getmro(D)
         self.assertEqual(expected, got)
 
+    def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
+                            varkw_e=None, defaults_e=None, formatted=None):
+        with self.assertWarns(DeprecationWarning):
+            args, varargs, varkw, defaults = inspect.getargspec(routine)
+        self.assertEqual(args, args_e)
+        self.assertEqual(varargs, varargs_e)
+        self.assertEqual(varkw, varkw_e)
+        self.assertEqual(defaults, defaults_e)
+        if formatted is not None:
+            self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
+                             formatted)
+
     def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
                                     varkw_e=None, defaults_e=None,
                                     kwonlyargs_e=[], kwonlydefaults_e=None,
@@ -646,6 +658,23 @@
                                                     kwonlyargs, kwonlydefaults, ann),
                              formatted)
 
+    def test_getargspec(self):
+        self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
+
+        self.assertArgSpecEquals(mod.spam,
+                                 ['a', 'b', 'c', 'd', 'e', 'f'],
+                                 'g', 'h', (3, 4, 5),
+                                 '(a, b, c, d=3, e=4, f=5, *g, **h)')
+
+        self.assertRaises(ValueError, self.assertArgSpecEquals,
+                          mod2.keyworded, [])
+
+        self.assertRaises(ValueError, self.assertArgSpecEquals,
+                          mod2.annotated, [])
+        self.assertRaises(ValueError, self.assertArgSpecEquals,
+                          mod2.keyword_only_arg, [])
+
+
     def test_getfullargspec(self):
         self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
                                      kwonlyargs_e=['arg2'],
@@ -659,19 +688,20 @@
                                      kwonlyargs_e=['arg'],
                                      formatted='(*, arg)')
 
-    def test_fullargspec_api_ignores_wrapped(self):
+    def test_argspec_api_ignores_wrapped(self):
         # Issue 20684: low level introspection API must ignore __wrapped__
         @functools.wraps(mod.spam)
         def ham(x, y):
             pass
         # Basic check
+        self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
         self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
         self.assertFullArgSpecEquals(functools.partial(ham),
                                      ['x', 'y'], formatted='(x, y)')
         # Other variants
         def check_method(f):
-            self.assertFullArgSpecEquals(f, ['self', 'x', 'y'],
-                                         formatted='(self, x, y)')
+            self.assertArgSpecEquals(f, ['self', 'x', 'y'],
+                                        formatted='(self, x, y)')
         class C:
             @functools.wraps(mod.spam)
             def ham(self, x, y):
@@ -749,11 +779,11 @@
         with self.assertRaises(TypeError):
             inspect.getfullargspec(builtin)
 
-    def test_getfullargspec_method(self):
+    def test_getargspec_method(self):
         class A(object):
             def m(self):
                 pass
-        self.assertFullArgSpecEquals(A.m, ['self'])
+        self.assertArgSpecEquals(A.m, ['self'])
 
     def test_classify_newstyle(self):
         class A(object):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -429,8 +429,7 @@
 - Issue #23661: unittest.mock side_effects can now be exceptions again. This
   was a regression vs Python 3.4. Patch from Ignacio Rossi
 
-- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo
-  functions.
+- Issue #13248: Remove deprecated inspect.getmoduleinfo function.
 
 - Issue #25578: Fix (another) memory leak in SSLSocket.getpeercer().
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list