Skip to content

Commit c7d2fa1

Browse files
authored
Fix over eager types-google-cloud-ndb suggestion (#15347)
Fixes #15343
1 parent d0d63b4 commit c7d2fa1

File tree

5 files changed

+33
-47
lines changed

5 files changed

+33
-47
lines changed

mypy/build.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
DecodeError,
5656
decode_python_encoding,
5757
get_mypy_comments,
58-
get_top_two_prefixes,
5958
hash_digest,
6059
is_stub_package_file,
6160
is_sub_path,
@@ -91,12 +90,7 @@
9190
from mypy.plugins.default import DefaultPlugin
9291
from mypy.renaming import LimitedVariableRenameVisitor, VariableRenameVisitor
9392
from mypy.stats import dump_type_stats
94-
from mypy.stubinfo import (
95-
is_legacy_bundled_package,
96-
legacy_bundled_packages,
97-
non_bundled_packages,
98-
stub_package_name,
99-
)
93+
from mypy.stubinfo import legacy_bundled_packages, non_bundled_packages, stub_distribution_name
10094
from mypy.types import Type
10195
from mypy.typestate import reset_global_state, type_state
10296
from mypy.version import __version__
@@ -2665,14 +2659,18 @@ def find_module_and_diagnose(
26652659
# search path or the module has not been installed.
26662660

26672661
ignore_missing_imports = options.ignore_missing_imports
2668-
top_level, second_level = get_top_two_prefixes(id)
2662+
2663+
id_components = id.split(".")
26692664
# Don't honor a global (not per-module) ignore_missing_imports
26702665
# setting for modules that used to have bundled stubs, as
26712666
# otherwise updating mypy can silently result in new false
26722667
# negatives. (Unless there are stubs but they are incomplete.)
26732668
global_ignore_missing_imports = manager.options.ignore_missing_imports
26742669
if (
2675-
(is_legacy_bundled_package(top_level) or is_legacy_bundled_package(second_level))
2670+
any(
2671+
".".join(id_components[:i]) in legacy_bundled_packages
2672+
for i in range(len(id_components), 0, -1)
2673+
)
26762674
and global_ignore_missing_imports
26772675
and not options.ignore_missing_imports_per_module
26782676
and result is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED
@@ -2790,15 +2788,19 @@ def module_not_found(
27902788
else:
27912789
code = codes.IMPORT
27922790
errors.report(line, 0, msg.format(module=target), code=code)
2793-
top_level, second_level = get_top_two_prefixes(target)
2794-
if second_level in legacy_bundled_packages or second_level in non_bundled_packages:
2795-
top_level = second_level
2791+
2792+
components = target.split(".")
2793+
for i in range(len(components), 0, -1):
2794+
module = ".".join(components[:i])
2795+
if module in legacy_bundled_packages or module in non_bundled_packages:
2796+
break
2797+
27962798
for note in notes:
27972799
if "{stub_dist}" in note:
2798-
note = note.format(stub_dist=stub_package_name(top_level))
2800+
note = note.format(stub_dist=stub_distribution_name(module))
27992801
errors.report(line, 0, note, severity="note", only_once=True, code=codes.IMPORT)
28002802
if reason is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED:
2801-
manager.missing_stub_packages.add(stub_package_name(top_level))
2803+
manager.missing_stub_packages.add(stub_distribution_name(module))
28022804
errors.set_import_context(save_import_context)
28032805

28042806

mypy/modulefinder.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,9 @@ def _find_module_non_stub_helper(
337337
# If this is not a directory then we can't traverse further into it
338338
if not self.fscache.isdir(dir_path):
339339
break
340-
if approved_stub_package_exists(components[0]):
341-
if len(components) == 1 or (
342-
self.find_module(components[0])
343-
is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED
344-
):
340+
for i in range(len(components), 0, -1):
341+
if approved_stub_package_exists(".".join(components[:i])):
345342
return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED
346-
if approved_stub_package_exists(".".join(components[:2])):
347-
return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED
348343
if plausible_match:
349344
return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS
350345
else:

mypy/stubinfo.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ def approved_stub_package_exists(prefix: str) -> bool:
99
return is_legacy_bundled_package(prefix) or prefix in non_bundled_packages
1010

1111

12-
def stub_package_name(prefix: str) -> str:
12+
def stub_distribution_name(prefix: str) -> str:
1313
return legacy_bundled_packages.get(prefix) or non_bundled_packages[prefix]
1414

1515

1616
# Stubs for these third-party packages used to be shipped with mypy.
1717
#
1818
# Map package name to PyPI stub distribution name.
19-
#
20-
# Package name can have one or two components ('a' or 'a.b').
2119
legacy_bundled_packages = {
2220
"aiofiles": "types-aiofiles",
2321
"bleach": "types-bleach",
@@ -116,7 +114,7 @@ def stub_package_name(prefix: str) -> str:
116114
"flask_sqlalchemy": "types-Flask-SQLAlchemy",
117115
"fpdf": "types-fpdf2",
118116
"gdb": "types-gdb",
119-
"google.cloud": "types-google-cloud-ndb",
117+
"google.cloud.ndb": "types-google-cloud-ndb",
120118
"hdbcli": "types-hdbcli",
121119
"html5lib": "types-html5lib",
122120
"httplib2": "types-httplib2",

mypy/util.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -308,17 +308,6 @@ def get_prefix(fullname: str) -> str:
308308
return fullname.rsplit(".", 1)[0]
309309

310310

311-
def get_top_two_prefixes(fullname: str) -> tuple[str, str]:
312-
"""Return one and two component prefixes of a fully qualified name.
313-
314-
Given 'a.b.c.d', return ('a', 'a.b').
315-
316-
If fullname has only one component, return (fullname, fullname).
317-
"""
318-
components = fullname.split(".", 3)
319-
return components[0], ".".join(components[:2])
320-
321-
322311
def correct_relative_import(
323312
cur_mod_id: str, relative: int, target: str, is_cur_package_init_file: bool
324313
) -> tuple[str, bool]:

test-data/unit/check-modules.test

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3121,26 +3121,28 @@ import google.cloud
31213121
from google.cloud import x
31223122

31233123
[case testErrorFromGoogleCloud]
3124-
import google.cloud
3124+
import google.cloud # E: Cannot find implementation or library stub for module named "google.cloud" \
3125+
# E: Cannot find implementation or library stub for module named "google"
31253126
from google.cloud import x
3126-
import google.non_existent
3127+
import google.non_existent # E: Cannot find implementation or library stub for module named "google.non_existent"
31273128
from google.non_existent import x
3128-
[out]
3129-
main:1: error: Library stubs not installed for "google.cloud"
3130-
main:1: note: Hint: "python3 -m pip install types-google-cloud-ndb"
3131-
main:1: note: (or run "mypy --install-types" to install all missing stub packages)
3132-
main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
3133-
main:1: error: Cannot find implementation or library stub for module named "google"
3134-
main:3: error: Cannot find implementation or library stub for module named "google.non_existent"
3129+
3130+
import google.cloud.ndb # E: Library stubs not installed for "google.cloud.ndb" \
3131+
# N: Hint: "python3 -m pip install types-google-cloud-ndb" \
3132+
# N: (or run "mypy --install-types" to install all missing stub packages) \
3133+
# N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
3134+
from google.cloud import ndb
31353135

31363136
[case testMissingSubmoduleOfInstalledStubPackage]
31373137
import bleach.xyz
31383138
from bleach.abc import fgh
31393139
[file bleach/__init__.pyi]
31403140
[out]
3141-
main:1: error: Cannot find implementation or library stub for module named "bleach.xyz"
3141+
main:1: error: Library stubs not installed for "bleach.xyz"
3142+
main:1: note: Hint: "python3 -m pip install types-bleach"
3143+
main:1: note: (or run "mypy --install-types" to install all missing stub packages)
31423144
main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
3143-
main:2: error: Cannot find implementation or library stub for module named "bleach.abc"
3145+
main:2: error: Library stubs not installed for "bleach.abc"
31443146

31453147
[case testMissingSubmoduleOfInstalledStubPackageIgnored]
31463148
# flags: --ignore-missing-imports

0 commit comments

Comments
 (0)