Skip to content

Commit bfeae2c

Browse files
author
hauntsaninja
committed
Fix caching of PEP 561 namespace packages with missing submodules
Fixes #12232 Another "fail every 2nd run" bug
1 parent b22c4e4 commit bfeae2c

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

mypy/build.py

+6-11
Original file line numberDiff line numberDiff line change
@@ -736,14 +736,6 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str:
736736
pri = import_priority(imp, PRI_MED)
737737
ancestor_pri = import_priority(imp, PRI_LOW)
738738
for id, _ in imp.ids:
739-
# We append the target (e.g. foo.bar.baz)
740-
# before the ancestors (e.g. foo and foo.bar)
741-
# so that, if FindModuleCache finds the target
742-
# module in a package marked with py.typed
743-
# underneath a namespace package installed in
744-
# site-packages, (gasp), that cache's
745-
# knowledge of the ancestors can be primed
746-
# when it is asked to find the target.
747739
res.append((pri, id, imp.line))
748740
ancestor_parts = id.split(".")[:-1]
749741
ancestors = []
@@ -768,14 +760,17 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str:
768760
# if all of the imports are submodules, do the import at a lower
769761
# priority.
770762
pri = import_priority(imp, PRI_HIGH if not all_are_submodules else PRI_LOW)
771-
# The imported module goes in after the
772-
# submodules, for the same namespace related
773-
# reasons discussed in the Import case.
774763
res.append((pri, cur_id, imp.line))
775764
elif isinstance(imp, ImportAll):
776765
pri = import_priority(imp, PRI_HIGH)
777766
res.append((pri, correct_rel_imp(imp), imp.line))
778767

768+
# Ensure that foo.bar.baz is always before foo.bar and foo
769+
# This ensures that if FindModuleCache finds a module in a package marked with py.typed
770+
# underneath a namespace package installed in site-packages, (gasp), that cache's knowledge
771+
# of the ancestors (FindModuleCache.ns_ancestors) is primed when it is asked to find the
772+
# parent.
773+
res.sort(key=lambda x: -len(x[1]))
779774
return res
780775

781776
def is_module(self, id: str) -> bool:

test-data/unit/pep561.test

+10
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,13 @@ b.bf(1)
222222
[out]
223223
testNamespacePkgWStubsWithNamespacePackagesFlag.py:7: error: Argument 1 to "bf" has incompatible type "int"; expected "bool"
224224
testNamespacePkgWStubsWithNamespacePackagesFlag.py:8: error: Argument 1 to "bf" has incompatible type "int"; expected "bool"
225+
226+
227+
[case testTypedPkgNamespaceRegFromImportTwiceMissing]
228+
# pkgs: typedpkg_ns_a
229+
from typedpkg_ns import b # type: ignore
230+
from typedpkg_ns import a
231+
-- dummy should trigger a second iteration
232+
[file dummy.py.2]
233+
[out]
234+
[out2]

0 commit comments

Comments
 (0)