Spaces:
Sleeping
Sleeping
| """Garde-fou contre la prolifération des helpers de rendu. | |
| Les renderers HTML dans ``picarones/report/`` ont accumulé des helpers | |
| locaux dupliqués (couleur, heatmap SVG, etc.) qui devraient vivre dans | |
| un unique ``picarones/report/render_helpers.py``. | |
| État après le sprint de consolidation : tous les ``_color_for_*`` et | |
| ``_build_heatmap_svg`` locaux ont été déplacés dans | |
| ``picarones/report/render_helpers.py`` qui expose | |
| :func:`color_traffic_light`, :func:`color_single_gradient`, | |
| :func:`color_diverging`, :func:`text_color_for_bg` et | |
| :func:`build_grid_svg`. | |
| Snapshot v1.0.0 (2026-05-02, post-consolidation) : **0 helper local | |
| dupliqué**. | |
| Test ratchet : ce nombre ne peut que descendre. Si un nouveau helper | |
| ``_color_for_*`` ou ``_build_heatmap_svg`` apparaît dans un renderer, | |
| le test échoue. La résolution est de paramétrer un des helpers de | |
| :mod:`picarones.reports._helpers.render_helpers` plutôt que de réintroduire | |
| une fonction locale. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from pathlib import Path | |
| REPO_ROOT = Path(__file__).resolve().parents[2] | |
| REPORT_DIR = REPO_ROOT / "picarones" / "report" | |
| #: Snapshot v1.0.0 post-consolidation. Doit rester à 0. | |
| HELPER_BASELINE = 0 | |
| #: Le module mutualisé est exempté (c'est *là* qu'on veut les voir). | |
| HELPERS_MODULE_NAME = "render_helpers.py" | |
| #: Fichiers à ignorer (pas des renderers). | |
| IGNORED_FILES: frozenset[str] = frozenset({"__init__.py", HELPERS_MODULE_NAME}) | |
| #: Patterns capturant les helpers à mutualiser. | |
| #: | |
| #: On vise spécifiquement la duplication observée : coloration et | |
| #: builders SVG génériques. Les helpers vraiment locaux (extraction | |
| #: depuis une structure de données spécifique au domaine, formatage | |
| #: dépendant de la métrique) ne sont *pas* visés. | |
| HELPER_PATTERNS: tuple[re.Pattern[str], ...] = ( | |
| re.compile(r"^def\s+_color_for\w*\s*\("), | |
| re.compile(r"^def\s+_color\s*\("), | |
| re.compile(r"^def\s+_build_heatmap\w*\s*\("), | |
| ) | |
| def _scan_helpers() -> list[tuple[str, int, str]]: | |
| """Retourne la liste des (chemin_relatif, ligne, signature).""" | |
| found: list[tuple[str, int, str]] = [] | |
| for path in sorted(REPORT_DIR.rglob("*.py")): | |
| if path.name in IGNORED_FILES: | |
| continue | |
| try: | |
| text = path.read_text(encoding="utf-8") | |
| except OSError: | |
| continue | |
| for line_num, line in enumerate(text.splitlines(), 1): | |
| for pattern in HELPER_PATTERNS: | |
| if pattern.match(line): | |
| rel = path.relative_to(REPO_ROOT).as_posix() | |
| found.append((rel, line_num, line.strip())) | |
| break | |
| return found | |
| def test_render_helpers_below_baseline() -> None: | |
| """Le nombre de helpers locaux ne peut que descendre. | |
| Quand on consolide un helper vers ``render_helpers.py``, abaisser | |
| aussi :data:`HELPER_BASELINE` dans le même commit pour verrouiller | |
| le gain. | |
| """ | |
| helpers = _scan_helpers() | |
| count = len(helpers) | |
| locations = "\n".join( | |
| f" {rel}:{line} — {sig}" for rel, line, sig in helpers | |
| ) | |
| assert count <= HELPER_BASELINE, ( | |
| f"\n{count} helpers locaux trouvés (baseline {HELPER_BASELINE}).\n" | |
| f"Régression : un nouveau helper a été ajouté.\n\n" | |
| f"Localisations :\n{locations}\n\n" | |
| "Soit déplace ce helper dans picarones/report/render_helpers.py " | |
| "et importe-le, soit relève HELPER_BASELINE consciemment dans " | |
| "tests/architecture/test_render_helpers.py." | |
| ) | |
| def test_baseline_must_be_tightened_when_progress_made() -> None: | |
| """Si le compte est sous le baseline, abaisse :data:`HELPER_BASELINE`. | |
| Force à verrouiller chaque consolidation : sans cette étape, le | |
| progrès n'est pas figé et une régression future passerait inaperçue | |
| sous le seuil obsolète. | |
| """ | |
| count = len(_scan_helpers()) | |
| assert count >= HELPER_BASELINE, ( | |
| f"\nExcellent : {count} helpers vs baseline {HELPER_BASELINE}.\n\n" | |
| f"Mets à jour HELPER_BASELINE = {count} dans " | |
| "tests/architecture/test_render_helpers.py pour verrouiller le gain." | |
| ) | |