Created on 2015-04-13 16:38 by ncoghlan, last changed 2015-05-30 21:10 by yselivanov. This issue is now closed.
inspect.signature isn't currently handling builtin & extension types correctly - these show up as having neither __new__ *nor* __init__ as pure Python callables, so the inspect.signature logic falls through into a currently unhandled case. _testcapi isn't currently exporting an extension type as docstring introspection fodder, only callables, so test_inspect didn't pick up the problem. The problem can be seen with builtin types like str: >>> import inspect >>> inspect.signature(str) <inspect.Signature object at 0x7fb81d44e518> >>> print(inspect.signature(str)) () Expected behaviour would be to throw a ValueError as with builtin callables without a signature: >>> import _testcapi >>> import inspect >>> inspect.signature(_testcapi.docstring_no_signature) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/ncoghlan/devel/py3k/Lib/inspect.py", line 2830, in signature return Signature.from_callable(obj) File "/home/ncoghlan/devel/py3k/Lib/inspect.py", line 2586, in from_callable return _signature_from_callable(obj, sigcls=cls) File "/home/ncoghlan/devel/py3k/Lib/inspect.py", line 2064, in _signature_from_callable skip_bound_arg=skip_bound_arg) File "/home/ncoghlan/devel/py3k/Lib/inspect.py", line 1984, in _signature_from_builtin raise ValueError("no signature found for builtin {!r}".format(func)) ValueError: no signature found for builtin <built-in function docstring_no_signature>
Would this qualify as an "easy" bug we could throw to a sprinter?
James Powell is currently looking into this at the PyCon sprints. The key problem appears to be the check that assumes "obj.__init__ is object.__init__" indicates that there's no user defined init or new method, when in fact a builtin or extension type that only overrides __new__ would also pass that check (since the earlier check for __new__ returns None if the method implementation isn't a pure Python callable)
Discussed with Nick Coghlan. See attached patch to return `signature(object)` only if both `__new__` and `__init__` are shared with `object`. Otherwise, raise TypeError indicating built-in types not supported. https://docs.python.org/3/library/inspect.html#inspect.signature "Raises ValueError if no signature can be provided, and TypeError if that type of object is not supported."
The main missing piece now is test fodder for this error. The simplest near-term option would be to use one of the actual builtins, such as 'str'. In Python 3.5+ we could borrow the matmulType that was added to _testcapi to test the "@" operator, future-proofing the test against eventual conversion of the builtin types to support Argument Clinic.
See attached patch for unittest. For 3.4, test that inspect.signature(str) raises TypeError. For >3.5, this can be improved to use _testcapi.matmulType
The patch looks good.
New changeset e59966bb6de5 by Yury Selivanov in branch '3.5': Issue #23934: Fix inspect.signature to fail correctly for builtin types. https://hg.python.org/cpython/rev/e59966bb6de5 New changeset 19e0ffdd1daa by Yury Selivanov in branch 'default': Issue #23934: Fix inspect.signature to fail correctly for builtin types. https://hg.python.org/cpython/rev/19e0ffdd1daa
messages: + msg240724