Files
Guillaume Meyer (The Opinionated Man)andGitHub 723627716c chore: add Ruff linting and formatting with CI enforcement (#103)
Introduce Ruff (pinned at 0.16.3) as the project linter + formatter and
enforce it in CI:

- requirements-dev.txt: pin ruff==0.16.3 (exact pins, no drift)
- ruff.toml: line-length 100, target py312; rule set E/F/W/I/UP/B/SIM/RUF/PLW/S
  with deliberate ignores (E501 for content strings, S603 for safe_arg
  subprocess calls, S101 asserts in tests) and per-file test ignores
- Makefile: add lint / format / lint-fix targets
- .github/workflows/ci.yml: add lint job (ruff check + format --check)
- .gitignore: whitelist ruff.toml

Also fix every finding the new gate surfaced so CI is green:
- 109+ auto-fixes from ruff --fix (import sorting, simplifications,
  unused vars, re.I aliases, etc.)
- explicit check=False on all subprocess.run calls (PLW1510)
- harden sitemap XML parsing: reject DTD/entity declarations (S314)
- replace hardcoded /tmp paths in tests with tmp_path (S108)
- narrow/annotate intentional bare excepts (S110/S112), bind loop vars
  in closures (B023), raise ... from None (B904), strict= for zip (B905)
- ruff format applied across service/ and tests/

Verified: ruff check + ruff format --check pass; 287 tests pass, 1 skip.
2026-08-16 17:32:40 -07:00

32 lines
1.2 KiB
TOML

# Ruff configuration — lint + format.
# Version pinned in requirements-dev.txt (exact pins, no drift).
line-length = 100
target-version = "py312"
[lint]
# E/F/W: pycodestyle + pyflakes core; I: import sorting; UP: pyupgrade;
# B: bugbear; SIM: simplify; RUF: ruff-specific; PLW: pylint warnings;
# S: bandit security checks.
select = ["E", "F", "W", "I", "UP", "B", "SIM", "RUF", "PLW", "S"]
ignore = [
"S101", # asserts are idiomatic in this test suite
# E501 would flag long content strings (XML fixtures, help text) that the
# formatter already keeps readable; ruff format enforces line length for code.
"E501",
# S603 fires on any subprocess call whose args aren't all literals, but this
# codebase already guards args with safe_arg() and never uses shell=True.
"S603",
]
[lint.per-file-ignores]
# Tests import scripts via sys.path manipulation; the delayed imports are
# intentional, so don't demand E402 there (ruff already tolerates them, but
# be explicit).
"tests/**" = [
"E402",
# RUF001/RUF003: tests intentionally embed confusables / ambiguous Unicode
# (NBSP, fullwidth, Cyrillic lookalikes) to exercise the scrubbing logic.
"RUF001",
"RUF003",
]