From b77511da9257bae4082556e0235b23d008dfb789 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Wed, 29 Jan 2014 10:46:14 -0500 Subject: inspect.Signature: Make from_builtin to raise an exception if no signature can be provided #20422 --- Lib/inspect.py | 30 ++++++++++++++++++++---------- Lib/test/test_inspect.py | 4 ++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 0072820..fefcddb 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1514,18 +1514,24 @@ def _signature_bound_method(sig): return sig.replace(parameters=params) +def _signature_is_builtin(obj): + # Internal helper to test if `obj` is a callable that might + # support Argument Clinic's __text_signature__ protocol. + return (isinstance(obj, _NonUserDefinedCallables) or + ismethoddescriptor(obj) or + # Can't test 'isinstance(type)' here, as it would + # also be True for regular python classes + obj in (type, object)) + + def signature(obj): '''Get a signature object for the passed callable.''' if not callable(obj): raise TypeError('{!r} is not a callable object'.format(obj)) - if (isinstance(obj, _NonUserDefinedCallables) or - ismethoddescriptor(obj) or - isinstance(obj, type)): - sig = Signature.from_builtin(obj) - if sig: - return sig + if _signature_is_builtin(obj): + return Signature.from_builtin(obj) if isinstance(obj, types.MethodType): # In this case we skip the first parameter of the underlying @@ -2017,9 +2023,13 @@ class Signature: @classmethod def from_builtin(cls, func): + if not _signature_is_builtin(func): + raise TypeError("{!r} is not a Python builtin " + "function".format(func)) + s = getattr(func, "__text_signature__", None) if not s: - return None + raise ValueError("no signature found for builtin {!r}".format(func)) Parameter = cls._parameter_cls @@ -2038,9 +2048,10 @@ class Signature: try: module = ast.parse(s) except SyntaxError: - return None + module = None + if not isinstance(module, ast.Module): - return None + raise ValueError("{!r} builtin has invalid signature".format(func)) f = module.body[0] @@ -2149,7 +2160,6 @@ class Signature: return cls(parameters, return_annotation=cls.empty) - @property def parameters(self): return self._parameters diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 1325c7a..2ef3ca2 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1667,6 +1667,10 @@ class TestSignatureObject(unittest.TestCase): with self.assertRaisesRegex(TypeError, 'is not a Python function'): inspect.Signature.from_function(42) + def test_signature_from_builtin_errors(self): + with self.assertRaisesRegex(TypeError, 'is not a Python builtin'): + inspect.Signature.from_builtin(42) + def test_signature_on_method(self): class Test: def __init__(*args): -- cgit v0.12