Search code examples
pythonpython-3.xpython-typingpython-3.9python-collections

Is collections.abc.Callable bugged in Python 3.9.1?


Python 3.9 includes PEP 585 and deprecates many of the types in the typing module in favor of the ones in collections.abc, now that they support __class_getitem__. This is the case with for example Callable. To me it would seem that typing.Callable and collections.abc.Callable should always behave similarly, but they do not.

This simple example results in an error:

>>> from typing import Optional
>>> from collections.abc import Callable
>>> def foo(arg: Optional[Callable[[int], int]]) -> None:
...    pass
...
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/local/lib/python3.9/typing.py", line 262, in inner
    return func(*args, **kwds)
  File "/usr/local/lib/python3.9/typing.py", line 339, in __getitem__
    return self._getitem(self, parameters)
  File "/usr/local/lib/python3.9/typing.py", line 463, in Optional
    return Union[arg, type(None)]
  File "/usr/local/lib/python3.9/typing.py", line 262, in inner
    return func(*args, **kwds)
  File "/usr/local/lib/python3.9/typing.py", line 339, in __getitem__
    return self._getitem(self, parameters)
  File "/usr/local/lib/python3.9/typing.py", line 451, in Union
    parameters = _remove_dups_flatten(parameters)
  File "/usr/local/lib/python3.9/typing.py", line 231, in _remove_dups_flatten
    return tuple(_deduplicate(params))
  File "/usr/local/lib/python3.9/typing.py", line 205, in _deduplicate
    all_params = set(params)
TypeError: unhashable type: 'list'

but the same error does not happen with typing.Callable:

>>> from typing import Callable
>>> def foo(arg: Optional[Callable[[int], int]]) -> None:
...    pass
...
>>> # no error

The error also doesn't happen if the signature is simplified a bit:

>>> from collections.abc import Callable
>>> def foo(arg: Optional[Callable[..., int]]) -> None:
...    pass
...
>>> # no error
>>> def foo(arg: Callable[[int], int]) -> None:
...    pass
...
>>> # no error

Is this a bug in Python 3.9 and 3.9.1?


Solution

  • Yes, collections.abc.Callable doesn't work for typing purposes in 3.9.0 and 3.9.1. It was reported here and is fixed in 3.9.2 and 3.10. In the meantime you can continue to use typing.Callable.