From 3bbf264934aff17d49cf743f2982f153fa0ed2e6 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 7 Jun 2023 16:28:10 -0400 Subject: [PATCH 1/2] Prevent cache misses in do_import_module() If modname is None (default), it's okay to use the cache; there's no point in recreating the module ad nauseum. Closes #2041 Co-authored-by: Leandro T. C. Melo --- astroid/nodes/_base_nodes.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/astroid/nodes/_base_nodes.py b/astroid/nodes/_base_nodes.py index 3ef97b580c..c79fec799b 100644 --- a/astroid/nodes/_base_nodes.py +++ b/astroid/nodes/_base_nodes.py @@ -130,8 +130,11 @@ def do_import_module(self, modname: str | None = None) -> nodes.Module: # If the module ImportNode is importing is a module with the same name # as the file that contains the ImportNode we don't want to use the cache # to make sure we use the import system to get the correct module. - # pylint: disable-next=no-member # pylint doesn't recognize type of mymodule - if mymodule.relative_to_absolute_name(modname, level) == mymodule.name: + if ( + modname + # pylint: disable-next=no-member # pylint doesn't recognize type of mymodule + and mymodule.relative_to_absolute_name(modname, level) == mymodule.name + ): use_cache = False else: use_cache = True From 2add5ab0bea7fbe6f971f06c2112b57ccb069fbe Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 7 Jun 2023 17:15:46 -0400 Subject: [PATCH 2/2] Add regression test --- tests/test_inference.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test_inference.py b/tests/test_inference.py index 29bf56ac2c..868c83bc5f 100644 --- a/tests/test_inference.py +++ b/tests/test_inference.py @@ -22,6 +22,7 @@ Uninferable, arguments, helpers, + manager, nodes, objects, test_utils, @@ -991,6 +992,16 @@ def test_import_as(self) -> None: self.assertIsInstance(inferred[0], nodes.FunctionDef) self.assertEqual(inferred[0].name, "exists") + def test_do_import_module_performance(self) -> None: + import_node = extract_node("import importlib") + import_node.modname = "" + import_node.do_import_module() + # calling file_from_module_name() indicates we didn't hit the cache + with unittest.mock.patch.object( + manager.AstroidManager, "file_from_module_name", side_effect=AssertionError + ): + import_node.do_import_module() + def _test_const_inferred(self, node: nodes.AssignName, value: float | str) -> None: inferred = list(node.infer()) self.assertEqual(len(inferred), 1)