diff --git a/mypy/semanal.py b/mypy/semanal.py index d7b50bd09496..038a914c2df6 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -719,7 +719,15 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None: else: inst = self.named_type_or_none("importlib.machinery.ModuleSpec") if inst is None: - if self.final_iteration: + if ( + self.final_iteration + or self.options.clone_for_module("importlib.machinery").follow_imports + == "skip" + ): + # If we are not allowed to resolve imports from `importlib.machinery`, + # ModuleSpec will not be available at any iteration. + # Use the fallback earlier. + # (see https://github.com/python/mypy/issues/18237) inst = self.named_type_or_none("builtins.object") assert inst is not None, "Cannot find builtins.object" else: diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 35d7b700b161..bed4134bff72 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1393,3 +1393,21 @@ Ts = TypeVarTuple("Ts") Warning: TypeVarTuple is already enabled by default Warning: Unpack is already enabled by default == Return code: 0 + +[case testImportlibImportCannotBeResolved] +# cmd: mypy a.py +# This test is here because it needs use_builtins_fixtures off. + +[file a.py] +from typing import NamedTuple + +class CodecKey(NamedTuple): + def foo(self) -> "CodecKey": + ... + +[file mypy.ini] +\[mypy] + +\[mypy-importlib.*] +follow_imports = skip +follow_imports_for_stubs = True