Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f5afdcd

Browse files
Add support for __spec__ (#14739)
Fixes #4145 Co-authored-by: Joongi Kim <[email protected]>
1 parent 3579c61 commit f5afdcd

5 files changed

Lines changed: 34 additions & 1 deletion

File tree

mypy/nodes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def set_line(
117117
"__file__": "__builtins__.str",
118118
"__package__": "__builtins__.str",
119119
"__annotations__": None, # dict[str, Any] bounded in add_implicit_module_attrs()
120+
"__spec__": None, # importlib.machinery.ModuleSpec bounded in add_implicit_module_attrs()
120121
}
121122

122123

mypy/semanal.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@
283283
TypeVarTupleType,
284284
TypeVarType,
285285
UnboundType,
286+
UnionType,
286287
UnpackType,
287288
get_proper_type,
288289
get_proper_types,
@@ -635,6 +636,7 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None:
635636
str_type: Type | None = self.named_type_or_none("builtins.str")
636637
if str_type is None:
637638
str_type = UnboundType("builtins.str")
639+
inst: Type | None
638640
for name, t in implicit_module_attrs.items():
639641
if name == "__doc__":
640642
typ: Type = str_type
@@ -660,6 +662,22 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None:
660662
self.defer()
661663
return
662664
typ = inst
665+
elif name == "__spec__":
666+
if self.options.use_builtins_fixtures:
667+
inst = self.named_type_or_none("builtins.object")
668+
else:
669+
inst = self.named_type_or_none("importlib.machinery.ModuleSpec")
670+
if inst is None:
671+
if self.final_iteration:
672+
inst = self.named_type_or_none("builtins.object")
673+
assert inst is not None, "Cannot find builtins.object"
674+
else:
675+
self.defer()
676+
return
677+
if file_node.name == "__main__":
678+
# https://docs.python.org/3/reference/import.html#main-spec
679+
inst = UnionType.make_union([inst, NoneType()])
680+
typ = inst
663681
else:
664682
assert t is not None, f"type should be specified for {name}"
665683
typ = UnboundType(t)

test-data/unit/check-basic.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ reveal_type(__doc__) # N: Revealed type is "builtins.str"
219219
reveal_type(__file__) # N: Revealed type is "builtins.str"
220220
reveal_type(__package__) # N: Revealed type is "builtins.str"
221221
reveal_type(__annotations__) # N: Revealed type is "builtins.dict[builtins.str, Any]"
222+
# This will actually reveal Union[importlib.machinery.ModuleSpec, None]
223+
reveal_type(__spec__) # N: Revealed type is "Union[builtins.object, None]"
224+
225+
import module
226+
reveal_type(module.__name__) # N: Revealed type is "builtins.str"
227+
# This will actually reveal importlib.machinery.ModuleSpec
228+
reveal_type(module.__spec__) # N: Revealed type is "builtins.object"
229+
[file module.py]
222230
[builtins fixtures/primitives.pyi]
223231

224232

test-data/unit/fine-grained-inspect.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class C: ...
236236
[builtins fixtures/module.pyi]
237237
[out]
238238
==
239-
{"<pack.bar>": ["C", "__annotations__", "__doc__", "__file__", "__name__", "__package__", "bar", "x"], "ModuleType": ["__file__", "__getattr__"]}
239+
{"<pack.bar>": ["C", "__annotations__", "__doc__", "__file__", "__name__", "__package__", "__spec__", "bar", "x"], "ModuleType": ["__file__", "__getattr__"]}
240240

241241
[case testInspectModuleDef]
242242
# inspect2: --show=definition --include-kind tmp/foo.py:2:1

test-data/unit/pythoneval.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,20 @@ f
107107
[case testModuleAttributes]
108108
import math
109109
import typing
110+
print(type(__spec__))
110111
print(math.__name__)
112+
print(math.__spec__.name)
111113
print(type(math.__dict__))
112114
print(type(math.__doc__ or ''))
115+
print(type(math.__spec__).__name__)
113116
print(math.__class__)
114117
[out]
118+
<class 'NoneType'>
119+
math
115120
math
116121
<class 'dict'>
117122
<class 'str'>
123+
ModuleSpec
118124
<class 'module'>
119125

120126
[case testSpecialAttributes]

0 commit comments

Comments
 (0)