Ilja Everilä
Ilja Everilä

Reputation: 52947

Can typing.Mapping and such be used with functools.singledispatch in 3.7 and up?

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

Answers (1)

user2357112
user2357112

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

Related Questions