]> granicus.if.org Git - python/commitdiff
Issue #25486: Resurrect inspect.getargspec in 3.6. Backout a565aad5d6e1.
authorYury Selivanov <yselivanov@sprymix.com>
Mon, 11 Jan 2016 20:15:01 +0000 (15:15 -0500)
committerYury Selivanov <yselivanov@sprymix.com>
Mon, 11 Jan 2016 20:15:01 +0000 (15:15 -0500)
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.

Doc/library/inspect.rst
Doc/whatsnew/3.6.rst
Lib/inspect.py
Lib/test/test_inspect.py
Misc/NEWS

index 8045d85a08e714d15ac03f9228b6f3b1ff44086c..8e8d7253a6eff9e56ad8e8d2d30fbc3a32ad20e0 100644 (file)
@@ -796,6 +796,24 @@ Classes and functions
    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
index bf5161d1a50169e6688102ef7074a975418ae56d..f7dbbeecbc43786cf4c8def4c5fdbbbb4b4e9e15 100644 (file)
@@ -218,9 +218,6 @@ Removed
 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.
index 7615e5277f78074b39dba4fdb540bc44be83fce6..74f3b3c3bbb4a81566e4363e6fe9e0b5c33bd3cf 100644 (file)
@@ -1004,6 +1004,31 @@ def _getfullargs(co):
         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')
 
index a88e7fdbd8cb7c0c1457455dd91683fb66988513..283c92268cbbe702a7cef580a94e6d63b05db7bb 100644 (file)
@@ -628,6 +628,18 @@ class TestClassesAndFunctions(unittest.TestCase):
         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 @@ class TestClassesAndFunctions(unittest.TestCase):
                                                     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 @@ class TestClassesAndFunctions(unittest.TestCase):
                                      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 @@ class TestClassesAndFunctions(unittest.TestCase):
         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):
index 593ed2475eb4d29ef3b3b5e7112fbfc354e363a3..089388ed080496a3d27c4e7960a776b681b33bd4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -429,8 +429,7 @@ Library
 - 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().