Skip to content

Commit

Permalink
Disallow undesirable implicit reexport with ImportFrom (#12704)
Browse files Browse the repository at this point in the history
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 <>
  • Loading branch information
hauntsaninja authored Jun 24, 2022
1 parent 5039c0f commit e046e20
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
12 changes: 8 additions & 4 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1900,10 +1900,14 @@ def process_imported_symbol(self,
fullname: str,
module_public: bool,
context: ImportBase) -> None:
module_hidden = not module_public and not (
# `from package import module` should work regardless of whether package
# re-exports module
isinstance(node.node, MypyFile) and fullname in self.modules
module_hidden = not module_public and (
# `from package import submodule` should work regardless of whether package
# re-exports submodule, so we shouldn't hide it
not isinstance(node.node, MypyFile)
or fullname not in self.modules
# but given `from somewhere import random_unrelated_module` we should hide
# random_unrelated_module
or not fullname.startswith(self.cur_mod_id + ".")
)

if isinstance(node.node, PlaceholderNode):
Expand Down
22 changes: 22 additions & 0 deletions test-data/unit/check-modules.test
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,28 @@ from package import mod as mod
from package import mod as internal_detail
[builtins fixtures/module.pyi]

[case testNoReExportUnrelatedModule]
from mod2 import unrelated # E: Module "mod2" has no attribute "unrelated"

[file mod1/__init__.pyi]
[file mod1/unrelated.pyi]
x: int

[file mod2.pyi]
from mod1 import unrelated
[builtins fixtures/module.pyi]

[case testNoReExportUnrelatedSiblingPrefix]
from pkg.unrel import unrelated # E: Module "pkg.unrel" has no attribute "unrelated"

[file pkg/__init__.pyi]
[file pkg/unrelated.pyi]
x: int

[file pkg/unrel.pyi]
from pkg import unrelated
[builtins fixtures/module.pyi]

[case testNoReExportChildStubs]
import mod
from mod import C, D # E: Module "mod" has no attribute "C"
Expand Down

0 comments on commit e046e20

Please sign in to comment.