diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 59af0d402e14..4316a59281c3 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -24,6 +24,7 @@ FuncDef, IndexExpr, MypyFile, + NameExpr, OverloadedFuncDef, SymbolNode, SymbolTable, @@ -608,7 +609,19 @@ def analyze_member_var_access( mx.msg.undefined_in_superclass(name, mx.context) return AnyType(TypeOfAny.from_error) else: - return report_missing_attribute(mx.original_type, itype, name, mx) + ret = report_missing_attribute(mx.original_type, itype, name, mx) + # Avoid paying double jeopardy if we can't find the member due to --no-implicit-reexport + if ( + mx.module_symbol_table is not None + and name in mx.module_symbol_table + and not mx.module_symbol_table[name].module_public + ): + v = mx.module_symbol_table[name].node + e = NameExpr(name) + e.set_line(mx.context) + e.node = v + return mx.chk.expr_checker.analyze_ref_expr(e, lvalue=mx.is_lvalue) + return ret def check_final_member(name: str, info: TypeInfo, msg: MessageBuilder, ctx: Context) -> None: diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 96f78d81dd16..06b7cab8391b 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1611,14 +1611,22 @@ from other_module_2 import a # E: Module "other_module_2" does not explicitly e reveal_type(a) # N: Revealed type is "builtins.int" import other_module_2 -# TODO: this should also reveal builtins.int, see #13965 -reveal_type(other_module_2.a) # E: "object" does not explicitly export attribute "a" [attr-defined] \ - # N: Revealed type is "Any" +reveal_type(other_module_2.a) # E: Module "other_module_2" does not explicitly export attribute "a" [attr-defined] \ + # N: Revealed type is "builtins.int" + +from other_module_2 import b # E: Module "other_module_2" does not explicitly export attribute "b" [attr-defined] +reveal_type(b) # N: Revealed type is "def (a: builtins.int) -> builtins.str" + +import other_module_2 +reveal_type(other_module_2.b) # E: Module "other_module_2" does not explicitly export attribute "b" [attr-defined] \ + # N: Revealed type is "def (a: builtins.int) -> builtins.str" [file other_module_1.py] a = 5 +def b(a: int) -> str: ... [file other_module_2.py] -from other_module_1 import a +from other_module_1 import a, b +[builtins fixtures/module.pyi] [case testNoImplicitReexportRespectsAll] # flags: --no-implicit-reexport @@ -1649,11 +1657,15 @@ __all__ = ('b',) [case testNoImplicitReexportGetAttr] # flags: --no-implicit-reexport --python-version 3.7 from other_module_2 import a # E: Module "other_module_2" does not explicitly export attribute "a" +reveal_type(a) # N: Revealed type is "builtins.int" +from other_module_2 import b # E: Module "other_module_2" does not explicitly export attribute "b" +reveal_type(b) # N: Revealed type is "builtins.str" [file other_module_1.py] -from typing import Any -def __getattr__(name: str) -> Any: ... +b: str = "asdf" +def __getattr__(name: str) -> int: ... [file other_module_2.py] -from other_module_1 import a +from other_module_1 import a, b +def __getattr__(name: str) -> bytes: ... [builtins fixtures/tuple.pyi] [case textNoImplicitReexportSuggestions] diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 94368f6c1113..abbdf4987c46 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1862,7 +1862,8 @@ import stub reveal_type(stub.y) # N: Revealed type is "builtins.int" reveal_type(stub.z) # E: Module "stub" does not explicitly export attribute "z" \ - # N: Revealed type is "Any" + # N: Revealed type is "builtins.int" + [file stub.pyi] from substub import y as y