-
Notifications
You must be signed in to change notification settings - Fork 123
Description
Description
If you try to make a generic class that inherits from one of the _SpecialGenericAlias types (such as Mapping), the type inference fails to work.
A minimal example below (Python 3.13, msgspec 0.20.0):
from collections.abc import Mapping
from dataclasses import dataclass
import msgspec
@dataclass
class Bar[T](Mapping[str, T]):
data: dict[str, T]
def __getitem__(self, x):
return self.data[x]
def __len__(self):
return len(self.data)
def __iter__(self):
return iter(self.data)
x: Bar[int] = Bar({"x": 3})
msgspec.msgpack.decode(msgspec.msgpack.encode(x), type=Bar[int])with traceback
Traceback (most recent call last):
File "<censored>", line 31, in <module>
msgspec.msgpack.decode(msgspec.msgpack.encode(x), type=Bar[int])
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/venv/lib/python3.13/site-packages/msgspec/_utils.py", line 252, in get_dataclass_info
hints = get_class_annotations(obj)
File "/opt/venv/lib/python3.13/site-packages/msgspec/_utils.py", line 149, in get_class_annotations
mro, typevar_mappings = _get_class_mro_and_typevar_mappings(obj)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/opt/venv/lib/python3.13/site-packages/msgspec/_utils.py", line 126, in _get_class_mro_and_typevar_mappings
inner(obj, {})
~~~~~^^^^^^^^^
File "/opt/venv/lib/python3.13/site-packages/msgspec/_utils.py", line 124, in inner
inner(b, new_scope)
~~~~~^^^^^^^^^^^^^^
File "/opt/venv/lib/python3.13/site-packages/msgspec/_utils.py", line 116, in inner
params = cls.__parameters__
^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Mapping' has no attribute '__parameters__'
I believe this is caused by the logic in inner(...) in the utils. For this, we look up __origin__ - however, in these specific cases, the types library has typing.Mapping as a typing._SpecialGenericAlias, which has different behaviour - it's __origin__ is not typing.Mapping, it's collections.abc.Mapping. This has no generic type parameters so inference fails.
This looks extremely tough to wade through so not sure what a good workaround is here - not a typing expert!
I'll note briefly that this behaviour goes away if it's not generic in inheritance, but it still fails if I use msgspec.Struct and a combined metaclass from StructMeta and ABCMeta so is not an artifact of dataclasses or anything, I think.