- 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>
39 lines
1.6 KiB
Python
39 lines
1.6 KiB
Python
from typing import Any
|
|
|
|
from flask import jsonify, request
|
|
from werkzeug.wrappers import Response
|
|
|
|
import db
|
|
import screens
|
|
from core.flask_app import app
|
|
|
|
|
|
@app.route("/game/<slug>/scene-objects/<int:object_id>/collision", methods=["POST"])
|
|
def scene_object_collision(slug: str, object_id: int) -> Response | tuple[Response, int]:
|
|
"""Boîte de collision d'un objet de scène (voir "🧱 Collision" dans
|
|
templates/scene_edit.html, static/js/play/conditions.js::
|
|
elementsOverlap pour son usage au jeu)."""
|
|
body = request.get_json(silent=True) or {}
|
|
obj = screens.get_scene_object(slug, object_id)
|
|
if not obj:
|
|
return jsonify({"error": "objet introuvable"}), 404
|
|
|
|
settings: dict[str, Any] = {"enabled": bool(body.get("enabled", True))}
|
|
settings["shape"] = body.get("shape") if body.get("shape") in screens.COLLISION_SHAPES else "rectangle"
|
|
for key in ("width", "height"):
|
|
try:
|
|
value = body.get(key)
|
|
settings[key] = float(value) if value not in (None, "") else None
|
|
except (TypeError, ValueError):
|
|
settings[key] = None
|
|
for key in ("offset_x", "offset_y"):
|
|
try:
|
|
settings[key] = float(body.get(key) or 0)
|
|
except (TypeError, ValueError):
|
|
settings[key] = 0
|
|
|
|
screens.set_scene_object_collision(slug, object_id, settings)
|
|
obj = screens.get_scene_object(slug, object_id)
|
|
obj = db.assert_not_none(obj, "object_id valide (deja lu ci-dessus, rien ne l'a supprime entre-temps)")
|
|
return jsonify({"ok": True, "collision": screens.resolve_collision_settings(obj)})
|