diff --git a/mypy/build.py b/mypy/build.py index 5b4c7744b907..5919c995d2c1 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -11,6 +11,7 @@ # TODO: More consistent terminology, e.g. path/fnam, module/id, state/file import contextlib +import copy import errno import gc import json @@ -2440,16 +2441,25 @@ def find_module_and_diagnose(manager: BuildManager, # Could not find a module. Typically the reason is a # misspelled module name, missing stub, module not in # search path or the module has not been installed. - ignore_missing_imports = options.ignore_missing_imports top_level = file_id.partition('.')[0] + # 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. However, if ignore_missing_imports was set + # at the module level, we will honor it. + # https://github.com/python/mypy/issues/10283 global_ignore_missing_imports = manager.options.ignore_missing_imports if top_level in legacy_bundled_packages and global_ignore_missing_imports: - ignore_missing_imports = False + # To see if this ignore_missing_imports was due to the global or due to the + # module, let's copy the options, set global ignore_missing_imports to False + # and then look again. + options_copy = copy.deepcopy(manager.options) + options_copy.ignore_missing_imports = False + module_copy = options_copy.clone_for_module(id) + if not module_copy.ignore_missing_imports: + ignore_missing_imports = False if skip_diagnose: raise ModuleNotFound diff --git a/mypy/options.py b/mypy/options.py index 9e41ad7d310d..6a1a1e7d6d66 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -141,7 +141,7 @@ def __init__(self) -> None: # Warn about unused '# type: ignore' comments self.warn_unused_ignores = False - # Warn about unused '[mypy-]' or '[[tool.mypy.overrides]]' config sections + # Warn about unused '[mypy-]' or '[[tool.mypy.overrides]]' config sections self.warn_unused_configs = False # Files in which to ignore all non-fatal errors diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index ddabfe252253..f5dc56e689bf 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1,6 +1,7 @@ -- Type checker test cases dealing with modules and imports. -- Towards the end there are tests for PEP 420 (namespace packages, i.e. __init__.py-less packages). + [case testAccessImportedDefinitions] import m import typing @@ -2982,3 +2983,43 @@ T = TypeVar("T") class F(M): x: C class C: ... + + +-- https://github.com/python/mypy/issues/10283 +[case testIgnoreMissingImportsGlobalWithMissingStub] +# flags: --config-file tmp/pyproject.toml +from redis.sentinel import Sentinel + +[file pyproject.toml] +\[tool.mypy] +ignore_missing_imports = true + +[out] +main:2: error: Cannot find implementation or library stub for module named "redis.sentinel" +main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports + + +-- https://github.com/python/mypy/issues/10283 +[case testIgnoreMissingImportsWildcardWithMissingStub] +# flags: --config-file tmp/pyproject.toml +from redis.sentinel import Sentinel + +[file pyproject.toml] +\[tool.mypy] +ignore_missing_imports = false +\[[tool.mypy.overrides]] +module = 'redis.*' +ignore_missing_imports = true + + +-- https://github.com/python/mypy/issues/10283 +[case testIgnoreMissingImportsGlobalAndWildcardWithMissingStub] +# flags: --config-file tmp/pyproject.toml +from redis.sentinel import Sentinel + +[file pyproject.toml] +\[tool.mypy] +ignore_missing_imports = true +\[[tool.mypy.overrides]] +module = 'redis.*' +ignore_missing_imports = true