85 lines
4.9 KiB
Markdown
85 lines
4.9 KiB
Markdown
# 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-прогресс во фронте после рефакторинга.
|