Skip to content

Commit f0afb04

Browse files
authored
Extract VERSIONS parsing to _utils.py (#12351)
1 parent d56c7bb commit f0afb04

File tree

3 files changed

+39
-57
lines changed

3 files changed

+39
-57
lines changed

tests/_utils.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from collections.abc import Iterable, Mapping
88
from functools import lru_cache
99
from pathlib import Path
10-
from typing import Any, Final, NamedTuple
10+
from typing import Any, Final, NamedTuple, Tuple
11+
from typing_extensions import TypeAlias
1112

1213
import pathspec
1314
from packaging.requirements import Requirement
@@ -106,8 +107,35 @@ def get_mypy_req() -> str:
106107
# Parsing the stdlib/VERSIONS file
107108
# ====================================================================
108109

110+
VersionTuple: TypeAlias = Tuple[int, int]
109111

110-
VERSIONS_RE = re.compile(r"^([a-zA-Z_][a-zA-Z0-9_.]*): ([23]\.\d{1,2})-([23]\.\d{1,2})?$")
112+
113+
VERSIONS_PATH = STDLIB_PATH / "VERSIONS"
114+
VERSION_LINE_RE = re.compile(r"^([a-zA-Z_][a-zA-Z0-9_.]*): ([23]\.\d{1,2})-([23]\.\d{1,2})?$")
115+
VERSION_RE = re.compile(r"^([23])\.(\d+)$")
116+
117+
118+
def parse_stdlib_versions_file() -> dict[str, tuple[VersionTuple, VersionTuple]]:
119+
result: dict[str, tuple[VersionTuple, VersionTuple]] = {}
120+
with VERSIONS_PATH.open(encoding="UTF-8") as f:
121+
for line in f:
122+
line = strip_comments(line)
123+
if line == "":
124+
continue
125+
m = VERSION_LINE_RE.match(line)
126+
assert m, f"invalid VERSIONS line: {line}"
127+
mod: str = m.group(1)
128+
assert mod not in result, f"Duplicate module {mod} in VERSIONS"
129+
min_version = _parse_version(m.group(2))
130+
max_version = _parse_version(m.group(3)) if m.group(3) else (99, 99)
131+
result[mod] = min_version, max_version
132+
return result
133+
134+
135+
def _parse_version(v_str: str) -> tuple[int, int]:
136+
m = VERSION_RE.match(v_str)
137+
assert m, f"invalid version: {v_str}"
138+
return int(m.group(1)), int(m.group(2))
111139

112140

113141
# ====================================================================

tests/check_typeshed_structure.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
STDLIB_PATH,
1919
TEST_CASES_DIR,
2020
TESTS_DIR,
21-
VERSIONS_RE,
2221
get_all_testcase_directories,
2322
get_gitignore_spec,
2423
parse_requirements,
24+
parse_stdlib_versions_file,
2525
spec_matches_path,
26-
strip_comments,
2726
tests_path,
2827
)
2928

@@ -127,30 +126,17 @@ def check_no_symlinks() -> None:
127126

128127
def check_versions_file() -> None:
129128
"""Check that the stdlib/VERSIONS file has the correct format."""
130-
versions = list[str]()
131-
with open("stdlib/VERSIONS", encoding="UTF-8") as f:
132-
data = f.read().splitlines()
133-
for line in data:
134-
line = strip_comments(line)
135-
if line == "":
136-
continue
137-
m = VERSIONS_RE.match(line)
138-
if not m:
139-
raise AssertionError(f"Bad line in VERSIONS: {line}")
140-
module = m.group(1)
141-
assert module not in versions, f"Duplicate module {module} in VERSIONS"
142-
versions.append(module)
143-
144-
deduped_versions = set(versions)
145-
assert len(versions) == len(deduped_versions)
129+
version_map = parse_stdlib_versions_file()
130+
versions = list(version_map.keys())
131+
146132
sorted_versions = sorted(versions)
147133
assert versions == sorted_versions, f"{versions=}\n\n{sorted_versions=}"
148134

149135
modules = _find_stdlib_modules()
150136
# Sub-modules don't need to be listed in VERSIONS.
151-
extra = {m.split(".")[0] for m in modules} - deduped_versions
137+
extra = {m.split(".")[0] for m in modules} - version_map.keys()
152138
assert not extra, f"Modules not in versions: {extra}"
153-
extra = deduped_versions - modules
139+
extra = version_map.keys() - modules
154140
assert not extra, f"Versions not in modules: {extra}"
155141

156142

tests/mypy_test.py

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import argparse
77
import concurrent.futures
88
import os
9-
import re
109
import subprocess
1110
import sys
1211
import tempfile
@@ -17,11 +16,7 @@
1716
from itertools import product
1817
from pathlib import Path
1918
from threading import Lock
20-
from typing import TYPE_CHECKING, Any, NamedTuple, Tuple
21-
22-
if TYPE_CHECKING:
23-
from _typeshed import StrPath
24-
19+
from typing import Any, NamedTuple
2520
from typing_extensions import Annotated, TypeAlias
2621

2722
import tomli
@@ -30,14 +25,13 @@
3025
from _utils import (
3126
PYTHON_VERSION,
3227
TESTS_DIR,
33-
VERSIONS_RE as VERSION_LINE_RE,
3428
colored,
3529
get_gitignore_spec,
3630
get_mypy_req,
31+
parse_stdlib_versions_file,
3732
print_error,
3833
print_success_msg,
3934
spec_matches_path,
40-
strip_comments,
4135
venv_python,
4236
)
4337

@@ -53,7 +47,6 @@
5347
DIRECTORIES_TO_TEST = [Path("stdlib"), Path("stubs")]
5448

5549
VersionString: TypeAlias = Annotated[str, "Must be one of the entries in SUPPORTED_VERSIONS"]
56-
VersionTuple: TypeAlias = Tuple[int, int]
5750
Platform: TypeAlias = Annotated[str, "Must be one of the entries in SUPPORTED_PLATFORMS"]
5851

5952

@@ -150,31 +143,6 @@ def match(path: Path, args: TestConfig) -> bool:
150143
return False
151144

152145

153-
def parse_versions(fname: StrPath) -> dict[str, tuple[VersionTuple, VersionTuple]]:
154-
result: dict[str, tuple[VersionTuple, VersionTuple]] = {}
155-
with open(fname, encoding="UTF-8") as f:
156-
for line in f:
157-
line = strip_comments(line)
158-
if line == "":
159-
continue
160-
m = VERSION_LINE_RE.match(line)
161-
assert m, f"invalid VERSIONS line: {line}"
162-
mod: str = m.group(1)
163-
min_version = parse_version(m.group(2))
164-
max_version = parse_version(m.group(3)) if m.group(3) else (99, 99)
165-
result[mod] = min_version, max_version
166-
return result
167-
168-
169-
_VERSION_RE = re.compile(r"^([23])\.(\d+)$")
170-
171-
172-
def parse_version(v_str: str) -> tuple[int, int]:
173-
m = _VERSION_RE.match(v_str)
174-
assert m, f"invalid version: {v_str}"
175-
return int(m.group(1)), int(m.group(2))
176-
177-
178146
def add_files(files: list[Path], module: Path, args: TestConfig) -> None:
179147
"""Add all files in package or module represented by 'name' located in 'root'."""
180148
if module.is_file() and module.suffix == ".pyi":
@@ -365,7 +333,7 @@ def test_third_party_distribution(
365333
def test_stdlib(args: TestConfig) -> TestResult:
366334
files: list[Path] = []
367335
stdlib = Path("stdlib")
368-
supported_versions = parse_versions(stdlib / "VERSIONS")
336+
supported_versions = parse_stdlib_versions_file()
369337
for name in os.listdir(stdlib):
370338
if name in ("VERSIONS", TESTS_DIR) or name.startswith("."):
371339
continue

0 commit comments

Comments
 (0)