From c09719c4f292240c9716145c6c4cd9447181a55e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 18 Jun 2021 17:43:59 +0100 Subject: [PATCH 1/3] Don't ask to install a stub package if stubs are installed If we encounter an import of a submodule of a package with installed stubs, and the submodule doesn't exist, don't ask to install stubs since that's not going to help. Also make it possible to ignore this error using `--ignore-missing-imports`. Work on #10645. --- mypy/build.py | 5 +++-- mypy/modulefinder.py | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 59d46cdf9bb8..a39b78798d98 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2447,13 +2447,14 @@ def find_module_and_diagnose(manager: BuildManager, # Don't honor a global (not per-module) ignore_missing_imports # setting for modules that used to have bundled stubs, as # otherwise updating mypy can silently result in new false - # negatives. + # negatives. (Unless there are stubs but they are incomplete.) global_ignore_missing_imports = manager.options.ignore_missing_imports py_ver = options.python_version[0] if ((is_legacy_bundled_package(top_level, py_ver) or is_legacy_bundled_package(second_level, py_ver)) and global_ignore_missing_imports - and not options.ignore_missing_imports_per_module): + and not options.ignore_missing_imports_per_module + and result is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED): ignore_missing_imports = False if skip_diagnose: diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 4e608097289b..7f678cb6572a 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -232,8 +232,11 @@ def _find_module_non_stub_helper(self, components: List[str], plausible_match = True if (is_legacy_bundled_package(components[0], self.python_major_ver) or is_legacy_bundled_package('.'.join(components[:2]), self.python_major_ver)): - return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED - elif plausible_match: + if (len(components) == 1 + or (self.find_module(components[0]) is + ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED)): + return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED + if plausible_match: return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS else: return ModuleNotFoundReason.NOT_FOUND From 863aa516c613958658bd19c7d6ba9180152f15e1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 18 Jun 2021 17:50:08 +0100 Subject: [PATCH 2/3] Add tests --- test-data/unit/check-modules.test | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 9a68b00b6007..ad7322a2573f 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -3107,3 +3107,18 @@ from google.cloud import x main:1: error: Cannot find implementation or library stub for module named "google.cloud" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main:1: error: Cannot find implementation or library stub for module named "google" + +[case testMissingSubmoduleOfInstalledStubPackage] +import bleach.xyz +from bleach.abc import fgh +[file bleach/__init__.pyi] +[out] +main:1: error: Cannot find implementation or library stub for module named "bleach.xyz" +main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:2: error: Cannot find implementation or library stub for module named "bleach.abc" + +[case testMissingSubmoduleOfInstalledStubPackageIgnored] +# flags: --ignore-missing-imports +import bleach.xyz +from bleach.abc import fgh +[file bleach/__init__.pyi] From ce702c696eb1c3f78c1c3b43f318a116065f0080 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 21 Jun 2021 13:57:05 +0100 Subject: [PATCH 3/3] This doesn't work for google.protobuf, so skip the new logic --- mypy/modulefinder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 7f678cb6572a..eb763652175e 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -230,12 +230,13 @@ def _find_module_non_stub_helper(self, components: List[str], elif not plausible_match and (self.fscache.isdir(dir_path) or self.fscache.isfile(dir_path + ".py")): plausible_match = True - if (is_legacy_bundled_package(components[0], self.python_major_ver) - or is_legacy_bundled_package('.'.join(components[:2]), self.python_major_ver)): + if is_legacy_bundled_package(components[0], self.python_major_ver): if (len(components) == 1 or (self.find_module(components[0]) is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED)): return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED + if is_legacy_bundled_package('.'.join(components[:2]), self.python_major_ver): + return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED if plausible_match: return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS else: