Skip to content

Commit 6938e7b

Browse files
gvanrossumJukkaL
authored andcommitted
Report error on dynamic metaclass (#2275)
* Avoid crash on dynamic metaclass (force error instead) * Add a unit test
1 parent 2e19181 commit 6938e7b

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

mypy/fastparse.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,10 @@ def stringify_name(self, n: ast35.AST) -> str:
371371
if isinstance(n, ast35.Name):
372372
return n.id
373373
elif isinstance(n, ast35.Attribute):
374-
return "{}.{}".format(self.stringify_name(n.value), n.attr)
375-
else:
376-
assert False, "can't stringify " + str(type(n))
374+
sv = self.stringify_name(n.value)
375+
if sv is not None:
376+
return "{}.{}".format(sv, n.attr)
377+
return None # Can't do it.
377378

378379
# ClassDef(identifier name,
379380
# expr* bases,
@@ -387,6 +388,8 @@ def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef:
387388
metaclass = None
388389
if metaclass_arg:
389390
metaclass = self.stringify_name(metaclass_arg.value)
391+
if metaclass is None:
392+
metaclass = '<error>' # To be reported later
390393

391394
cdef = ClassDef(n.name,
392395
self.as_block(n.body, n.lineno),

mypy/semanal.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,9 @@ def is_base_class(self, t: TypeInfo, s: TypeInfo) -> bool:
835835

836836
def analyze_metaclass(self, defn: ClassDef) -> None:
837837
if defn.metaclass:
838+
if defn.metaclass == '<error>':
839+
self.fail("Dynamic metaclass not supported for '%s'" % defn.name, defn)
840+
return
838841
sym = self.lookup_qualified(defn.metaclass, defn)
839842
if sym is not None and not isinstance(sym.node, TypeInfo):
840843
self.fail("Invalid metaclass '%s'" % defn.metaclass, defn)

test-data/unit/check-classes.test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,3 +2050,8 @@ class A: pass
20502050
class B(object, A): # E: Cannot determine consistent method resolution order (MRO) for "B"
20512051
def readlines(self): pass
20522052
__iter__ = readlines
2053+
2054+
[case testDynamicMetaclass]
2055+
# flags: --fast-parser
2056+
class C(metaclass=int()): # E: Dynamic metaclass not supported for 'C'
2057+
pass

0 commit comments

Comments
 (0)