@@ -49,10 +49,18 @@ class ModuleNotFoundReason(Enum):
49
49
# corresponding *-stubs package.
50
50
FOUND_WITHOUT_TYPE_HINTS = 1
51
51
52
+ # The module was not found in the current working directory, but
53
+ # was able to be found in the parent directory.
54
+ WRONG_WORKING_DIRECTORY = 2
55
+
52
56
def error_message_templates (self ) -> Tuple [str , str ]:
53
57
if self is ModuleNotFoundReason .NOT_FOUND :
54
58
msg = "Cannot find implementation or library stub for module named '{}'"
55
59
note = "See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports"
60
+ elif self is ModuleNotFoundReason .WRONG_WORKING_DIRECTORY :
61
+ msg = "Cannot find implementation or library stub for module named '{}'"
62
+ note = ("You may be running mypy in a subpackage, "
63
+ "mypy should be run on the package root" )
56
64
elif self is ModuleNotFoundReason .FOUND_WITHOUT_TYPE_HINTS :
57
65
msg = "Skipping analyzing '{}': found module but no type hints or library stubs"
58
66
note = "See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports"
@@ -166,6 +174,9 @@ def find_module(self, id: str) -> ModuleSearchResult:
166
174
"""Return the path of the module source file or why it wasn't found."""
167
175
if id not in self .results :
168
176
self .results [id ] = self ._find_module (id )
177
+ if (self .results [id ] is ModuleNotFoundReason .NOT_FOUND
178
+ and self ._can_find_module_in_parent_dir (id )):
179
+ self .results [id ] = ModuleNotFoundReason .WRONG_WORKING_DIRECTORY
169
180
return self .results [id ]
170
181
171
182
def _find_module_non_stub_helper (self , components : List [str ],
@@ -192,6 +203,20 @@ def _update_ns_ancestors(self, components: List[str], match: Tuple[str, bool]) -
192
203
self .ns_ancestors [pkg_id ] = path
193
204
path = os .path .dirname (path )
194
205
206
+ def _can_find_module_in_parent_dir (self , id : str ) -> bool :
207
+ """Test if a module can be found by checking the parent directories
208
+ of the current working directory.
209
+ """
210
+ working_dir = os .getcwd ()
211
+ parent_search = FindModuleCache (SearchPaths ((), (), (), ()))
212
+ while any (file .endswith (("__init__.py" , "__init__.pyi" ))
213
+ for file in os .listdir (working_dir )):
214
+ working_dir = os .path .dirname (working_dir )
215
+ parent_search .search_paths = SearchPaths ((working_dir ,), (), (), ())
216
+ if not isinstance (parent_search ._find_module (id ), ModuleNotFoundReason ):
217
+ return True
218
+ return False
219
+
195
220
def _find_module (self , id : str ) -> ModuleSearchResult :
196
221
fscache = self .fscache
197
222
0 commit comments