/
niceSOFT
/
python3-hatchling
Обзор
Документация
Войти
/
niceSOFT
/
python3-hatchling
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
scripts/update_ruff.py
172 строки
6 KB
Dimitri Papadopoulos Orfanos
Upgrade Ruff to 0.13.2 (#1890)
28 сен 2025, 21:20
Не верифицирован
28 сен 2025, 21:20
aff6f39
Код
Авторство
О чём код?
from __future__ import annotations import json import re import subprocess import sys import typing from importlib.metadata import version from utils import ROOT if typing.TYPE_CHECKING: from pathlib import Path # fmt: off UNSELECTED_RULE_PATTERNS: list[str] = [ # Allow non-abstract empty methods in abstract base classes 'B027', # Allow boolean positional values in function calls, like `dict.get(... True)` 'FBT003', # Ignore complexity 'C901', 'PLR0904', 'PLR0911', 'PLR0912', 'PLR0913', 'PLR0914', 'PLR0915', 'PLR0916', 'PLR0917', 'PLR1702', # These are dependent on projects themselves 'AIR\\d+', 'CPY\\d+', 'D\\d+', 'DJ\\d+', 'NPY\\d+', 'PD\\d+', # Many projects either don't have type annotations or it would take much effort to satisfy this 'ANN\\d+', # Don't be too strict about TODOs as not everyone uses them the same way 'FIX\\d+', 'TD001', 'TD002', 'TD003', # There are valid reasons to not use pathlib such as performance and import cost 'PTH\\d+', 'FURB101', 'FURB103', # Conflicts with type checking 'RET501', 'RET502', # Under review https://github.com/astral-sh/ruff/issues/8796 'PT004', 'PT005', # Buggy https://github.com/astral-sh/ruff/issues/4845 'ERA001', # Business logic relying on other programs has no choice but to use subprocess 'S404', # Too prone to false positives and might be removed https://github.com/astral-sh/ruff/issues/4045 'S603', # Too prone to false positives https://github.com/astral-sh/ruff/issues/8761 'SIM401', # Allow for easy ignores 'PGH003', 'PGH004', # This is required sometimes, and doesn't matter on Python 3.11+ 'PERF203', # Potentially unnecessary on Python 3.12+ 'FURB140', # Conflicts with formatter, see: # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules 'COM812', 'COM819', 'D206', 'D300', 'E111', 'E114', 'E117', 'E301', 'E302', 'E303', 'E304', 'E305', 'E306', "E501", 'ISC001', 'ISC002', 'Q000', 'Q001', 'Q002', 'Q003', 'Q004', 'W191', # Conflicts with context formatting in dependencies 'RUF200', # Currently broken ] PER_FILE_IGNORED_RULES: dict[str, list[str]] = { '**/scripts/*': [ # Implicit namespace packages 'INP001', # Print statements 'T201', ], '**/tests/**/*': [ # Empty string comparisons 'PLC1901', # Magic values 'PLR2004', # Methods that don't use `self` 'PLR6301', # Potential security issues like assert statements and hardcoded passwords 'S', # Relative imports 'TID252', ], } # fmt: on def get_lines_until(file_path: Path, marker: str) -> list[str]: lines = file_path.read_text(encoding="utf-8").splitlines() for i, line in enumerate(lines): if line.startswith(marker): block_start = i break else: message = f"Could not find {marker}: {file_path.relative_to(ROOT)}" raise ValueError(message) del lines[block_start:] return lines def main(): process = subprocess.run( # noqa: PLW1510 [sys.executable, "-m", "ruff", "rule", "--all", "--output-format", "json"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8", cwd=str(ROOT), ) if process.returncode: raise OSError(process.stdout) data_file = ROOT / "src" / "hatch" / "cli" / "fmt" / "core.py" lines = get_lines_until(data_file, "STABLE_RULES") ignored_pattern = re.compile(f"^({'|'.join(UNSELECTED_RULE_PATTERNS)})$") # https://github.com/astral-sh/ruff/issues/9891#issuecomment-1951403651 removed_pattern = re.compile(r"^\s*#+\s+(removed|removal)", flags=re.IGNORECASE | re.MULTILINE) stable_rules: set[str] = set() preview_rules: set[str] = set() unselected_rules: set[str] = set() for rule in json.loads(process.stdout): code = rule["code"] if ignored_pattern.match(code) or removed_pattern.search(rule["explanation"]): unselected_rules.add(code) continue if rule["preview"]: preview_rules.add(code) else: stable_rules.add(code) lines.append("STABLE_RULES: tuple[str, ...] = (") lines.extend(f" {rule!r}," for rule in sorted(stable_rules)) lines.append(")") lines.append("PREVIEW_RULES: tuple[str, ...] = (") lines.extend(f" {rule!r}," for rule in sorted(preview_rules)) lines.append(")") lines.append("PER_FILE_IGNORED_RULES: dict[str, list[str]] = {") for ignored_glob, ignored_rules in sorted(PER_FILE_IGNORED_RULES.items()): lines.append(f" {ignored_glob!r}: [") lines.extend(f" {rule!r}," for rule in sorted(ignored_rules)) lines.append(" ],") lines.append("}") lines.append("") data_file.write_text("\n".join(lines), encoding="utf-8") version_file = ROOT / "src" / "hatch" / "env" / "internal" / "static_analysis.py" latest_version = version("ruff") version_file.write_text( re.sub( r"^(RUFF_DEFAULT_VERSION.+=.+\').+?(\')$", rf"\g<1>{latest_version}\g<2>", version_file.read_text(encoding="utf-8"), count=1, flags=re.MULTILINE, ), encoding="utf-8", ) data_file = ROOT / "docs" / ".hooks" / "render_ruff_defaults.py" lines = get_lines_until(data_file, "UNSELECTED_RULES") lines.append("UNSELECTED_RULES: tuple[str, ...] = (") lines.extend(f" {rule!r}," for rule in sorted(unselected_rules)) lines.append(")") lines.append("") data_file.write_text("\n".join(lines), encoding="utf-8") print(f"Stable rules: {len(stable_rules)}") print(f"Preview rules: {len(preview_rules)}") print(f"Unselected rules: {len(unselected_rules)}") if __name__ == "__main__": main()