Files
drhider/History/code-fixes/2026-08-18-fix-review-bugs.md
T

4.9 KiB
Raw Blame History

v0.0.32 — фиксы по ревью обфускатора — 2026-08-18

Дата: 2026-08-18 Версия: 0.0.31 → 0.0.32 Ветка: master (коммит 94e588a, после rebase над c3c6e5b) Источник: ревью History/2026-08-18-review-sonnet-bugs.md


Внесённые изменения

1. Единый обфускатор на все файлы (ТОП-1 — согласованность токенов)

  • Было: api_bp.py обрабатывал каждый файл отдельным obfuscate_files() → новая инстанс TwoPassObfuscator на файл → одна сущность получала РАЗНЫЕ токены в разных файлах, all_mapping (ручной разбор CSV) был неверен.
  • Стало: все файлы сессии → один obfuscate_files(...) с общим mapping. Проверено: «ООО Ромашка» в двух файлах → один токен «Сфера_0001».
  • Побочно: убран хрупкий ручной разбор CSV split(",", 2) (ломавшийся на запятых в значениях) — больше не нужен при едином вызове.

2. Рекурсивный expand_zips (ТОП-2)

  • extractor.py:expand_zips переписан: очередь + распаковка вложенных ZIP. ZIP внутри ZIP теперь раскрывается. Проверено: вложенный doc1.txt извлекается.

3. SSE-дисконнект (ТОП-3)

  • api_bp.py:generate(): ловится (GeneratorExit, BrokenPipeError, ConnectionResetError) вместо одного GeneratorExit.
  • obfuscate_files выполняется в отдельном потоке; прогресс через очередь; флаг отмены (threading.Event) при разрыве соединения.
  • Коллбек прогресса (phase, idx, total, fname) где phase ∈ {start, done} — согласуется с фронт-протоколом (start/done по idx).

4. Кириллица 1С (CP437→CP866)

  • extractor.py._decode_name: если имя не-UTF-8 (флаг 0x800 снят) и содержит не-ASCII → name.encode("cp437").decode("cp866"). Проверено изолированно.

5. Дедупликация имён

  • builder.py:build_zip: одинаковое имя+контент → пропуск; имя+разный контент → суффикс _2, _3... Проверено: ['a.md', 'a_2.md'].
  • obfuscator.py:_dedupe_file_names: уникализация имён на входе до прохода 1 (защита all_texts[fname] от перезаписи).

6. upload(): цикл по всем файлам

  • api_bp.py:upload(): обрабатывает все request.files.getlist("files") (поддержка загрузки целых папок через webkitdirectory).
  • Сохранено поведение ошибок: файл без имени → «No filename» (совместимо с тестом).

7. Лимит объёма сессии

  • session.py: MAX_SESSION_BYTES = 500 MB; в add_file — скип при превышении.

8. Защита от ZIP-бомб

  • extractor.py: проверка total + file_size > LIMIT ДО zf.read; скип архива при превышении ratio/лимита/числа файлов; лимиты глобально на вызов.

Тесты

Набор Результат
test_builder 20/20 OK
test_zip 28/28 OK
test_replacer 10/10 OK
test_scanner 20/20 OK
test_upload 13/13 OK
test_extractor 14/15 — падает .doc (внешний сервис liberta)

test_extractor .doc: отправляется мусорный OLE2-магик b"\xD0\xCF\x11\xE0\x00"*10, сервис liberta.containerk8s.dev.nubes.ru/convert возвращает «conversion produced no .docx». НЕ регрессия от v0.0.32 — ветка .doc/doc_to_markdown не менялась. Вероятно, сервис изменил поведение или не принимает невалидный контент. Требует отдельного разбора.


Git

  • Remote был впереди (посторонний коммит c3c6e5b про магистратуру) → git pull --rebase.
  • Push успешен: c3c6e5b..94e588a.
  • Ветка-сохранение документации: save-docs-2026-08-18 (de072d8).

TODO / открытые вопросы

  • Разобраться с тестом .doc (возможно, обновить тест на актуальный сервис).
  • Визуально проверить SSE-прогресс во фронте после рефакторинга.