Skip to content

Commit e046e20

Browse files
authored
Disallow undesirable implicit reexport with ImportFrom (#12704)
Fixes #12689 We always hid e.g. `import concurrent`, but looks like mypy never hid `from concurrent import futures`. It's possible this fix is pretty breaking for users, let's see what primer thinks. I last touched this logic in #11707, which fixed cases involving implicitly reexported symbols that shared the name of a module Co-authored-by: hauntsaninja <>
1 parent 5039c0f commit e046e20

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

mypy/semanal.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,10 +1900,14 @@ def process_imported_symbol(self,
19001900
fullname: str,
19011901
module_public: bool,
19021902
context: ImportBase) -> None:
1903-
module_hidden = not module_public and not (
1904-
# `from package import module` should work regardless of whether package
1905-
# re-exports module
1906-
isinstance(node.node, MypyFile) and fullname in self.modules
1903+
module_hidden = not module_public and (
1904+
# `from package import submodule` should work regardless of whether package
1905+
# re-exports submodule, so we shouldn't hide it
1906+
not isinstance(node.node, MypyFile)
1907+
or fullname not in self.modules
1908+
# but given `from somewhere import random_unrelated_module` we should hide
1909+
# random_unrelated_module
1910+
or not fullname.startswith(self.cur_mod_id + ".")
19071911
)
19081912

19091913
if isinstance(node.node, PlaceholderNode):

test-data/unit/check-modules.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,28 @@ from package import mod as mod
19291929
from package import mod as internal_detail
19301930
[builtins fixtures/module.pyi]
19311931

1932+
[case testNoReExportUnrelatedModule]
1933+
from mod2 import unrelated # E: Module "mod2" has no attribute "unrelated"
1934+
1935+
[file mod1/__init__.pyi]
1936+
[file mod1/unrelated.pyi]
1937+
x: int
1938+
1939+
[file mod2.pyi]
1940+
from mod1 import unrelated
1941+
[builtins fixtures/module.pyi]
1942+
1943+
[case testNoReExportUnrelatedSiblingPrefix]
1944+
from pkg.unrel import unrelated # E: Module "pkg.unrel" has no attribute "unrelated"
1945+
1946+
[file pkg/__init__.pyi]
1947+
[file pkg/unrelated.pyi]
1948+
x: int
1949+
1950+
[file pkg/unrel.pyi]
1951+
from pkg import unrelated
1952+
[builtins fixtures/module.pyi]
1953+
19321954
[case testNoReExportChildStubs]
19331955
import mod
19341956
from mod import C, D # E: Module "mod" has no attribute "C"

0 commit comments

Comments
 (0)