From 0c077147ccec94697229f7e1f6c75a4c2c3dfbe8 Mon Sep 17 00:00:00 2001 From: STerliakov Date: Sun, 2 Nov 2025 15:53:17 +0100 Subject: [PATCH 1/2] Use the fallback for `ModuleSpec` early if it can never be resolved --- mypy/semanal.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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: From 8af60ed9af261d1ee1c6e423c9c6d22876988a17 Mon Sep 17 00:00:00 2001 From: STerliakov Date: Sun, 2 Nov 2025 15:57:48 +0100 Subject: [PATCH 2/2] Add a testcase --- test-data/unit/cmdline.test | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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