summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@sprymix.com>2016-01-11 20:15:01 (GMT)
committerYury Selivanov <yselivanov@sprymix.com>2016-01-11 20:15:01 (GMT)
commit37dc2b28834c95d24746c2958e9ea31d3e8d1968 (patch)
tree86745aeede3b7ebc00dbde82ffb0cc8d8ffae2dc
parentec71f1779fc4d3509e8f16197a99a6ed3706a591 (diff)
downloadcpython-37dc2b28834c95d24746c2958e9ea31d3e8d1968.zip
cpython-37dc2b28834c95d24746c2958e9ea31d3e8d1968.tar.gz
cpython-37dc2b28834c95d24746c2958e9ea31d3e8d1968.tar.bz2
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.
-rw-r--r--Doc/library/inspect.rst18
-rw-r--r--Doc/whatsnew/3.6.rst3
-rw-r--r--Lib/inspect.py25
-rw-r--r--Lib/test/test_inspect.py40
-rw-r--r--Misc/NEWS3
5 files changed, 79 insertions, 10 deletions
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 8045d85..8e8d725 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -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
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index bf5161d..f7dbbee 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -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.
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 7615e52..74f3b3c 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -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')
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index a88e7fd..283c922 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -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):
diff --git a/Misc/NEWS b/Misc/NEWS
index 593ed24..089388e 100644
--- 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().