Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 417bdb9

Browse files
authored
Refactor and merge requirements parsing (#11581)
1 parent e960f2f commit 417bdb9

2 files changed

Lines changed: 45 additions & 21 deletions

File tree

tests/check_consistent.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,15 @@
1717
from packaging.specifiers import SpecifierSet
1818

1919
from parse_metadata import read_metadata
20-
from utils import VERSIONS_RE, get_all_testcase_directories, get_gitignore_spec, spec_matches_path, strip_comments
20+
from utils import (
21+
REQS_FILE,
22+
VERSIONS_RE,
23+
get_all_testcase_directories,
24+
get_gitignore_spec,
25+
parse_requirements,
26+
spec_matches_path,
27+
strip_comments,
28+
)
2129

2230
extension_descriptions = {".pyi": "stub", ".py": ".py"}
2331

@@ -135,13 +143,6 @@ def check_metadata() -> None:
135143
read_metadata(distribution)
136144

137145

138-
def get_txt_requirements() -> dict[str, SpecifierSet]:
139-
with open("requirements-tests.txt", encoding="UTF-8") as requirements_file:
140-
stripped_lines = map(strip_comments, requirements_file)
141-
requirements = map(Requirement, filter(None, stripped_lines))
142-
return {requirement.name: requirement.specifier for requirement in requirements}
143-
144-
145146
class PreCommitConfigRepos(TypedDict):
146147
hooks: list[dict[str, str]]
147148
repo: str
@@ -172,30 +173,30 @@ def get_precommit_requirements() -> dict[str, SpecifierSet]:
172173

173174
def check_requirement_pins() -> None:
174175
"""Check that type checkers and linters are pinned to an exact version."""
175-
requirements = get_txt_requirements()
176+
requirements = parse_requirements()
176177
for package in linters:
177-
assert package in requirements, f"type checker/linter '{package}' not found in requirements-tests.txt"
178-
spec = requirements[package]
179-
assert len(spec) == 1, f"type checker/linter '{package}' has complex specifier in requirements-tests.txt"
180-
msg = f"type checker/linter '{package}' is not pinned to an exact version in requirements-tests.txt"
178+
assert package in requirements, f"type checker/linter '{package}' not found in {REQS_FILE}"
179+
spec = requirements[package].specifier
180+
assert len(spec) == 1, f"type checker/linter '{package}' has complex specifier in {REQS_FILE}"
181+
msg = f"type checker/linter '{package}' is not pinned to an exact version in {REQS_FILE}"
181182
assert str(spec).startswith("=="), msg
182183

183184

184185
def check_precommit_requirements() -> None:
185-
"""Check that the requirements in requirements-tests.txt and .pre-commit-config.yaml match."""
186-
requirements_txt_requirements = get_txt_requirements()
186+
"""Check that the requirements in the requirements file and .pre-commit-config.yaml match."""
187+
requirements_txt_requirements = parse_requirements()
187188
precommit_requirements = get_precommit_requirements()
188-
no_txt_entry_msg = "All pre-commit requirements must also be listed in `requirements-tests.txt` (missing {requirement!r})"
189+
no_txt_entry_msg = f"All pre-commit requirements must also be listed in `{REQS_FILE}` (missing {{requirement!r}})"
189190
for requirement, specifier in precommit_requirements.items():
190-
# annoying: the Ruff and Black repos for pre-commit are different to the names in requirements-tests.txt
191+
# annoying: the Ruff and Black repos for pre-commit are different to the names in the requirements file
191192
if requirement in {"ruff-pre-commit", "black-pre-commit-mirror"}:
192193
requirement = requirement.split("-")[0]
193194
assert requirement in requirements_txt_requirements, no_txt_entry_msg.format(requirement=requirement)
194195
specifier_mismatch = (
195196
f'Specifier "{specifier}" for {requirement!r} in `.pre-commit-config.yaml` '
196-
f'does not match specifier "{requirements_txt_requirements[requirement]}" in `requirements-tests.txt`'
197+
f'does not match specifier "{requirements_txt_requirements[requirement].specifier}" in `{REQS_FILE}`'
197198
)
198-
assert specifier == requirements_txt_requirements[requirement], specifier_mismatch
199+
assert specifier == requirements_txt_requirements[requirement].specifier, specifier_mismatch
199200

200201

201202
if __name__ == "__main__":

tests/utils.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import os
66
import re
77
import sys
8+
from collections.abc import Mapping
89
from functools import lru_cache
910
from pathlib import Path
1011
from typing import Any, Final, NamedTuple
1112

1213
import pathspec
14+
from packaging.requirements import Requirement
1315

1416
try:
1517
from termcolor import colored as colored # pyright: ignore[reportAssignmentType]
@@ -31,6 +33,11 @@ def strip_comments(text: str) -> str:
3133
return text.split("#")[0].strip()
3234

3335

36+
# ====================================================================
37+
# Printing utilities
38+
# ====================================================================
39+
40+
3441
def print_error(error: str, end: str = "\n", fix_path: tuple[str, str] = ("", "")) -> None:
3542
error_split = error.split("\n")
3643
old, new = fix_path
@@ -55,10 +62,26 @@ def venv_python(venv_dir: Path) -> Path:
5562
return venv_dir / "bin" / "python"
5663

5764

65+
# ====================================================================
66+
# Parsing the requirements file
67+
# ====================================================================
68+
69+
70+
REQS_FILE: Final = "requirements-tests.txt"
71+
72+
5873
@cache
74+
def parse_requirements() -> Mapping[str, Requirement]:
75+
"""Return a dictionary of requirements from the requirements file."""
76+
77+
with open(REQS_FILE, encoding="UTF-8") as requirements_file:
78+
stripped_lines = map(strip_comments, requirements_file)
79+
requirements = map(Requirement, filter(None, stripped_lines))
80+
return {requirement.name: requirement for requirement in requirements}
81+
82+
5983
def get_mypy_req() -> str:
60-
with open("requirements-tests.txt", encoding="UTF-8") as requirements_file:
61-
return next(strip_comments(line) for line in requirements_file if "mypy" in line)
84+
return str(parse_requirements()["mypy"])
6285

6386

6487
# ====================================================================

0 commit comments

Comments
 (0)