Files
team-tryouts/pyproject.toml
T
GGThedandClaude Opus 5 66f2838402 chore(lint): interdire d avaler une exception sans laisser de trace
Regle BLE de ruff activee. Ce qu'elle enforce n'est pas "ne jamais attraper
large" : elle se satisfait d'un logger.exception. C'est exactement la
discipline visee — une frontiere peut tout avaler, a condition de laisser de
quoi distinguer un defaut d'une panne. Les cinq noqa que j'avais prepares
d'avance etaient donc inertes ; la raison reste en commentaire simple.

Ce que la regle a trouve, une fois activee :

app.py, demarrage du bot — les deux facons d'echouer, jeton invalide et
import casse, se lisaient a l'identique sur une seule ligne et aucune
n'etait diagnosticable. Passe en error avec exc_info : un club qui ne
recoit plus aucun rappel a perdu une fonctionnalite, et warning mettait ca
a cote des avis de depreciation.

services/notifications.py — le bloc webhook attrapait large autour d'un
requests.post. RequestException couvre toutes les facons dont un appel HTTP
echoue ; le reste est un defaut. La branche DM et la branche webhook etaient
en plus imbriquees dans un seul try alors qu'elles s'excluent.

logging_config.py et les deux scripts CLI gardent leur largeur, avec la
raison sur la ligne. Le filtre de journalisation est le cas ou la trace que
BLE001 reclame est precisement ce qu'il ne faut pas produire : journaliser
depuis un filtre rentre dans le meme filtre.

RUF100 (noqa inutile) n'est volontairement pas active : il ferait remonter
des directives preexistantes sans rapport avec ce chantier.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-11 16:29:13 -04:00

78 lines
3.6 KiB
TOML

# 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",
# Every model uses datetime.utcnow as a column default. Tracked as
# DB-009; the warning would otherwise drown the run.
"ignore:datetime.datetime.utcnow:DeprecationWarning",
]
[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"