mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
inspect.Signature: Make from_builtin to raise an exception if no signature can
be provided #20422
This commit is contained in:
parent
9f2e46de34
commit
b77511da92
2 changed files with 24 additions and 10 deletions
|
@ -1514,18 +1514,24 @@ def _signature_bound_method(sig):
|
||||||
return sig.replace(parameters=params)
|
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):
|
def signature(obj):
|
||||||
'''Get a signature object for the passed callable.'''
|
'''Get a signature object for the passed callable.'''
|
||||||
|
|
||||||
if not callable(obj):
|
if not callable(obj):
|
||||||
raise TypeError('{!r} is not a callable object'.format(obj))
|
raise TypeError('{!r} is not a callable object'.format(obj))
|
||||||
|
|
||||||
if (isinstance(obj, _NonUserDefinedCallables) or
|
if _signature_is_builtin(obj):
|
||||||
ismethoddescriptor(obj) or
|
return Signature.from_builtin(obj)
|
||||||
isinstance(obj, type)):
|
|
||||||
sig = Signature.from_builtin(obj)
|
|
||||||
if sig:
|
|
||||||
return sig
|
|
||||||
|
|
||||||
if isinstance(obj, types.MethodType):
|
if isinstance(obj, types.MethodType):
|
||||||
# In this case we skip the first parameter of the underlying
|
# In this case we skip the first parameter of the underlying
|
||||||
|
@ -2017,9 +2023,13 @@ class Signature:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_builtin(cls, func):
|
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)
|
s = getattr(func, "__text_signature__", None)
|
||||||
if not s:
|
if not s:
|
||||||
return None
|
raise ValueError("no signature found for builtin {!r}".format(func))
|
||||||
|
|
||||||
Parameter = cls._parameter_cls
|
Parameter = cls._parameter_cls
|
||||||
|
|
||||||
|
@ -2038,9 +2048,10 @@ class Signature:
|
||||||
try:
|
try:
|
||||||
module = ast.parse(s)
|
module = ast.parse(s)
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
return None
|
module = None
|
||||||
|
|
||||||
if not isinstance(module, ast.Module):
|
if not isinstance(module, ast.Module):
|
||||||
return None
|
raise ValueError("{!r} builtin has invalid signature".format(func))
|
||||||
|
|
||||||
f = module.body[0]
|
f = module.body[0]
|
||||||
|
|
||||||
|
@ -2149,7 +2160,6 @@ class Signature:
|
||||||
|
|
||||||
return cls(parameters, return_annotation=cls.empty)
|
return cls(parameters, return_annotation=cls.empty)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parameters(self):
|
def parameters(self):
|
||||||
return self._parameters
|
return self._parameters
|
||||||
|
|
|
@ -1667,6 +1667,10 @@ class TestSignatureObject(unittest.TestCase):
|
||||||
with self.assertRaisesRegex(TypeError, 'is not a Python function'):
|
with self.assertRaisesRegex(TypeError, 'is not a Python function'):
|
||||||
inspect.Signature.from_function(42)
|
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):
|
def test_signature_on_method(self):
|
||||||
class Test:
|
class Test:
|
||||||
def __init__(*args):
|
def __init__(*args):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue