Skip to content

Commit 452a64f

Browse files
elazargJukkaL
authored andcommitted
Do not support metaclasses not inheriting from type (#2820)
Fix #2818. ABCMeta requires special treatment. Related: #2475
1 parent b731899 commit 452a64f

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

mypy/nodes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2024,7 +2024,7 @@ def calculate_metaclass_type(self) -> 'Optional[mypy.types.Instance]':
20242024
return None
20252025

20262026
def is_metaclass(self) -> bool:
2027-
return self.has_base('builtins.type')
2027+
return self.has_base('builtins.type') or self.fullname() == 'abc.ABCMeta'
20282028

20292029
def _calculate_is_enum(self) -> bool:
20302030
"""

mypy/semanal.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,9 @@ def analyze_metaclass(self, defn: ClassDef) -> None:
966966
if not isinstance(sym.node, TypeInfo) or sym.node.tuple_type is not None:
967967
self.fail("Invalid metaclass '%s'" % defn.metaclass, defn)
968968
return
969+
if not sym.node.is_metaclass():
970+
self.fail("Metaclasses not inheriting from 'type' are not supported", defn)
971+
return
969972
inst = fill_typevars(sym.node)
970973
assert isinstance(inst, Instance)
971974
defn.info.declared_metaclass = inst

test-data/unit/check-classes.test

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,9 +2770,9 @@ class B(A, metaclass=Y): pass # E: Inconsistent metaclass structure for 'B'
27702770
class M:
27712771
x = 0 # type: int
27722772

2773-
class A(metaclass=M): pass
2773+
class A(metaclass=M): pass # E: Metaclasses not inheriting from 'type' are not supported
27742774

2775-
reveal_type(A.x) # E: Revealed type is 'builtins.int'
2775+
A.x # E: "A" has no attribute "x"
27762776

27772777
[case testMetaclassTypeReveal]
27782778
from typing import Type
@@ -2785,6 +2785,14 @@ def f(TA: Type[A]):
27852785
reveal_type(TA) # E: Revealed type is 'Type[__main__.A]'
27862786
reveal_type(TA.x) # E: Revealed type is 'builtins.int'
27872787

2788+
[case testSubclassMetaclass]
2789+
class M1(type):
2790+
x = 0
2791+
class M2(M1): pass
2792+
class C(metaclass=M2):
2793+
pass
2794+
reveal_type(C.x) # E: Revealed type is 'builtins.int'
2795+
27882796
[case testMetaclassSubclass]
27892797
from typing import Type
27902798
class M(type):
@@ -2822,4 +2830,4 @@ from typing import Tuple
28222830
class M(Tuple[int]): pass
28232831
class C(metaclass=M): pass # E: Invalid metaclass 'M'
28242832

2825-
[builtins fixtures/tuple.pyi]
2833+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)