Skip to content

Commit 00ccb78

Browse files
authored
New analyser: Fix crash in plugins when star import blocks adding a symbol (#7136)
Fixes #7076 The fix is pretty straightforward. I also add a comment about `missing_names` being per-module, not per namespace.
1 parent 0440ca0 commit 00ccb78

File tree

5 files changed

+52
-2
lines changed

5 files changed

+52
-2
lines changed

mypy/newsemanal/semanal.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ class NewSemanticAnalyzer(NodeVisitor[None],
201201
# unbound names due to cyclic definitions and should not defer)?
202202
_final_iteration = False
203203
# These names couldn't be added to the symbol table due to incomplete deps.
204+
# Note that missing names are per module, _not_ per namespace. This means that e.g.
205+
# a missing name at global scope will block adding same name at a class scope.
206+
# This should not affect correctness and is purely a performance issue,
207+
# since it can cause unnecessary deferrals.
208+
# Note that a star import adds a special name '*' to the set, this blocks
209+
# adding _any_ names in the current file.
204210
missing_names = None # type: Set[str]
205211
# Callbacks that will be called after semantic analysis to tweak things.
206212
patches = None # type: List[Tuple[int, Callable[[], None]]]

mypy/plugins/attrs.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,12 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext',
212212
if ctx.api.options.new_semantic_analyzer:
213213
# Check if attribute types are ready.
214214
for attr in attributes:
215-
if info[attr.name].type is None and not ctx.api.final_iteration:
215+
node = info.get(attr.name)
216+
if node is None:
217+
# This name is likely blocked by a star import. We don't need to defer because
218+
# defer() is already called by mark_incomplete().
219+
return
220+
if node.type is None and not ctx.api.final_iteration:
216221
ctx.api.defer()
217222
return
218223

mypy/plugins/dataclasses.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,14 @@ def collect_attributes(self) -> List[DataclassAttribute]:
213213
if not isinstance(lhs, NameExpr):
214214
continue
215215

216-
node = cls.info.names[lhs.name].node
216+
sym = cls.info.names.get(lhs.name)
217+
if sym is None:
218+
# This name is likely blocked by a star import. We don't need to defer because
219+
# defer() is already called by mark_incomplete().
220+
assert ctx.api.options.new_semantic_analyzer
221+
continue
222+
223+
node = sym.node
217224
if isinstance(node, PlaceholderNode):
218225
# This node is not ready yet.
219226
continue

test-data/unit/check-attr.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,3 +1151,19 @@ class C:
11511151

11521152
C(0).total = 1 # E: Property "total" defined in "C" is read-only
11531153
[builtins fixtures/bool.pyi]
1154+
1155+
[case testTypeInAttrDeferredStar]
1156+
import lib
1157+
[file lib.py]
1158+
import attr
1159+
from other import *
1160+
1161+
@attr.s
1162+
class C:
1163+
total = attr.ib(type=int)
1164+
1165+
C() # E: Too few arguments for "C"
1166+
C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int"
1167+
[file other.py]
1168+
import lib
1169+
[builtins fixtures/bool.pyi]

test-data/unit/check-dataclasses.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,19 @@ def func() -> int: ...
665665
c: C
666666
c.x = 1 # E: Property "x" defined in "C" is read-only
667667
[builtins fixtures/bool.pyi]
668+
669+
[case testTypeInDataclassDeferredStar]
670+
import lib
671+
[file lib.py]
672+
from dataclasses import dataclass
673+
from other import *
674+
675+
@dataclass
676+
class C:
677+
total: int
678+
679+
C() # E: Too few arguments for "C"
680+
C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int"
681+
[file other.py]
682+
import lib
683+
[builtins fixtures/bool.pyi]

0 commit comments

Comments
 (0)