Ajoute CODE_QUALITY.md et corrige S7632 a la racine (helper assert_not_none)

- Nouveau db/assert_not_none.py : centralise l'unique suppression
  Bandit/Ruff (# nosec B101 / # noqa: S101) de narrowing de type dans
  tout le moteur. Remplace 11 sites disperses (ai/chat.py, ai/tools.py,
  routes/scenes/scene_object_{add,collision,geometry,personnage_data,
  quiz_config}.py, screens/payload/full_game_payload.py,
  scripts/build_demo_dialogues.py) qui repetaient chacun le meme
  commentaire empile - Sonar (python:S7632) ne parse pas deux
  commentaires # sur une ligne, meme si Ruff et Bandit les acceptent
  chacun tres bien (contrainte structurelle documentee dans
  CODE_QUALITY.md : chaque outil exige son propre mot-cle immediatement
  apres un #, aucun format a un seul # ne peut satisfaire les deux a la
  fois). Les 6 sites # nosec B608 (SQL dynamique) restent inchanges,
  nature differente, hors perimetre de ce refactor.
  Verifie : mypy --strict propre (389 fichiers), ruff/bandit/import-linter
  clean, suite complete verte (591 tests), scan SonarQube local relance
  confirmant S7632 a 7 (1 seul site restant dans le helper lui-meme + les
  6 B608), 0 bug (une regression S8371 trouvee et corrigee en route).

- 4 sites |safe repositionnes sur leur ligne exacte (scene_edit.html,
  register_2fa.html, onboarding_new.html, play.html) - le marqueur
  NOSONAR etait sur la ligne precedente par erreur (meme piege que celui
  documente pour S8371 ci-dessus). Confirme par scan que meme corrige,
  l'analyseur Web de Sonar ne supporte aucune syntaxe de suppression
  inline testee pour la regle Web:S5247 - documente comme limitation
  technique connue dans CODE_QUALITY.md plutot que force.

- CODE_QUALITY.md (nouveau) : reference complete du dispositif qualite -
  vue d'ensemble par outil, configuration de chacun, commandes de lancement
  local, procedure de justification d'une exception (avec le format exact
  attendu par Bandit/Ruff/Sonar, verifie empiriquement), table des 10
  exceptions documentees, backlog (djLint H021, code smells Sonar).

djLint (H021, styles inline) volontairement saute pour ce commit - meme
backlog assume que les commits precedents, aucun rapport avec ce changement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-09-16 12:41:02 +02:00
co-authored by Claude Sonnet 5
parent 20f9398bd4
commit 55e81c0fbb
16 changed files with 187 additions and 35 deletions
+6 -7
View File
@@ -2,6 +2,7 @@ from flask import abort, g, jsonify, redirect, request, url_for
from werkzeug.wrappers import Response
import auth
import db
import screens
from core.flask_app import app
from core.sprite_gate import forbid_admin_only_background, forbid_admin_only_character
@@ -94,11 +95,11 @@ def scene_object_add(slug: str, screen_id: int) -> Response:
# _clamp_to_camera pour l'IA, ici pour un dépôt manuel.
obj_for_clamp = screens.get_scene_object(slug, new_id)
screen = screens.get_screen(slug, screen_id)
assert obj_for_clamp is not None, ( # nosec B101 # noqa: S101 - narrowing de type, sur par construction
"new_id vient d'etre cree par screens.add_scene_object juste au-dessus"
obj_for_clamp = db.assert_not_none(
obj_for_clamp, "new_id vient d'etre cree par screens.add_scene_object juste au-dessus"
)
assert screen is not None, ( # nosec B101 # noqa: S101 - narrowing de type, sur par construction
"screen_id valide : add_scene_object aurait leve IntegrityError sinon (FK scene_id)"
screen = db.assert_not_none(
screen, "screen_id valide : add_scene_object aurait leve IntegrityError sinon (FK scene_id)"
)
max_x = max(0, screen["scene_width"] - obj_for_clamp["width"])
max_y = max(0, screen["scene_height"] - obj_for_clamp["height"])
@@ -110,9 +111,7 @@ def scene_object_add(slug: str, screen_id: int) -> Response:
)
if request.headers.get("X-Requested-With") == "fetch":
obj = screens.get_scene_object(slug, new_id)
assert obj is not None, ( # nosec B101 # noqa: S101 - narrowing de type, sur par construction
"new_id vient d'etre cree par screens.add_scene_object plus haut"
)
obj = db.assert_not_none(obj, "new_id vient d'etre cree par screens.add_scene_object plus haut")
return jsonify(
{
"id": new_id,