From 0f6067d699c9f63c49f519c4454408b03ca39111 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 19 Oct 2022 14:52:23 -0700 Subject: [PATCH 1/2] Always mention explicit export when relevant Related to #13917 and #13908. This handles situations involving per-module re-exports correctly / is consistent with the error you'd get with attribute access. --- mypy/semanal.py | 5 ++--- test-data/unit/check-flags.test | 12 ++++++------ test-data/unit/check-modules.test | 18 +++++++++--------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 9fca74b71872..6ee93057ab3b 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2346,10 +2346,9 @@ def report_missing_module_attribute( # Suggest alternatives, if any match is found. module = self.modules.get(import_id) if module: - if not self.options.implicit_reexport and source_id in module.names.keys(): + if source_id in module.names.keys(): message = ( - 'Module "{}" does not explicitly export attribute "{}"' - "; implicit reexport disabled".format(import_id, source_id) + f'Module "{import_id}" does not explicitly export attribute "{source_id}"' ) else: alternatives = set(module.names.keys()).difference({source_id}) diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index d7ce4c8848e3..03c2d1f38b82 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1613,7 +1613,7 @@ a = 5 [file other_module_2.py] from other_module_1 import a [out] -main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled +main:2: error: Module "other_module_2" does not explicitly export attribute "a" [case testNoImplicitReexportRespectsAll] # flags: --no-implicit-reexport @@ -1627,7 +1627,7 @@ from other_module_1 import a, b __all__ = ('b',) [builtins fixtures/tuple.pyi] [out] -main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled +main:2: error: Module "other_module_2" does not explicitly export attribute "a" [case testNoImplicitReexportStarConsideredExplicit] # flags: --no-implicit-reexport @@ -1643,7 +1643,7 @@ __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"; implicit reexport disabled +from other_module_2 import a # E: Module "other_module_2" does not explicitly export attribute "a" [file other_module_1.py] from typing import Any def __getattr__(name: str) -> Any: ... @@ -1661,7 +1661,7 @@ attr_2 = 6 [file other_module_2.py] from other_module_1 import attr_1, attr_2 [out] -main:2: error: Module "other_module_2" does not explicitly export attribute "attr_1"; implicit reexport disabled +main:2: error: Module "other_module_2" does not explicitly export attribute "attr_1" [case testNoImplicitReexportMypyIni] # flags: --config-file tmp/mypy.ini @@ -1679,7 +1679,7 @@ implicit_reexport = True \[mypy-other_module_2] implicit_reexport = False [out] -main:2: error: Module "other_module_2" has no attribute "a" +main:2: error: Module "other_module_2" does not explicitly export attribute "a" [case testNoImplicitReexportPyProjectTOML] @@ -1700,7 +1700,7 @@ module = 'other_module_2' implicit_reexport = false [out] -main:2: error: Module "other_module_2" has no attribute "a" +main:2: error: Module "other_module_2" does not explicitly export attribute "a" [case testImplicitAnyOKForNoArgs] diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 9b41692e52e6..a8eced3959e5 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1787,8 +1787,8 @@ m = n # E: Cannot assign multiple modules to name "m" without explicit "types.M [builtins fixtures/module.pyi] [case testNoReExportFromStubs] -from stub import Iterable # E: Module "stub" has no attribute "Iterable" -from stub import D # E: Module "stub" has no attribute "D" +from stub import Iterable # E: Module "stub" does not explicitly export attribute "Iterable" +from stub import D # E: Module "stub" does not explicitly export attribute "D" from stub import C c = C() @@ -1884,7 +1884,7 @@ class C: from util import mod reveal_type(mod) # N: Revealed type is "def () -> package.mod.mod" -from util import internal_detail # E: Module "util" has no attribute "internal_detail" +from util import internal_detail # E: Module "util" does not explicitly export attribute "internal_detail" [file package/__init__.pyi] from .mod import mod as mod @@ -1899,7 +1899,7 @@ from package import mod as internal_detail [builtins fixtures/module.pyi] [case testNoReExportUnrelatedModule] -from mod2 import unrelated # E: Module "mod2" has no attribute "unrelated" +from mod2 import unrelated # E: Module "mod2" does not explicitly export attribute "unrelated" [file mod1/__init__.pyi] [file mod1/unrelated.pyi] @@ -1910,7 +1910,7 @@ from mod1 import unrelated [builtins fixtures/module.pyi] [case testNoReExportUnrelatedSiblingPrefix] -from pkg.unrel import unrelated # E: Module "pkg.unrel" has no attribute "unrelated" +from pkg.unrel import unrelated # E: Module "pkg.unrel" does not explicitly export attribute "unrelated" [file pkg/__init__.pyi] [file pkg/unrelated.pyi] @@ -1922,7 +1922,7 @@ from pkg import unrelated [case testNoReExportChildStubs] import mod -from mod import C, D # E: Module "mod" has no attribute "C" +from mod import C, D # E: Module "mod" does not explicitly export attribute "C" reveal_type(mod.x) # N: Revealed type is "mod.submod.C" mod.C # E: "Module mod" does not explicitly export attribute "C" @@ -1940,7 +1940,7 @@ class D: [builtins fixtures/module.pyi] [case testNoReExportNestedStub] -from stub import substub # E: Module "stub" has no attribute "substub" +from stub import substub # E: Module "stub" does not explicitly export attribute "substub" [file stub.pyi] import substub @@ -2887,10 +2887,10 @@ CustomDict = TypedDict( [builtins fixtures/tuple.pyi] [case testNoReExportFromMissingStubs] -from stub import a # E: Module "stub" has no attribute "a" +from stub import a # E: Module "stub" does not explicitly export attribute "a" from stub import b from stub import c # E: Module "stub" has no attribute "c" -from stub import d # E: Module "stub" has no attribute "d" +from stub import d # E: Module "stub" does not explicitly export attribute "d" [file stub.pyi] from mystery import a, b as b, c as d From 82cb5844ad15a9b2c1fae24e475712c6bd180657 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 20 Oct 2022 12:24:18 -0700 Subject: [PATCH 2/2] fix tests --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 6ee93057ab3b..b37c9b2a5c77 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2346,7 +2346,7 @@ def report_missing_module_attribute( # Suggest alternatives, if any match is found. module = self.modules.get(import_id) if module: - if source_id in module.names.keys(): + if source_id in module.names.keys() and not module.names[source_id].module_public: message = ( f'Module "{import_id}" does not explicitly export attribute "{source_id}"' )