diff --git a/mypy/build.py b/mypy/build.py index e4b202c4e72ba..9e4e3d7ebd220 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -1478,6 +1478,24 @@ def calculate_mros(self) -> None: fixup_module_pass_two(self.tree, self.manager.modules, self.manager.options.quick_and_dirty) + def patch_dependency_parents(self) -> None: + """ + In Python, if a and a.b are both modules, running `import a.b` will + modify not only the current module's namespace, but a's namespace as + well -- see SemanticAnalyzer.add_submodules_to_parent_modules for more + details. + + However, this patching process can occur after `a` has been parsed and + serialized during increment mode. Consequently, we need to repeat this + patch when deserializing a cached file. + + This function should be called only when processing fresh SCCs -- the + semantic analyzer will perform this patch for us when processing stale + SCCs. + """ + for dep in self.dependencies: + self.manager.semantic_analyzer.add_submodules_to_parent_modules(dep, True) + def fix_suppressed_dependencies(self, graph: Graph) -> None: """Corrects whether dependencies are considered stale in silent mode. @@ -2010,6 +2028,8 @@ def process_fresh_scc(graph: Graph, scc: List[str]) -> None: graph[id].fix_cross_refs() for id in scc: graph[id].calculate_mros() + for id in scc: + graph[id].patch_dependency_parents() def process_stale_scc(graph: Graph, scc: List[str], manager: BuildManager) -> None: diff --git a/test-data/unit/check-serialize.test b/test-data/unit/check-serialize.test index 2504fe6aa1c5f..9576d95c7eefa 100644 --- a/test-data/unit/check-serialize.test +++ b/test-data/unit/check-serialize.test @@ -1103,8 +1103,7 @@ main:3: error: Too few arguments for "g" [out2] main:3: error: Too few arguments for "g" -[case testSerializeQualifiedImport-skip] -# This fails currently: https://github.com/python/mypy/issues/3274 +[case testSerializeQualifiedImport] import b b.c.d.f() b.c.d.g()