chore: add CI, lint config, login rate limit and split large modules

- 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>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-25 11:23:22 +03:00
1 parent 57a4edcbfd
commit bbbcc6a5d8
42 files changed
+678 -391

No files matched your search

+12 -6
View File
@@ -1,13 +1,17 @@
import asyncio
import json
from pathlib import Path
from types import SimpleNamespace
import zipfile
from types import SimpleNamespace
import pytest
from app.config import get_settings
from app.converter.compatibility import CompatibilityError, audit_ir, detect, require_supported_scripts
from app.converter.compatibility import (
CompatibilityError,
audit_ir,
detect,
require_supported_scripts,
)
from app.converter.nani_compiler import compile_package
from app.converter.nani_expr import assignment, parse
from app.converter.nani_package import Package, decode_script, text_records
@@ -92,8 +96,8 @@ def test_renpy_atl_animation_is_rejected_instead_of_becoming_static():
def test_source_encoding_is_preserved_or_explicitly_rejected(tmp_path):
from app.converter.source import read_source
from app.converter.rpy_lexer import ParseError
from app.converter.source import read_source
source = tmp_path / "script.rpy"
source.write_bytes('# coding: cp1251\nlabel start:\n "Привет"'.encode("cp1251"))
assert "Привет" in read_source(source)
@@ -222,8 +226,8 @@ def test_naninovel_resources_keep_keys_delimiters_and_context():
def test_naninovel_import_localization_and_mod_editor_roundtrip(tmp_path, monkeypatch):
from app.blobs import read_bytes
from app.converter.naninovel import convert_naninovel
from app.translation import apply_changes, locale_tables, text_index
from app.mods import document, validate
from app.translation import apply_changes, locale_tables, text_index
monkeypatch.setenv("DATA_DIR", str(tmp_path / "library"))
get_settings.cache_clear()
@@ -250,6 +254,7 @@ def test_naninovel_import_localization_and_mod_editor_roundtrip(tmp_path, monkey
def test_unity_codec_restores_global_hooks_after_error():
from UnityPy.helpers import TypeTreeHelper as helper
from app.converter.unity_scripts import ScriptCodec
codec = ScriptCodec.__new__(ScriptCodec)
before = (helper.read_value, helper.write_value, helper.read_typetree_boost, helper.get_ref_type_node)
@@ -288,9 +293,10 @@ def test_unused_renpy_translation_entries_are_not_script_blockers(tmp_path):
def test_upload_rejects_unsupported_engine_without_queueing(tmp_path, monkeypatch):
from fastapi import HTTPException
from app.routers import versions
from app.uploads import upload_path
from fastapi import HTTPException
source = tmp_path / "unsupported.zip"
with zipfile.ZipFile(source, "w") as archive: