fix(client,exporter): handle HTTP 429 retry and sanitize JSON
_get_with_retry now retries on HTTP 429 responses, respecting the Retry-After header when present. exporter sanitizes control characters (0x00-0x1F except \n \r \t) in text fields before JSON serialization. fixes #11 fixes #12 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,18 +3,38 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from dataclasses import asdict
|
||||
|
||||
from gitea_dashboard.collector import 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.
|
||||
|
||||
Chaque dict contient toutes les donnees du RepoData,
|
||||
pret pour json.dumps().
|
||||
Sanitize les champs texte (name, full_name, description) pour
|
||||
supprimer les caracteres de controle invalides en JSON.
|
||||
"""
|
||||
return [asdict(repo) for repo in repos]
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user