Skip to content

Commit

Permalink
Fix module alias as instance attribute (#8259)
Browse files Browse the repository at this point in the history
Fixes #4291
  • Loading branch information
xhochy authored and msullivan committed Jan 21, 2020
1 parent 4f3c9cd commit 2d3a1bf
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
15 changes: 12 additions & 3 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3120,21 +3120,30 @@ def process_module_assignment(self, lvals: List[Lvalue], rval: Expression,
rnode = self.lookup_type_node(rval)
if rnode and isinstance(rnode.node, MypyFile):
for lval in lvals:
if not isinstance(lval, NameExpr):
if not isinstance(lval, RefExpr):
continue
# respect explicitly annotated type
if (isinstance(lval.node, Var) and lval.node.type is not None):
continue
lnode = self.current_symbol_table().get(lval.name)

# We can handle these assignments to locals and to self
if isinstance(lval, NameExpr):
lnode = self.current_symbol_table().get(lval.name)
elif isinstance(lval, MemberExpr) and self.is_self_member_ref(lval):
assert self.type is not None
lnode = self.type.names.get(lval.name)
else:
continue

if lnode:
if isinstance(lnode.node, MypyFile) and lnode.node is not rnode.node:
assert isinstance(lval, (NameExpr, MemberExpr))
self.fail(
"Cannot assign multiple modules to name '{}' "
"without explicit 'types.ModuleType' annotation".format(lval.name),
ctx)
# never create module alias except on initial var definition
elif lval.is_inferred_def:
lnode.kind = self.current_symbol_kind()
assert rnode.node is not None
lnode.node = rnode.node

Expand Down
26 changes: 26 additions & 0 deletions test-data/unit/check-basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -474,3 +474,29 @@ from typing import Any
def f() -> object:
x: Any = 1
return x

[case testImportModuleAsClassMember]
import test

class A:
def __init__(self) -> None:
self.test = test

def __call__(self) -> None:
self.test.foo("Message")

[file test.py]
def foo(s: str) -> None: ...

[case testLocalImportModuleAsClassMember]
class A:
def __init__(self) -> None:
import test

self.test = test

def __call__(self) -> None:
self.test.foo("Message")

[file test.py]
def foo(s: str) -> None: ...

0 comments on commit 2d3a1bf

Please sign in to comment.