Skip to content

Commit be5aed7

Browse files
committed
Make ignore_missing_imports work for libs which had bundled stubs (#10582)
It has to be specified as a per-module option, if the library used to have bundled stubs. This way mypy won't silently start ignoring these missing stubs. This makes ignore_missing_imports special by making it work a bit differently, depending on whether it's set globally or per module. The new behavior is less surprising. This makes it possible to ignore arbitrary missing third-party stub packages, even those which used to have bundled stubs. Fixes #10283. Originally implemented by @TheCleric in #10283. This is somewhat simpler alternative implementation which is easier to reason about and may perform better in some cases of very large configs.
1 parent e056774 commit be5aed7

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

mypy/build.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2449,7 +2449,9 @@ def find_module_and_diagnose(manager: BuildManager,
24492449
# otherwise updating mypy can silently result in new false
24502450
# negatives.
24512451
global_ignore_missing_imports = manager.options.ignore_missing_imports
2452-
if top_level in legacy_bundled_packages and global_ignore_missing_imports:
2452+
if (top_level in legacy_bundled_packages
2453+
and global_ignore_missing_imports
2454+
and not options.ignore_missing_imports_per_module):
24532455
ignore_missing_imports = False
24542456

24552457
if skip_diagnose:

mypy/options.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def __init__(self) -> None:
8282
self.no_silence_site_packages = False
8383
self.no_site_packages = False
8484
self.ignore_missing_imports = False
85+
# Is ignore_missing_imports set in a per-module section
86+
self.ignore_missing_imports_per_module = False
8587
self.follow_imports = 'normal' # normal|silent|skip|error
8688
# Whether to respect the follow_imports setting even for stub files.
8789
# Intended to be used for disabling specific stubs.
@@ -325,6 +327,10 @@ def apply_changes(self, changes: Dict[str, object]) -> 'Options':
325327
replace_object_state(new_options, self, copy_dict=True)
326328
for key, value in changes.items():
327329
setattr(new_options, key, value)
330+
if changes.get("ignore_missing_imports"):
331+
# This is the only option for which a per-module and a global
332+
# option sometimes beheave differently.
333+
new_options.ignore_missing_imports_per_module = True
328334
return new_options
329335

330336
def build_per_module_cache(self) -> None:

test-data/unit/check-modules.test

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3011,7 +3011,6 @@ certifi.x # E: Expression has type "Any"
30113011
certifi.x # E: Expression has type "Any"
30123012
1() # E: "int" not callable
30133013

3014-
30153014
[case testDoNotLimitImportErrorVolume]
30163015
# flags: --disallow-any-expr --soft-error-limit=3
30173016
import xyz1 # E: Cannot find implementation or library stub for module named "xyz1" \
@@ -3064,3 +3063,34 @@ certifi.x # E: Expression has type "Any"
30643063
certifi.x # E: Expression has type "Any"
30653064
certifi.x # E: Expression has type "Any"
30663065
certifi.x # E: Expression has type "Any"
3066+
3067+
[case testIgnoreErrorFromMissingStubs1]
3068+
# flags: --config-file tmp/pyproject.toml
3069+
import certifi
3070+
from foobar1 import x
3071+
import foobar2
3072+
[file pyproject.toml]
3073+
\[tool.mypy]
3074+
ignore_missing_imports = true
3075+
\[[tool.mypy.overrides]]
3076+
module = "certifi"
3077+
ignore_missing_imports = true
3078+
\[[tool.mypy.overrides]]
3079+
module = "foobar1"
3080+
ignore_missing_imports = true
3081+
3082+
[case testIgnoreErrorFromMissingStubs2]
3083+
# flags: --config-file tmp/pyproject.toml
3084+
import certifi
3085+
from foobar1 import x
3086+
import foobar2 # E: Cannot find implementation or library stub for module named "foobar2" \
3087+
# N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
3088+
[file pyproject.toml]
3089+
\[tool.mypy]
3090+
ignore_missing_imports = false
3091+
\[[tool.mypy.overrides]]
3092+
module = "certifi"
3093+
ignore_missing_imports = true
3094+
\[[tool.mypy.overrides]]
3095+
module = "foobar1"
3096+
ignore_missing_imports = true

0 commit comments

Comments
 (0)