# Ruff configuration for this repo's Python surface (all of it lives under `scripts/`). # # WHY THIS FILE EXISTS (ersatztv#780). Without a committed config, ruff falls back to whatever # `~/.config/ruff/ruff.toml` the operator's machine happens to have — so a second machine lints this # repo differently, or not at all. That is the environment-divergence class #643/#647/#648 (a shell # gate whose behaviour was a function of an untested interpreter version) and #512 (a test that # passed on a fast laptop and flaked on a starved CI VM). The settings below are pinned HERE so the # lint verdict is a property of the repo, not of the machine. # # It is enforced by the `script-tests` job (`Script lint and tests (ruff + pytest)`) in # .gitea/workflows/pr-checks.yml. A config nobody runs is the same divergence one step later. # # That job does NOT invoke `ruff check .`: it passes an explicit population from `git ls-files` with # `--no-force-exclude`. An `exclude` added to this file silently empties a discovery-based run into a # GREEN one — a top-level `exclude` empties both commands, one under `[lint]` empties `check`, one # under `[format]` (where an appended line lands, by TOML rules) empties `format --check`. Adding # `exclude` here will therefore not do what you expect, which is the point. The measured matrix is in # `ci.python-lint-ruff-config-committed`. # # `pyright` is deliberately NOT gated: its only findings here are `reportMissingImports` for # `etv_client` in scripts/scripted-schedules/entrypoint.py, which resolves only inside that script's # deploy environment, and gating it would put a node toolchain on the git-only `small` lane for zero # real findings. Revisit if this repo grows a typed Python surface. target-version = "py311" line-length = 120 [lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "UP", # pyupgrade "SIM", # flake8-simplify "S", # flake8-bandit (security) # RUF100 is load-bearing, not tidiness: every `# noqa` below is an assertion that a real finding # is being suppressed for a stated reason, and without this a suppression that suppresses nothing # stays in the file reading as one. #780 did exactly that mid-branch — a `# noqa: UP031` on a site # the same branch had already fixed in code — and found two more already in the tree: one whose # rule had stopped firing, one for a rule this config never enables. "RUF100", ] ignore = [ "S603", # subprocess call - check for execution of untrusted input (too noisy for scripts) "S607", # starting a process with a partial executable path ] [lint.per-file-ignores] # scripts/tests asserts, so S101 would fire on every test. S105 is deliberately NOT exempted here: # the eight sites that trip it (`env["ETV_GITEA_TOKEN"] = "stub"`) carry a per-site `# noqa: S105` # instead, so a real credential pasted into a fixture next year still reddens the gate. A directory # blanket would have given up hardcoded-credential coverage over the largest Python surface in the # repo, permanently, to suppress eight known lines. "scripts/tests/**" = ["S101"] [format] quote-style = "double"