From 0ad5a5fabddff75e71325f639ff07962839afe80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Tue, 18 Aug 2026 23:08:43 +0400 Subject: [PATCH] =?UTF-8?q?test:=20.doc=20=D0=B7=D0=B0=D0=B3=D0=BB=D1=83?= =?UTF-8?q?=D1=88=D0=BA=D0=B0=20=E2=80=94=20=D0=B0=D0=BA=D1=82=D1=83=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=B8=D1=81=D0=B0;=20docs:=20=D0=B8=D1=82=D0=BE?= =?UTF-8?q?=D0=B3=D0=B8=20v0.0.32?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/2026-08-18-fix-review-bugs.md | 84 +++++++++++++++++++++++++++ tests/test_extractor.py | 5 +- 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 History/2026-08-18-fix-review-bugs.md diff --git a/History/2026-08-18-fix-review-bugs.md b/History/2026-08-18-fix-review-bugs.md new file mode 100644 index 0000000..62d37b1 --- /dev/null +++ b/History/2026-08-18-fix-review-bugs.md @@ -0,0 +1,84 @@ +# 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-прогресс во фронте после рефакторинга. diff --git a/tests/test_extractor.py b/tests/test_extractor.py index 7a24d12..a4c3cf5 100644 --- a/tests/test_extractor.py +++ b/tests/test_extractor.py @@ -39,9 +39,10 @@ check(".txt — текст извлечён", text == "Просто текст") text = extract_text("документ.txt", "Привет мир".encode("utf-8")) check(".txt — кириллица", "Привет" in text) -# 3. .doc (бинарный — пропускается) +# 3. .doc (бинарный — не конвертируется, возвращается заглушка об ошибке) +# Мусорный OLE2-магик: сервис liberta не может сконвертировать → заглушка "[DOC ...]" text = extract_text("старый.doc", b"\xD0\xCF\x11\xE0\x00" * 10) -check(".doc — заглушка", "not supported" in text.lower() or "binary" in text.lower()) +check(".doc — заглушка", text.startswith("[DOC") or "not supported" in text.lower()) # 4. Неизвестное расширение → UTF-8 text = extract_text("file.xyz", "hello".encode("utf-8"))