Active la regle isort (I) de ruff. 45 fichiers reordonnes, aucun
changement de comportement : la suite passe avant comme apres.
app/models/__init__.py en est exclu. Ses imports sont ranges en onze
couches commentees qui decrivent le graphe de dependances ; trier par
ordre alphabetique laisse chaque titre au-dessus d un import qu il ne
decrit pas, et ce fichier n a qu un role, etre lu.
Commit isole, comme le formatage : un diff de brassage ne doit pas
servir de couverture a un changement de comportement.
QUA-002, premiere moitie. **Ce commit ne fait que reformater** : aucun
changement de comportement, aucune ligne de logique touchee. 72 fichiers,
4 restaient deja conformes. Il est isole exprès, pour que `git log -p` sur
les commits voisins reste lisible.
`quote-style = "preserve"` etait deja pose dans pyproject.toml, ce qui
evite le brassage guillemets simples / doubles : le diff porte sur les
retours a la ligne, l indentation des appels longs et les virgules
finales, pas sur le style de chaine.
Verification : 263 tests passent avant et apres, ruff check propre.
L activation en CI arrive dans le commit suivant, separement, pour que ce
diff-ci ne contienne rien d autre.
Co-Authored-By: Claude Opus 5 <[email protected]>
ARCH-007.
Trois points d entree, trois configurations differentes
python app/app.py 0.0.0.0:10000, debogueur desactive par defaut
python run.py 127.0.0.2:5000, debogueur ACTIVE par defaut
python wsgi.py Waitress, production
Le bloc __main__ de app/app.py disparait : ce module expose la fabrique.
run.py reste le point d entree de developpement, wsgi.py celui de
production, et c est tout.
run.py passait FLASK_DEBUG a 'true' par defaut. Le debogueur Werkzeug
execute du code soumis depuis le navigateur ; un processus lance ainsi et
laisse joignable est un shell distant. Le defaut passe a 'false', avec
l avertissement reecrit pour dire ce que le mode implique reellement.
L hote devient 127.0.0.1 -- 127.0.0.2 est une boucle locale valide mais
inhabituelle -- et hote comme port sont surchargeables par DEV_HOST et
DEV_PORT.
Code mort retire
- discord_bot.py, notify_player_about_one_on_one : jamais appelee, seule
la variante _direct l est.
- evaluations.py, branche else de list_evaluations : elle listait les
evaluations recues, une vue de joueur, alors que les joueurs sont
rediriges au debut de la fonction et que can_evaluate() est vrai pour
les quatre roles restants. Inatteignable.
Les autres elements du constat sont deja resorbes : get_auth_logger est
appelee depuis log_auth_event (OBS-001), et ALLOWED_CONTRACT_EXTENSIONS /
ALLOWED_SIGNED_EXTENSIONS sont lues par pdf_upload_error (SEC-021).
wsgi.py n est pas touche : trusted_proxy et HOST attendent la reponse du
developpeur sur la topologie reelle (nginx sur la meme machine ou non).
Co-Authored-By: Claude Opus 5 <[email protected]>
198 appels flash dans les sept modules de routes, plus les 23 messages de
validation de app/validators.py. Le catalogue compte desormais 631 chaines,
aucune non traduite.
validators.py utilise lazy_gettext : les champs de schema sont construits a
l'import, donc avant qu'une requete existe. Un gettext ordinaire s'y
resoudrait une seule fois, dans la langue active au demarrage.
Un bug introduit par la conversion, puis corrige
Le convertisseur automatique ne voyait que le premier litteral d'un appel
flash, ce qui a casse deux chaines concatenees sur plusieurs lignes dans
users.py -- le resultat n'etait meme pas du Python valide. Ma premiere
verification ne l'a pas vu : elle enchainait py_compile sur head, or head
reussit toujours, donc le "OK" s'affichait quoi qu'il arrive. Les deux
appels sont reecrits et la verification refaite correctement.
Un bug plus interessant, revele par le test de fumee
La langue choisie ne survivait pas a la connexion. login() et logout()
appellent tous deux session.clear() -- l'un contre la fixation de session,
l'autre pour terminer la session -- et le choix de langue partait avec le
reste. Concretement : quelqu'un qui lisait la page de connexion en anglais
se retrouvait en francais des qu'il se connectait.
La langue est une preference d'affichage, pas un etat appartenant au
compte. Les deux endroits la reportent maintenant explicitement, a cote du
jeton CSRF. Quatre tests couvrent le cas, dont un qui verifie que corriger
une cle preservee n'a pas fait tomber l'autre.
Detail de nommage : le convertisseur avait genere %(value)s pour une
expression conditionnelle, ce qui n'aide pas un traducteur. Renomme en
%(player)s.
Les 14 traductions ecrites avec une apostrophe droite sont normalisees en
apostrophe typographique. Sans consequence en HTML, ou ' s'affiche
correctement -- mais les blocs <script> ne decodent pas les entites, et
autant que le catalogue soit homogene.
200 tests.
Co-Authored-By: Claude Opus 5 <[email protected]>
SEC-AUTHZ-002. add_to_team recevait tryout_id et team_id independamment
dans l'URL, controlait l'autorisation sur le tryout, puis operait sur
l'equipe sans jamais etablir de lien entre les deux. Un gestionnaire du
tryout A pouvait donc modifier une equipe du tryout B.
Le lint pointait exactement dessus : `team` etait charge ligne 463 puis
jamais utilise. La correction automatique proposee etait de supprimer la
variable, ce qui aurait fait taire l'avertissement en cimentant la faille.
Elle est desormais utilisee pour ce a quoi elle servait.
Trois defauts sur la meme route, corriges ensemble :
- team.tryout_id != tryout_id repond maintenant 404
- seuls les joueurs inscrits au tryout peuvent rejoindre ses equipes
- int(player_id) sur une entree de formulaire brute levait ValueError,
donc une erreur 500, sur toute valeur non numerique
Nettoyage automatique par ruff : 34 imports et variables morts retires
sur l'ensemble du paquet. La suite de tests a servi de filet, elle passe
a l'identique avant et apres. Aucun changement de comportement.
A noter, OneOnOneRequestSchema figurait aussi parmi les imports morts :
c'est un quatrieme schema jamais appele, la route one_on_one validant ses
dates a la main. Unifier la validation reste a faire (ARCH-005).
Co-Authored-By: Claude Opus 5 <[email protected]>