-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
Description
Bug Report
Since mypy 0.990 I am getting a "Metaclass conflict" error for the definition of a class derived from a base class which uses a metaclass imported from a third-party library that doesn't provide type annotations.
To Reproduce
# Import metaclass from external module which doesn't provide type annotations
from mymodule import MyMeta
class Base(metaclass=MyMeta):
pass
# This generates the error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases [misc]
class Derived(Base):
pass
# If there is type annotation for the metaclass, no issue.
class MyMeta2(type):
pass
class Base2(metaclass=MyMeta2):
pass
class Derived2(Base2):
passAlso available as gist at: https://mypy-play.net/?mypy=latest&python=3.11&gist=6d41ba53b2226e3bef16df71554b10b1
Expected Behavior
No errors.
Actual Behavior
metaclass_conflict.py:10: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases [misc]
class Derived(Base):
^
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 0.911
- Mypy command-line flags:
- Mypy configuration options from
mypy.ini(and other config files):show_error_codes = True ignore_missing_imports = True pretty = True
- Python version used: 3.8
More info
I tried some debugging and found out that:
- the error comes from the TypeChecker.check_metaclass_compatibility() method in
mypy/checker.py - Using the reproducer example above, when mypy enters the
check_metaclass_compatibility()method for the derived classes, the main difference betweenDerived(which errors) andDerived2(which doesn't) is thattyp.metaclass_typeisNonein the first case (instead of the expectedMyMeta) andMyMeta2in the second (correctly). - This pointed me to look at the TypeInfo.calculate_metaclass_type() method in
mypy/nodes.py. When run for theDerivedobject, the only candidate metaclass isMyMeta(correctly), but then this is excluded in the followingforloop becauseMyMeta.type.mrois[](I supposed because it's missing type annotation).
kbehlers