davidfstr/trycast

Callable[[Any * N], Any]: Trouble matching against constructors for certain built-in types

davidfstr opened this issue · 2 comments

In the test suite's test_callable_p_r you will see lines like:

# NOTE: Cannot introspect constructor for certain built-in types
# TODO: Define __signature__ for failing internal types
self.assertTryCastFailure(Callable[[], Any], bool)
self.assertTryCastFailure(Callable[[], Any], int)
self.assertTryCastSuccess(Callable[[], Any], float)
self.assertTryCastSuccess(Callable[[], Any], complex)
self.assertTryCastFailure(Callable[[], Any], str)
self.assertTryCastSuccess(Callable[[], Any], list)
self.assertTryCastFailure(Callable[[], Any], dict)
self.assertTryCastSuccess(Callable[[], Any], tuple)

We want all of those lines to all be assertTryCastSuccess (and still have the test pass).

The failing lines above occur because an inspect.Signature cannot be generated for the constructor of certain built-in types:

inspect.signature(bool)  # ERROR: ValueError: no signature found for builtin type
inspect.signature(int)  # ERROR: ValueError: no signature found for builtin type
inspect.signature(float)  # OK
inspect.signature(complex)  # OK
inspect.signature(str)  # ERROR: ValueError: no signature found for builtin type
inspect.signature(list)  # OK
inspect.signature(dict)  # ERROR: ValueError: no signature found for builtin type
inspect.signature(tuple)  # OK

Based on reading the implementation of inspect.signature() and the underlying _signature_from_callable(), it looks like the desired fix would be to define an __signature__ on the type itself. For example:

sig = inspect.Signature()
bool.__signature__ = sig  # ERROR: TypeError: can't set attributes of built-in/extension type 'bool'
assert inspect.signature(bool) == sig

Unfortunately as the ERROR above alludes, there's no way to set __signature__ directly from normal Python code.

Next steps:

  • Find/create issue on upstream Python issue tracker RE inspect.signature(bool) (and calls on similar built-in types) not working
  • Shepherd that issue to resolution

The inspect.signature() documentation alludes:

Note: Some callables may not be introspectable in certain implementations of Python. For example, in CPython, some built-in functions defined in C provide no metadata about their arguments.

I think this issue should be considered a bug (and therefore prioritized higher than a normal enhancement) because its existence means that when checking against a Callable[[Any * N], Any] type, the output of trycast is NOT Decidable, which is a goal articulated in trycast's Philosophy.

However this issue is NOT a regression in functionality, so doesn't merit the "regression" label.