From fa54eb3f0275bdb480cfb05957b4125afa5c0737 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 13 Nov 2018 20:40:51 -0800 Subject: [PATCH 1/4] Always set correct kind for module __getattr__ --- mypy/semanal.py | 2 +- test-data/unit/check-modules.test | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 47a797504df1..a122b7deb4ba 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3017,7 +3017,7 @@ def visit_member_expr(self, expr: MemberExpr) -> None: typ = AnyType(TypeOfAny.from_error) else: typ = AnyType(TypeOfAny.from_error) - expr.kind = MDEF + expr.kind = GDEF expr.fullname = '{}.{}'.format(file.fullname(), expr.name) expr.node = Var(expr.name, type=typ) else: diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index c6bc89f2a25d..f15f90ba56d9 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2627,3 +2627,29 @@ import foo.bar.baz reveal_type(foo.bar.baz.x) # E: Revealed type is 'builtins.int' [file foo/bar/baz.py] x = 0 + +[case testModuleGetAttrAssignUnannotated] +import roles + +# this should not crash +roles.role = 1 + +[file roles.pyi] +def __getattr__(name): ... + +[case testModuleGetAttrAssignAny] +import roles + +roles.role = 1 + +[file roles.pyi] +from typing import Any +def __getattr__(name: str) -> Any: ... + +[case testModuleGetAttrAssignError] +import roles + +roles.role = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") + +[file roles.pyi] +def __getattr__(name: str) -> str: ... From d5ff76b0d098b12ba8e9b621c4d4966e60f4b36e Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 13 Nov 2018 20:46:38 -0800 Subject: [PATCH 2/4] Add one more test --- test-data/unit/check-modules.test | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index f15f90ba56d9..a725f7be151a 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2637,6 +2637,15 @@ roles.role = 1 [file roles.pyi] def __getattr__(name): ... +[case testModuleGetAttrAssignUnannotatedDouble] +import roles + +# this also should not crash +roles.role.attr = 1 + +[file roles.pyi] +def __getattr__(name): ... + [case testModuleGetAttrAssignAny] import roles From 395319325c2bda158aa460e8ab68c6b6c3c1c142 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 13 Nov 2018 20:48:54 -0800 Subject: [PATCH 3/4] Remove whitespace in tests --- test-data/unit/check-modules.test | 3 --- 1 file changed, 3 deletions(-) diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index a725f7be151a..dd6d35b73588 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2630,7 +2630,6 @@ x = 0 [case testModuleGetAttrAssignUnannotated] import roles - # this should not crash roles.role = 1 @@ -2639,7 +2638,6 @@ def __getattr__(name): ... [case testModuleGetAttrAssignUnannotatedDouble] import roles - # this also should not crash roles.role.attr = 1 @@ -2648,7 +2646,6 @@ def __getattr__(name): ... [case testModuleGetAttrAssignAny] import roles - roles.role = 1 [file roles.pyi] From 57d432e698cdeab2cecc58c562f9024c480202a8 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Wed, 14 Nov 2018 15:48:34 -0800 Subject: [PATCH 4/4] Add more tests --- test-data/unit/check-modules.test | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index dd6d35b73588..2e1ba918df82 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2659,3 +2659,21 @@ roles.role = 1 # E: Incompatible types in assignment (expression has type "int" [file roles.pyi] def __getattr__(name: str) -> str: ... + +[case testModuleGetAttrAssignSubmodule] +import roles +roles.role = 1 +roles.missing.attr = 1 + +[file roles/__init__.pyi] +from typing import Any +def __getattr__(name: str) -> Any: ... + +[case testModuleGetAttrAssignSubmoduleStrict] +import roles +roles.role = 1 # E: Incompatible types in assignment (expression has type "int", variable has type Module) + +[file roles/__init__.pyi] +from types import ModuleType +def __getattr__(name: str) -> ModuleType: ... +[builtins fixtures/module.pyi]