Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metaclass Error #16

Closed
TylerYep opened this issue Jan 14, 2021 · 1 comment
Closed

Metaclass Error #16

TylerYep opened this issue Jan 14, 2021 · 1 comment
Labels
question Further information is requested

Comments

@TylerYep
Copy link

TylerYep commented Jan 14, 2021

I encountered this issue while testing dataclassy. From reading the documentation, it looks like I should pass something into the meta= parameter to dataclasses? I'm not quite sure how to fix this. If this is easily solvable, maybe you could edit to the error message to explain what to do.

This was while testing the performance branch, but I suspect it applies to the current main branch as well.

from typing import Any, Generic, Mapping, TypeVar
from dataclassy import dataclass
V = TypeVar("V")

@dataclass
class Edge(Generic[V], Mapping[str, Any]):
    start: V
    end: V
    weight: float

or a simpler version:

from typing import Mapping
from dataclassy import dataclass
@dataclass
class Edge(Mapping[str, float]):
    weight: float

Running this code gives:

Traceback (most recent call last):
  File "/Users/tyler.yep/Documents/Github/workshop/explore/ff.py", line 8, in <module>
    class Edge( Mapping[str, Any]):
  File "/Users/tyler.yep/Documents/Github/dataclassy/dataclassy/decorator.py", line 25, in dataclass
    return apply_metaclass(cls)
  File "/Users/tyler.yep/Documents/Github/dataclassy/dataclassy/decorator.py", line 20, in apply_metaclass
    return metaclass(to_class.__name__, to_class.__bases__, dict_, **options)
  File "/Users/tyler.yep/Documents/Github/dataclassy/dataclassy/dataclass.py", line 96, in __new__
    return type.__new__(mcs, name, bases, dict_)
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Thanks!

@biqqles
Copy link
Owner

biqqles commented Jan 14, 2021

Hmm, this is a problem caused by both typing and dataclassy using metaclasses to do their magic. The TypeError is a little cryptic, but what Python means is that both the metaclasses must be in the same inheritance chain, which obviously they are not.

>>> from typing import Mapping
>>> type(Mapping)
<class 'typing._SpecialGenericAlias'>)  # recall that the type of a data class is DataClassMeta

typing.Generic is just a regular class, so works, which is nice because generic data classes can be useful.

There are other examples of metaclasses in the standard library that would cause the same issue. For example, if you tried to create an abstract dataclass with collections.ABC:

from abc import ABC
from dataclassy import dataclass

@dataclass
class AbstractDataClass(ABC):
    pass

you would get the same error, because ABC has the metaclass ABCMeta.


Sadly, this is not easily solvable. In theory, you can merge the metaclasses by inheriting them to create a new metaclass, and then use the meta option to tell dataclassy to use that. But this is often difficult, as it seems to be here (though I tried only very briefly). If you absolutely need to subclass Mapping here, you can't use a dataclassy data class, sorry.

@biqqles biqqles added the question Further information is requested label Jan 17, 2021
@biqqles biqqles closed this as completed Jan 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants