Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves #10283; check for module level ignore_missing_imports on missing stubs #10546

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 13 additions & 3 deletions mypy/build.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems potentially dangerous, since Options can have significant state (_per_module_cache) and it's hard to reason about the performance and correctness implications of the cache. I came up with a simple alternative approach that doesn't use deepcopy, and since there is not much time before the release, I'll create a PR now (but I'll give you credit for the first implementation).

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
Expand Down
2 changes: 1 addition & 1 deletion mypy/options.py
Expand Up @@ -141,7 +141,7 @@ def __init__(self) -> None:
# Warn about unused '# type: ignore' comments
self.warn_unused_ignores = False

# Warn about unused '[mypy-<pattern>]' or '[[tool.mypy.overrides]]' config sections
# Warn about unused '[mypy-<pattern>]' or '[[tool.mypy.overrides]]' config sections
self.warn_unused_configs = False

# Files in which to ignore all non-fatal errors
Expand Down
41 changes: 41 additions & 0 deletions 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
Expand Down Expand Up @@ -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