diff --git a/mypy/exportjson.py b/mypy/exportjson.py index 7bd341401ce9..f294b813ddbe 100644 --- a/mypy/exportjson.py +++ b/mypy/exportjson.py @@ -104,6 +104,7 @@ def convert_symbol_table(self: SymbolTable, cfg: Config) -> Json: if key == "__builtins__" or value.no_serialize: continue if not cfg.implicit_names and key in { + "__loader__", "__spec__", "__package__", "__file__", diff --git a/mypy/nodes.py b/mypy/nodes.py index cbeda29ec74a..2f2f4c4f90f3 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -176,6 +176,7 @@ def set_line( "__file__": "__builtins__.str", "__package__": "__builtins__.str", "__annotations__": None, # dict[str, Any] bounded in add_implicit_module_attrs() + "__loader__": None, # _typeshed.importlib.LoaderProtocol | None, see semanal.py "__spec__": None, # importlib.machinery.ModuleSpec bounded in add_implicit_module_attrs() } diff --git a/mypy/semanal.py b/mypy/semanal.py index 7f961687a8ae..59ae4d1260d0 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -771,6 +771,23 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None: self.defer() return typ = inst + elif name == "__loader__": + if self.options.use_builtins_fixtures: + inst = self.named_type_or_none("builtins.object") + else: + inst = self.named_type_or_none("_typeshed.importlib.LoaderProtocol") + if inst is None: + if ( + self.final_iteration + or self.options.clone_for_module("_typeshed.importlib").follow_imports + == "skip" + ): + inst = self.named_type_or_none("builtins.object") + assert inst is not None, "Cannot find builtins.object" + else: + self.defer() + return + typ = UnionType.make_union([inst, NoneType()]) elif name == "__spec__": if self.options.use_builtins_fixtures: inst = self.named_type_or_none("builtins.object") diff --git a/test-data/unit/fine-grained-inspect.test b/test-data/unit/fine-grained-inspect.test index 5caa1a94387b..c69f84bad104 100644 --- a/test-data/unit/fine-grained-inspect.test +++ b/test-data/unit/fine-grained-inspect.test @@ -236,7 +236,7 @@ class C: ... [builtins fixtures/module.pyi] [out] == -{"": ["C", "__annotations__", "__doc__", "__file__", "__name__", "__package__", "__spec__", "bar", "x"], "ModuleType": ["__file__", "__getattr__"]} +{"": ["C", "__annotations__", "__doc__", "__file__", "__loader__", "__name__", "__package__", "__spec__", "bar", "x"], "ModuleType": ["__file__", "__getattr__"]} [case testInspectModuleDef] # inspect2: --show=definition --include-kind tmp/foo.py:2:1