diff --git a/cinderx/PythonLib/cinderx/compiler/static/declaration_visitor.py b/cinderx/PythonLib/cinderx/compiler/static/declaration_visitor.py index 3589b0c72ce..811b23eb2fc 100644 --- a/cinderx/PythonLib/cinderx/compiler/static/declaration_visitor.py +++ b/cinderx/PythonLib/cinderx/compiler/static/declaration_visitor.py @@ -236,7 +236,9 @@ def visitImport(self, node: Import) -> None: top_level_module, None, DeferredImport( + self.module, name.name, + top_level_module, self.optimize, self.compiler, mod_to_return=top_level_module, @@ -246,7 +248,9 @@ def visitImport(self, node: Import) -> None: self.module.declare_import( asname, None, - DeferredImport(name.name, self.optimize, self.compiler), + DeferredImport( + self.module, name.name, asname, self.optimize, self.compiler + ), ) def visitImportFrom(self, node: ImportFrom) -> None: @@ -258,7 +262,14 @@ def visitImportFrom(self, node: ImportFrom) -> None: self.module.declare_import( child_name, (mod_name, name.name), - DeferredImport(mod_name, self.optimize, self.compiler, name.name), + DeferredImport( + self.module, + mod_name, + name.name, + self.optimize, + self.compiler, + name.name, + ), ) # We don't pick up declarations in nested statements diff --git a/cinderx/PythonLib/cinderx/compiler/static/module_table.py b/cinderx/PythonLib/cinderx/compiler/static/module_table.py index 37752b74795..b06441a8bf7 100644 --- a/cinderx/PythonLib/cinderx/compiler/static/module_table.py +++ b/cinderx/PythonLib/cinderx/compiler/static/module_table.py @@ -204,13 +204,17 @@ def __init__(self, reason: str) -> None: class DeferredImport: def __init__( self, + in_module: ModuleTable, mod_to_import: str, + asname: str, optimize: int, compiler: Compiler, name: str | None = None, mod_to_return: str | None = None, ) -> None: + self.in_module = in_module self.mod_to_import = mod_to_import + self.asname = asname self.name = name self.mod_to_return = mod_to_return self.compiler = compiler @@ -241,6 +245,11 @@ def resolve(self) -> Value: raise ModuleTableException( f"Cannot find {self.mod_to_import}.{self.name} due to cyclic reference" ) + # For unknown modules, we don't need to record each individual object + # used from them; it doesn't matter, as we won't track transitive deps + # across them. We just need to record a dependency to the module in + # general. + self.in_module.record_dependency(self.asname, (self.mod_to_import, "")) return self.compiler.type_env.DYNAMIC diff --git a/cinderx/test_cinderx/test_compiler/test_static/dependencies.py b/cinderx/test_cinderx/test_compiler/test_static/dependencies.py index 1d52de2b868..4c08fb8a36d 100644 --- a/cinderx/test_cinderx/test_compiler/test_static/dependencies.py +++ b/cinderx/test_cinderx/test_compiler/test_static/dependencies.py @@ -398,15 +398,30 @@ def g(): def test_dep_on_unknown_module(self) -> None: """We record deps on non-static modules; they could become static.""" - code = """ - from unknown import U + for from_import in [True, False]: + if from_import: + code = """ + from unknown import U - class C(U): - pass - """ - compiler = self.compiler(mod=code) - compiler.compile_module("mod") - self.assertDep(compiler.modules["mod"].decl_deps, "C", {("unknown", "U")}) + class C(U): + pass + """ + else: + code = """ + import unknown as unk + + class C(unk.U): + pass + """ + with self.subTest(from_import=from_import): + compiler = self.compiler(mod=code) + compiler.compile_module("mod") + expected = {("unknown", "U")} if from_import else {("mod", "unk")} + self.assertDep(compiler.modules["mod"].decl_deps, "C", expected) + if not from_import: + self.assertDep( + compiler.modules["mod"].decl_deps, "unk", {("unknown", "")} + ) class GetDependenciesTests(StaticTestBase):