Skip to content

Commit 18ff207

Browse files
authored
Add __path__ to package __init__ (#9454)
Resolves #1422 Co-authored-by: hauntsaninja <>
1 parent 7919e59 commit 18ff207

File tree

7 files changed

+35
-15
lines changed

7 files changed

+35
-15
lines changed

mypy/nodes.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ def get_column(self) -> int:
9999

100100

101101
implicit_module_attrs: Final = {
102-
"__name__": "__builtins__.str",
103-
"__doc__": None, # depends on Python version, see semanal.py
104-
"__file__": "__builtins__.str",
105-
"__package__": "__builtins__.str",
102+
'__name__': '__builtins__.str',
103+
'__doc__': None, # depends on Python version, see semanal.py
104+
'__path__': None, # depends on if the module is a package
105+
'__file__': '__builtins__.str',
106+
'__package__': '__builtins__.str'
106107
}
107108

108109

mypy/semanal.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,17 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None:
427427
else:
428428
typ = UnionType([UnboundType('__builtins__.str'),
429429
UnboundType('__builtins__.unicode')])
430+
elif name == '__path__':
431+
if not file_node.is_package_init_file():
432+
continue
433+
# Need to construct the type ourselves, to avoid issues with __builtins__.list
434+
# not being subscriptable or typing.List not getting bound
435+
sym = self.lookup_qualified("__builtins__.list", Context())
436+
if not sym:
437+
continue
438+
node = sym.node
439+
assert isinstance(node, TypeInfo)
440+
typ = Instance(node, [self.str_type()])
430441
else:
431442
assert t is not None, 'type should be specified for {}'.format(name)
432443
typ = UnboundType(t)

test-data/unit/check-incomplete-fixture.test

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ import m
1212
m.x # E: "object" has no attribute "x"
1313
[file m.py]
1414

15-
[case testListMissingFromStubs]
16-
from typing import List
17-
def f(x: List[int]) -> None: pass
18-
[out]
19-
main:1: error: Module "typing" has no attribute "List"
20-
main:1: note: Maybe your test fixture does not define "builtins.list"?
21-
main:1: note: Consider adding [builtins fixtures/list.pyi] to your test description
22-
2315
[case testDictMissingFromStubs]
2416
from typing import Dict
2517
def f(x: Dict[int]) -> None: pass

test-data/unit/check-modules.test

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2888,6 +2888,16 @@ from mystery import a, b as b, c as d
28882888
tmp/stub.pyi:1: error: Cannot find implementation or library stub for module named "mystery"
28892889
tmp/stub.pyi:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
28902890

2891+
[case testPackagePath]
2892+
import p
2893+
reveal_type(p.__path__) # N: Revealed type is "builtins.list[builtins.str]"
2894+
p.m.__path__ # E: "object" has no attribute "__path__"
2895+
2896+
[file p/__init__.py]
2897+
from . import m as m
2898+
[file p/m.py]
2899+
[builtins fixtures/list.pyi]
2900+
28912901
[case testReExportAllInStub]
28922902
from m1 import C
28932903
from m1 import D # E: Module "m1" has no attribute "D"
@@ -3121,4 +3131,4 @@ main:2: error: Cannot find implementation or library stub for module named "blea
31213131
# flags: --ignore-missing-imports
31223132
import bleach.xyz
31233133
from bleach.abc import fgh
3124-
[file bleach/__init__.pyi]
3134+
[file bleach/__init__.pyi]

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,7 @@ x = 1
14371437
[file b/foo.py]
14381438
[file b/__init__.py.2]
14391439
# Dummy change
1440-
[builtins fixtures/bool.pyi]
1440+
[builtins fixtures/primitives.pyi]
14411441
[out]
14421442
==
14431443

test-data/unit/fixtures/args.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Builtins stub used to support *args, **kwargs.
22

3-
from typing import TypeVar, Generic, Iterable, Tuple, Dict, Any, overload, Mapping
3+
from typing import TypeVar, Generic, Iterable, Sequence, Tuple, Dict, Any, overload, Mapping
44

55
Tco = TypeVar('Tco', covariant=True)
66
T = TypeVar('T')
@@ -22,6 +22,8 @@ class tuple(Iterable[Tco], Generic[Tco]): pass
2222

2323
class dict(Iterable[T], Mapping[T, S], Generic[T, S]): pass
2424

25+
class list(Generic[T], Sequence[T]): pass
26+
2527
class int:
2628
def __eq__(self, o: object) -> bool: pass
2729
class str: pass

test-data/unit/lib-stub/builtins.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ class bytes: pass
2020
class function: pass
2121
class ellipsis: pass
2222

23+
from typing import Generic, Sequence, TypeVar
24+
_T = TypeVar('_T')
25+
class list(Generic[_T], Sequence[_T]): pass
26+
2327
# Definition of None is implicit

0 commit comments

Comments
 (0)