diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 93096e54e6..618faa4456 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -24,6 +24,8 @@ from . import util +modpath_cache = {} + # The MetaPathFinder protocol comes from typeshed, which says: # Intentionally omits one deprecated and one optional method of `importlib.abc.MetaPathFinder` @@ -423,6 +425,18 @@ def _find_spec_with_path( raise ImportError(f"No module named {'.'.join(module_parts)}") +def cache_modpath(func): + def wrapper(*args): + key = ".".join(args[0]) + if key not in modpath_cache: + modpath_cache[key] = func(*args) + + return modpath_cache[key] + + return wrapper + + +@cache_modpath def find_spec(modpath: list[str], path: Sequence[str] | None = None) -> ModuleSpec: """Find a spec for the given module. diff --git a/tests/test_manager.py b/tests/test_manager.py index 7861927930..4db6e7053a 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -41,6 +41,7 @@ class AstroidManagerTest( ): def setUp(self) -> None: super().setUp() + astroid.interpreter._import.spec.modpath_cache.clear() self.manager = test_utils.brainless_manager() def test_ast_from_file(self) -> None: diff --git a/tests/test_modutils.py b/tests/test_modutils.py index 929c58992c..8f21064cb2 100644 --- a/tests/test_modutils.py +++ b/tests/test_modutils.py @@ -41,6 +41,7 @@ class ModuleFileTest(unittest.TestCase): package = "mypypa" def tearDown(self) -> None: + astroid.interpreter._import.spec.modpath_cache.clear() for k in list(sys.path_importer_cache): if "MyPyPa" in k: del sys.path_importer_cache[k]