@@ -55,14 +55,14 @@ class ModuleNotFoundReason(Enum):
55
55
def error_message_templates (self ) -> Tuple [str , List [str ]]:
56
56
doc_link = "See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports"
57
57
if self is ModuleNotFoundReason .NOT_FOUND :
58
- msg = 'Cannot find implementation or library stub for module named "{}"'
58
+ msg = 'Cannot find implementation or library stub for module named "{module }"'
59
59
notes = [doc_link ]
60
60
elif self is ModuleNotFoundReason .FOUND_WITHOUT_TYPE_HINTS :
61
- msg = 'Skipping analyzing "{}": found module but no type hints or library stubs'
61
+ msg = 'Skipping analyzing "{module }": found module but no type hints or library stubs'
62
62
notes = [doc_link ]
63
63
elif self is ModuleNotFoundReason .STUBS_NOT_INSTALLED :
64
- msg = 'Library stubs not installed for "{}" '
65
- notes = ['Hint: "python3 -m pip install {}"' ,
64
+ msg = 'Library stubs not installed for "{module}" (or incompatible with Python {pyver}) '
65
+ notes = ['Hint: "python3 -m pip install {stub_dist }"' ,
66
66
'(or run "mypy --install-types" to install all missing stub packages)' ,
67
67
doc_link ]
68
68
else :
@@ -230,7 +230,7 @@ def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult:
230
230
for pkg_dir in self .search_paths .package_path :
231
231
stub_name = components [0 ] + '-stubs'
232
232
stub_dir = os .path .join (pkg_dir , stub_name )
233
- if fscache .isdir (stub_dir ):
233
+ if fscache .isdir (stub_dir ) and self . _is_compatible_stub_package ( stub_dir ) :
234
234
stub_typed_file = os .path .join (stub_dir , 'py.typed' )
235
235
stub_components = [stub_name ] + components [1 :]
236
236
path = os .path .join (pkg_dir , * stub_components [:- 1 ])
@@ -360,6 +360,24 @@ def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult:
360
360
else :
361
361
return ModuleNotFoundReason .NOT_FOUND
362
362
363
+ def _is_compatible_stub_package (self , stub_dir : str ) -> bool :
364
+ """Does a stub package support the target Python version?
365
+
366
+ Stub packages may contain a metadata file which specifies
367
+ whether the stubs are compatible with Python 2 and 3.
368
+ """
369
+ metadata_fnam = os .path .join (stub_dir , 'METADATA.toml' )
370
+ if os .path .isfile (metadata_fnam ) and self .options :
371
+ # Delay import for a possible minor performance win.
372
+ import toml
373
+ with open (metadata_fnam , 'r' ) as f :
374
+ metadata = toml .load (f )
375
+ if self .options .python_version [0 ] == 2 :
376
+ return bool (metadata .get ('python2' , False ))
377
+ else :
378
+ return bool (metadata .get ('python3' , True ))
379
+ return True
380
+
363
381
def find_modules_recursive (self , module : str ) -> List [BuildSource ]:
364
382
module_path = self .find_module (module )
365
383
if isinstance (module_path , ModuleNotFoundReason ):
0 commit comments