# Tooling configuration. # # Deliberately limited to tool settings: the project is run from wsgi.py, # not installed as a distribution, so there is no [project] table. # # QUA-001 asked for requirements.txt / requirements-dev.txt to be folded # into dependency groups here. Not done, on purpose. Deployment is an # lftp file mirror with no build step: the server runs whatever # `pip install -r requirements.txt` gives it, and PEP 735 groups need # pip >= 25.1 on a machine whose pip version cannot be checked from here. # Trading a working install path for a tidier declaration is not a trade # worth making blind. The parts of QUA-001 that were real defects — the # psycopg dialect and the parasitic packages — are fixed; revisit the # consolidation when the deployment gains a build step (OPS-011). [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["."] addopts = "-q --strict-markers --strict-config" filterwarnings = [ "default", # discord.py imports audioop, removed from the stdlib in 3.13. "ignore:'audioop' is deprecated:DeprecationWarning", ] [tool.coverage.report] # The exhaustive audit established a 71% baseline. Keep one point of margin # for platform-specific branches while making any material regression fail CI. fail_under = 70 show_missing = true [tool.ruff] line-length = 100 target-version = "py312" exclude = [".venv", "venv", "migrations", "docs"] [tool.ruff.lint] # Widened once the repository had been formatted, so that this enforcement # is about defects rather than churn (QUA-002). The whole set produced 24 # findings across 76 files — the code was cleaner than the audit feared. # # E4/E7/E9, F pyflakes and the pycodestyle subset ruff enables by default # B bugbear; B904 alone is worth it (lost exception causes) # C4 comprehension shortcuts # RET return-flow tidiness # SIM obvious simplifications # UP syntax available on the 3.12 this targets # I isort; enabled in its own commit, for the same reason the # formatting got one — the diff is churn and must not hide # behind a behavioural change # BLE blind `except Exception`. Added with QUA-004/ARCH-008, and # the point of it is what happens next: the rule cannot be # satisfied by narrowing every catch, because a handful of # boundaries genuinely need the breadth. It can only be # satisfied by writing down which ones and why, in a # `# noqa: BLE001 — reason` on the line. That turns a count # that drifts back up into a decision someone has to defend. select = ["E4", "E7", "E9", "F", "B", "C4", "RET", "SIM", "UP", "I", "BLE"] # Forcing a ternary reads worse than the if/else it replaces in the one place # it fires (evaluations.py, choosing a sort direction). ignore = ["SIM108"] [tool.ruff.lint.per-file-ignores] # Intentional re-export facade: `from app.models import User, Tryout, ...` # is the documented entry point, and importing the modules is what # registers every model with SQLAlchemy. # # I001 is off here too. The imports are grouped into eleven commented # layers that spell out the dependency graph (constants → users → teams → # tryouts → matches → participants). Alphabetising them leaves every # heading above an import it does not describe, and the file's one job is # to be read. The order is documentation, not a requirement: the suite # passes either way. "app/models/__init__.py" = ["F401", "I001"] "app/models/user_model/__init__.py" = ["F401"] "tests/conftest.py" = ["E402"] [tool.ruff.format] quote-style = "preserve"