- Rate-limit failed logins (8 per 15 min per IP or username, 429 + Retry-After) - Add ruff/mypy config and GitHub Actions workflow (ruff, pytest, tsc, tests, build) - Apply ruff autofixes (import order, pyupgrade) - Extract rpy_helpers.py, engine-util.ts, TranslationParts.tsx and translation-types.ts from oversized modules - Add dependency-free React UI tests - Refresh README and ARCHITECTURE (Naninovel/Tomie, status and plans) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
16 lines
555 B
Python
16 lines
555 B
Python
"""Decode source text without silently replacing characters in localisations."""
|
|
import io
|
|
import tokenize
|
|
from pathlib import Path
|
|
|
|
from app.converter.rpy_lexer import ParseError
|
|
|
|
|
|
def read_source(path: Path) -> str:
|
|
raw = path.read_bytes()
|
|
try:
|
|
encoding, _ = tokenize.detect_encoding(io.BytesIO(raw).readline)
|
|
return raw.decode(encoding)
|
|
except (UnicodeError, SyntaxError, LookupError) as exc:
|
|
raise ParseError(f"Не удалось прочитать кодировку сценария: {exc}", path.name) from exc
|