67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
"""Export des donnees du dashboard en formats structures."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import re
|
|
from dataclasses import asdict
|
|
|
|
from gitea_dashboard.collector import MilestoneData, RepoData
|
|
|
|
# Caracteres de controle ASCII (0x00-0x1F) sauf \t (0x09), \n (0x0A), \r (0x0D)
|
|
_CONTROL_CHAR_RE = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f]")
|
|
|
|
|
|
def _sanitize_control_chars(text: str) -> str:
|
|
"""Supprime les caracteres de controle ASCII (0x00-0x1F) sauf \\n, \\r et \\t.
|
|
|
|
Ces caracteres peuvent provenir de descriptions de repos Gitea
|
|
et causent des erreurs JSON ('Invalid control character').
|
|
"""
|
|
return _CONTROL_CHAR_RE.sub("", text)
|
|
|
|
|
|
def repos_to_dicts(repos: list[RepoData]) -> list[dict]:
|
|
"""Convertit une liste de RepoData en liste de dicts serialisables.
|
|
|
|
Sanitize les champs texte (name, full_name, description) pour
|
|
supprimer les caracteres de controle invalides en JSON.
|
|
"""
|
|
result = []
|
|
for repo in repos:
|
|
d = asdict(repo)
|
|
for field in ("name", "full_name", "description"):
|
|
if isinstance(d.get(field), str):
|
|
d[field] = _sanitize_control_chars(d[field])
|
|
result.append(d)
|
|
return result
|
|
|
|
|
|
def export_json(repos: list[RepoData], indent: int = 2) -> str:
|
|
"""Exporte les repos en JSON formate.
|
|
|
|
Returns:
|
|
Chaine JSON indentee, prete pour stdout ou ecriture fichier.
|
|
"""
|
|
return json.dumps(repos_to_dicts(repos), indent=indent, ensure_ascii=False)
|
|
|
|
|
|
def milestones_to_dicts(milestones: list[MilestoneData]) -> list[dict]:
|
|
"""Convertit une liste de MilestoneData en liste de dicts serialisables.
|
|
|
|
Sanitize les champs texte (repo_name, title) pour les caracteres de controle.
|
|
"""
|
|
result = []
|
|
for ms in milestones:
|
|
d = asdict(ms)
|
|
for field in ("repo_name", "title"):
|
|
if isinstance(d.get(field), str):
|
|
d[field] = _sanitize_control_chars(d[field])
|
|
result.append(d)
|
|
return result
|
|
|
|
|
|
def export_milestones_json(milestones: list[MilestoneData], indent: int = 2) -> str:
|
|
"""Exporte les milestones en JSON formate."""
|
|
return json.dumps(milestones_to_dicts(milestones), indent=indent, ensure_ascii=False)
|