Reputation: 52947
I had a function using functools.singledispatch
with generics break after an upgrade to version 3.7. What used to work in 3.6:
>>> from functools import singledispatch
>>> from typing import Mapping
>>> @singledispatch
... def f(_):
... raise NotImplementedError
...
>>> @f.register(Mapping)
... def _(x):
... return x
...
now raises
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/cpython/Lib/functools.py", line 831, in register
raise TypeError(
TypeError: Invalid first argument to `register()`: typing.Mapping. Use either `@register(some_class)` or plain `@register` on an annotated function.
Registering an annotated version fares no better:
>>> @f.register
... def _(x: Mapping):
... return x
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/home/user/cpython/Lib/functools.py", line 842, in register
raise TypeError(
TypeError: Invalid annotation for 'x'. typing.Mapping is not a class.
Have I been misusing single dispatch and generics before, and is there a way to achieve equivalent behaviour in version 3.7 and up?
Upvotes: 0
Views: 876
Reputation: 281683
You need collections.abc.Mapping
. Generic classes are mostly incompatible with any sort of runtime checks.
What little compatibility exists is mostly undocumented and changing frequently. For example, typing.Mapping
used to be a class, and the docs still say it's a class, but it's really just pretending to be one now. functools.singledispatch
needs a real class.
Upvotes: 4