diff --git a/Lib/inspect.py b/Lib/inspect.py index 1c36579..e2759f4 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -933,7 +933,7 @@ FullArgSpec = namedtuple('FullArgSpec', 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') def getfullargspec(func): - """Get the names and default values of a function's arguments. + """Get the names and default values of a callable object's arguments. A tuple of seven things is returned: (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults annotations). @@ -949,10 +949,15 @@ def getfullargspec(func): if ismethod(func): func = func.__func__ - if not isfunction(func): - raise TypeError('{!r} is not a Python function'.format(func)) - sig = signature(func) + try: + sig = signature(func) + except Exception as ex: + # Most of the times 'signature' will raise ValueError. + # But, it can also raise AttributeError, and, maybe something + # else. So to be fully backwards compatible, we catch all + # exceptions here, and reraise a TypeError. + raise TypeError('unsupported callable') from ex args = [] varargs = None diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 8660949..aad072f 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -566,7 +566,7 @@ class TestClassesAndFunctions(unittest.TestCase): kwonlyargs_e=['arg'], formatted='(*, arg)') - def test_getfullargspec_signature(self): + def test_getfullargspec_signature_attr(self): def test(): pass spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) @@ -574,6 +574,18 @@ class TestClassesAndFunctions(unittest.TestCase): self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)') + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") + def test_getfullagrspec_builtin_func(self): + builtin = _testcapi.docstring_with_signature_with_defaults + spec = inspect.getfullargspec(builtin) + self.assertEqual(spec.defaults[0], 'avocado') + + def test_getfullagrspec_builtin_func_no_signature(self): + builtin = _testcapi.docstring_no_signature + with self.assertRaises(TypeError): + inspect.getfullargspec(builtin) + def test_getargspec_method(self): class A(object): def m(self):