Open fubuloubu opened 3 years ago
As I see it there are three possibilities that explain this (ranked in order of my guesses at likelihood):
1) The implementation of typing.Generic
changed between 3.6 and 3.7. I think this is most likely because the typing
module underwent a lot of changes between these versions IIRC
2) The implementation of abc.ABCMeta
changed
3) Python became somehow "better" at resolving metaclass mixing
I will take some time later to try to prove or disprove these theories, then hopefully fix the problem if it's with dataclassy, or find a workaround.
MRE:
from typing import Generic, TypeVar
from dataclassy import dataclass
X = TypeVar('X')
@dataclass
class T(Generic[X]):
...
Diff: https://github.com/python/cpython/compare/v3.6.14...v3.7.10 Unfortunately I can't find a way to link to the single file typing.py
.
Diff: python/cpython@v3.6.14...v3.7.10 Unfortunately I can't find a way to link to the single file
typing.py
.
These seems relevant (in typing.py
)
So, seems like in Python <=3.6 only you'd need to integrate GenericMeta
into dataclassy's meta to support Generics
So, seems like in Python <=3.6 only you'd need to integrate
GenericMeta
into dataclassy's meta to support Generics
Or... I can just drop 3.6 support from my library :sweat: (which I've been meaning to anyways)
Great find. The 3.7 release notes are a little more blunt:
the generic types can be used without metaclass conflicts
This kind of makes me want to say it's a typing
problem, but I'm not against a fix in dataclassy if it's easy.
Anyway, this made me curious what the same paragraph looked like in 3.6. There I read:
The metaclass used by
Generic
is a subclass ofabc.ABCMeta
.
This made me try implementing class AbstractDataClassMeta(DataClassMeta, GenericMeta):
as a sneaky workaround. It seems like it should maybe work but instead of (or before, quite possibly) the conflict TypeError
you get TypeError: Cannot inherit from plain Generic
when actually using the decorator.
Edit: trying your suggestion of basing DataClassMeta
on GenericMeta
causes the same error.
@biqqles thanks for looking into it, I've decided to just deprecate support for Python 3.6 in my framework. IPython was also giving me grief, so it made sense to do.
In general, I was under the impression that such situations could be handled on the caller side by merging the separate (conflicting) metaclasses into one via inheritance, similar to how the above AbstractDataClassMeta
does?
Reading between the lines, it seems like this is, for some reason, not an option with Generic
? Or is it?
(Sorry if I'm missing something obvious here, I never was much into typing...)
I found a bug when I attempt to mix metaclasses w/
dataclassy
. Here is what I was doing:Generic
has nothing to do withdataclassy'
mechanics, but I could see how the metaclass might interfere.This is the error it raises in Python 3.6 (from my CI):
For reference, here is the code that defines the
abstractdataclass
decorator:It works perfectly fine with Python 3.7+, I think related to this: https://stackoverflow.com/questions/11276037/resolving-metaclass-conflicts