Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 56f8cf2

Browse filesBrowse files
committed
improve test coverage and documentation
1 parent 8263868 commit 56f8cf2
Copy full SHA for 56f8cf2

File tree

Expand file treeCollapse file tree

6 files changed

+165
-1
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+165
-1
lines changed

‎docs/source/command_line.rst

Copy file name to clipboardExpand all lines: docs/source/command_line.rst
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,29 @@ imports.
212212
By default, mypy will suppress any error messages generated within :pep:`561`
213213
compliant packages. Adding this flag will disable this behavior.
214214

215+
.. option:: --fast-module-lookup
216+
217+
The default logic used to scan through search paths to resolve imports has a
218+
quadratic worse-case behavior in some cases, which is for instance triggered
219+
by a large number of folders sharing a top-level namespace as in:
220+
221+
foo/
222+
company/
223+
foo/
224+
a.py
225+
bar/
226+
company/
227+
bar/
228+
b.py
229+
baz/
230+
company/
231+
baz/
232+
c.py
233+
...
234+
235+
If you are in this situation, you can enable an experimental fast path by
236+
setting the :option:`--fast-module-lookup` option.
237+
215238

216239
.. _platform-configuration:
217240

‎docs/source/running_mypy.rst

Copy file name to clipboardExpand all lines: docs/source/running_mypy.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ same directory on the search path, only the stub file is used.
516516
(However, if the files are in different directories, the one found
517517
in the earlier directory is used.)
518518

519+
519520
Other advice and best practices
520521
*******************************
521522

‎mypy/main.py

Copy file name to clipboardExpand all lines: mypy/main.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ def add_invertible_flag(flag: str,
883883
group=code_group)
884884
add_invertible_flag(
885885
'--fast-module-lookup', default=False,
886-
help="Enable fast path for finding modules within input sources",
886+
help=argparse.SUPPRESS,
887887
group=code_group)
888888
code_group.add_argument(
889889
"--exclude",

‎mypy/modulefinder.py

Copy file name to clipboardExpand all lines: mypy/modulefinder.py
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ def clear(self) -> None:
195195
self.ns_ancestors.clear()
196196

197197
def find_module_via_source_set(self, id: str) -> Optional[ModuleSearchResult]:
198+
"""Fast path to find modules by looking through the input sources
199+
200+
This is only used when --fast-module-lookup is passed on the command line."""
198201
if not self.source_set:
199202
return None
200203

‎mypy/test/testcheck.py

Copy file name to clipboardExpand all lines: mypy/test/testcheck.py
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
'check-multiple-inheritance.test',
4747
'check-super.test',
4848
'check-modules.test',
49+
'check-modules-fast.test',
4950
'check-typevar-values.test',
5051
'check-unsupported.test',
5152
'check-unreachable-code.test',
+136Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
-- Type checker test cases dealing with module lookup edge cases
2+
-- to ensure that --fast-module-lookup matches regular lookup behavior
3+
4+
[case testModuleLookup]
5+
# flags: --fast-module-lookup
6+
import m
7+
reveal_type(m.a) # N: Revealed type is "m.A"
8+
9+
[file m.py]
10+
class A: pass
11+
a = A()
12+
13+
[case testModuleLookupStub]
14+
# flags: --fast-module-lookup
15+
import m
16+
reveal_type(m.a) # N: Revealed type is "m.A"
17+
18+
[file m.pyi]
19+
class A: pass
20+
a = A()
21+
22+
[case testModuleLookupFromImport]
23+
# flags: --fast-module-lookup
24+
from m import a
25+
reveal_type(a) # N: Revealed type is "m.A"
26+
27+
[file m.py]
28+
class A: pass
29+
a = A()
30+
31+
[case testModuleLookupStubFromImport]
32+
# flags: --fast-module-lookup
33+
from m import a
34+
reveal_type(a) # N: Revealed type is "m.A"
35+
36+
[file m.pyi]
37+
class A: pass
38+
a = A()
39+
40+
41+
[case testModuleLookupWeird]
42+
# flags: --fast-module-lookup
43+
from m import a
44+
reveal_type(a) # N: Revealed type is "builtins.object"
45+
reveal_type(a.b) # N: Revealed type is "m.a.B"
46+
47+
[file m.py]
48+
class A: pass
49+
a = A()
50+
51+
[file m/__init__.py]
52+
[file m/a.py]
53+
class B: pass
54+
b = B()
55+
56+
57+
[case testModuleLookupWeird2]
58+
# flags: --fast-module-lookup
59+
from m.a import b
60+
reveal_type(b) # N: Revealed type is "m.a.B"
61+
62+
[file m.py]
63+
class A: pass
64+
a = A()
65+
66+
[file m/__init__.py]
67+
[file m/a.py]
68+
class B: pass
69+
b = B()
70+
71+
72+
[case testModuleLookupWeird3]
73+
# flags: --fast-module-lookup
74+
from m.a import b
75+
reveal_type(b) # N: Revealed type is "m.a.B"
76+
77+
[file m.py]
78+
class A: pass
79+
a = A()
80+
[file m/__init__.py]
81+
class B: pass
82+
a = B()
83+
[file m/a.py]
84+
class B: pass
85+
b = B()
86+
87+
88+
[case testModuleLookupWeird4]
89+
# flags: --fast-module-lookup
90+
import m.a
91+
m.a.b # E: "str" has no attribute "b"
92+
93+
[file m.py]
94+
class A: pass
95+
a = A()
96+
[file m/__init__.py]
97+
class B: pass
98+
a = 'foo'
99+
b = B()
100+
[file m/a.py]
101+
class C: pass
102+
b = C()
103+
104+
105+
[case testModuleLookupWeird5]
106+
# flags: --fast-module-lookup
107+
import m.a as ma
108+
reveal_type(ma.b) # N: Revealed type is "m.a.C"
109+
110+
[file m.py]
111+
class A: pass
112+
a = A()
113+
[file m/__init__.py]
114+
class B: pass
115+
a = 'foo'
116+
b = B()
117+
[file m/a.py]
118+
class C: pass
119+
b = C()
120+
121+
122+
[case testModuleLookupWeird6]
123+
# flags: --fast-module-lookup
124+
from m.a import b
125+
reveal_type(b) # N: Revealed type is "m.a.C"
126+
127+
[file m.py]
128+
class A: pass
129+
a = A()
130+
[file m/__init__.py]
131+
class B: pass
132+
a = 'foo'
133+
b = B()
134+
[file m/a.py]
135+
class C: pass
136+
b = C()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.