Skip to content

Support max version marker of stdlib typeshed modules #10402

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

Merged
merged 2 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions mypy/modulefinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,21 @@ def find_module(self, id: str, *, fast_path: bool = False) -> ModuleSearchResult
top_level = id.partition('.')[0]
use_typeshed = True
if top_level in self.stdlib_py_versions:
min_version = self.stdlib_py_versions[top_level]
use_typeshed = (self.options is None
or typeshed_py_version(self.options) >= min_version)
use_typeshed = self._typeshed_has_version(top_level)
self.results[id] = self._find_module(id, use_typeshed)
if (not fast_path
and self.results[id] is ModuleNotFoundReason.NOT_FOUND
and self._can_find_module_in_parent_dir(id)):
self.results[id] = ModuleNotFoundReason.WRONG_WORKING_DIRECTORY
return self.results[id]

def _typeshed_has_version(self, module: str) -> bool:
if not self.options:
return True
version = typeshed_py_version(self.options)
min_version, max_version = self.stdlib_py_versions[module]
return version >= min_version and (max_version is None or version <= max_version)

def _find_module_non_stub_helper(self, components: List[str],
pkg_dir: str) -> Union[OnePackageDir, ModuleNotFoundReason]:
plausible_match = False
Expand Down Expand Up @@ -735,10 +740,14 @@ def compute_search_paths(sources: List[BuildSource],
typeshed_path=tuple(lib_path))


def load_stdlib_py_versions(custom_typeshed_dir: Optional[str]) -> Dict[str, Tuple[int, int]]:
"""Return dict with minimum Python versions of stdlib modules.
def load_stdlib_py_versions(custom_typeshed_dir: Optional[str]
) -> Dict[str, Tuple[Tuple[int, int], Optional[Tuple[int, int]]]]:
"""Return dict with minimum and maximum Python versions of stdlib modules.

The contents look like
{..., 'secrets': ((3, 6), None), 'symbol': (2, 7), (3, 9)), ...}

The contents look like {..., 'secrets': 3.6, 're': 2.7, ...}.
None means there is no maximum version.
"""
typeshed_dir = custom_typeshed_dir or os.path.join(os.path.dirname(__file__), "typeshed")
stdlib_dir = os.path.join(typeshed_dir, "stdlib")
Expand All @@ -751,20 +760,29 @@ def load_stdlib_py_versions(custom_typeshed_dir: Optional[str]) -> Dict[str, Tup
line = line.strip()
if line.startswith("#") or line == "":
continue
module, version = line.split(":")
major, minor = version.strip().split(".")
result[module] = int(major), int(minor)
module, version_range = line.split(":")
versions = version_range.split("-")
min_version = parse_version(versions[0])
max_version = (parse_version(versions[1])
if len(versions) >= 2 and versions[1].strip() else None)
result[module] = min_version, max_version

# Modules that are Python 2 only or have separate Python 2 stubs
# have stubs in @python2/ and may need an override.
python2_dir = os.path.join(stdlib_dir, PYTHON2_STUB_DIR)
for fnam in os.listdir(python2_dir):
fnam = fnam.replace(".pyi", "")
result[fnam] = (2, 7)
max_version = result.get(fnam, ((2, 7), None))[1]
result[fnam] = (2, 7), max_version

return result


def parse_version(version: str) -> Tuple[int, int]:
major, minor = version.strip().split(".")
return int(major), int(minor)


def typeshed_py_version(options: Options) -> Tuple[int, int]:
"""Return Python version used for checking whether module supports typeshed."""
# Typeshed no longer covers Python 3.x versions before 3.6, so 3.6 is
Expand Down
5 changes: 3 additions & 2 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,8 +1074,9 @@ def get_typeshed_stdlib_modules(custom_typeshed_dir: Optional[str]) -> List[str]
version_info = (3, 6)
else:
version_info = sys.version_info[0:2]
for module, minver in stdlib_py_versions.items():
if version_info >= minver:
for module, versions in stdlib_py_versions.items():
minver, maxver = versions
if version_info >= minver and (maxver is None or version_info <= maxver):
packages.add(module)

if custom_typeshed_dir:
Expand Down