Files
Igor20264 f7136bd8bd
Example document / build (push) Has been cancelled
Python application / build (push) Has been cancelled
v0.5.3
- Мелкие исправления увеличивающие работу конвертера
2026-09-10 10:50:15 +03:00

16 KiB
Raw Permalink Blame History

Незакрытые задачи после аудита

Состояние на 10 сентября 2026. Всё перечисленное — то, что осталось после прохода по плану оптимизации. Что уже сделано, см. audit-report.md.

Тесты сейчас: 320 passed, 1 skipped, 174 subtests, полный прогон 11.85 с. Ничего не закоммичено — всё лежит в staging и рабочем дереве.


P0 — сломает сборку, если не сделать

mdexport/ не добавлен в git

Пакет mdexport/ (общий обходчик AST для md2latex и md2fodt) создан, но остался untracked, при этом на него уже завязаны:

  • pyproject.toml — перечислен в [tool.hatch.build.targets.wheel].packages
  • md2latex/emitter.py, md2latex/escape.py
  • md2fodt/emitter.py, md2fodt/escape.py

На свежем клоне оба конвертера упадут с ModuleNotFoundError, сборка колеса тоже. Локально работает только потому, что файлы лежат на диске.

git add mdexport/blocks.py mdexport/inline.py mdexport/labels.py mdexport/__init__.py
git status --short mdexport

Скомпилированные .pyc внутри уже покрыты правилом __pycache__/, добавлять их не нужно.


P1 — найденный баг, теряет данные

word2md выбрасывает пункты списка при смене его типа

Найден при разборе _handle_paragraph. Баг существовал и до рефакторинга, его сохранили намеренно, чтобы правка осталась поведенчески нейтральной.

word2md/walker.py, строки 406-429. Оба обработчика списков заканчиваются на return [], выбрасывая накопленный out — притом что _flush_code(out) и _flush_list(out) внутри уже успели в него дописать:

    def _as_numbered_list_item(self, para: _Para, out: list[Block]) -> list[Block] | None:
        if not paragraph_has_numpr(para.paragraph):
            return None
        self._flush_code(out)          # может дописать в out
        ...
        self._append_list_item(ordered, body, out)   # внутри вызывает _flush_list(out)
        return []                       # <- out выброшен

_append_list_item (строки 431-437) при смене типа списка вызывает _flush_list(out), который сбрасывает накопленные пункты в out. После чего return [] их теряет. Соседний _as_plain_paragraph (строка 439) в такой же ситуации корректно делает return out.

Воспроизведение: два упорядоченных пункта с numPr, за ними пункт-буллет. Оба упорядоченных пропадают из результата. Тот же механизм теряет и забуференный код, если он был.

Порядок работ: сначала красный тест на исчезающие пункты, потом замена return [] на return out в обоих обработчиках, потом проверка, что побайтовая сверка вывода на остальных документах не поехала (она поедет только там, где баг срабатывал).


P1 — решено, но не выполнено

Калибровка Courier New 10 пт

Ты выбрал вариант «10 пт канон по табл. 4.1, добавить калибровку и перевести тест-фикстуру». Не сделано — я не успел запустить задачу до конца сессии.

Что именно нужно, в md2gost/renderable/paragraph_sizer.py, метод Font.get_line_height (строки 78-83):

        # TODO: make it work for all fonts
        if "Times" in str(self._face.family_name) and self._freetypefont.size == 14:
            return Pt(16.05)
        if "Courier" in str(self._face.family_name) and self._freetypefont.size == 12:
            return Pt(13.61)

Сейчас калиброванная ветка есть только для Courier 12 пт. Замеры, снятые в ходе аудита:

Размер Возвращает сейчас Фактическая высота
Courier 10 пт 11.000 ≈ 11.34
Courier 11 пт 12.000 —
Courier 12 пт 13.610 (калибровка) 13.61
Courier 14 пт 16.000 —

Целые числа выдаёт округление FreeType; калибровочные ветки существуют ровно затем, чтобы подменить округление реальным значением Word. Пропорция от 13.61 при переходе 12 → 10 пт даёт примерно 11.34.

Итог: пока ветки для 10 пт нет, каждая строка листинга меряется примерно на 3% короче, и на длинных листингах разъезжаются разрывы страниц.

Порядок работ:

  1. Добавить ветку Courier + размер 10 → Pt(11.34). Лучше сначала подтвердить число замером в Word через COM, а не принимать пропорцию на веру.
  2. Перевести tests/__init__.py (строка 27) с Pt(12) на Pt(10), чтобы фикстура совпадала с style_config.py:305 и табл. 4.1.
  3. Прогнать tests/test_paragraph_sizer.py — серия test_count_lines_courier1..10 завязана на текущую высоту, ожидаемые значения поедут.

Не делай пункт 2 без пункта 1 — иначе калиброванная ветка перестанет срабатывать, и замер станет хуже, чем сейчас.

Other_Code/ — 59 файлов, 1158 КБ

Это была Фаза 4.2 плана, и я её просто не назначил ни одному исполнителю при раскладке работ. Каталог до сих пор полностью в git.

Ни одного импорта из md2gost, word2md, md2latex, md2fodt, tests/; не упоминается в .spec, .bat, .github/workflows/, pyproject.toml. Единственные ссылки — раздел 12 в PROJECT.md и внутренние перекрёстные ссылки самого каталога.

Команды и три варианта действий расписаны в git-cleanup.md, раздел 1.

Личные документы в корне

ТарасовИА_КР_v3.docx (2326 КБ) и Практическая_работа_6.docx (42 КБ) — ФИО прямо в имени файла. Ты сказал, что уберёшь руками; команды и предупреждение про ловушку с md2gost/Template.docx в git-cleanup.md, раздел 2.


P2 — открытые вопросы по методичке

«С новой страницы» для надписи листинга

Табл. 4.1 (docs/reference/method-mirea-2022.txt, строки 714-715) в блоке «Положение на странице» перечисляет и «Не отрывать от следующего», и «С новой страницы».

В md2gost/style_config.py у стиля Caption Listing (строки 278-291) есть keep_with_next=True, но нет page_break_before=True. Вопрос не праздный: в репозитории есть целая система режимов --listing-continuation, так что отсутствие разрыва может быть осознанным выбором. Плюс Caption.__init__ теперь явно ставит page_break_before = False, чтобы не плодить пустые страницы при сочетании с keep_with_next — то есть менять придётся согласованно в двух местах.

Решение нужно принять до того, как кто-то «починит» это по табл. 4.1 в лоб.

Правило heading.empty ложно срабатывает внутри листингов

Новое правило в md2gost/checker/__init__.py не вырезает fenced-блоки, поэтому одинокая строка # внутри блока кода будет засчитана как пустой заголовок. Поведение консистентно с уже существующим HEADING_RE в том же файле, то есть это общая для checker'а проблема, а не привнесённая. Чинить имеет смысл сразу для всех проверок заголовков.


P3 — не начатое из Фазы 6

Всё это помечено в плане как опциональное. Ничего из перечисленного не сделано, кроме общего обходчика AST и разбора word2md/_handle_paragraph.

Разбиение idef0.py

1935 строк (сейчас 74 КБ). God-функции: _parse_arrow_line (~177 строк), _draw_kit_form (~121), _route_icom (~110), _draw_arrow (~83), _layout_arrow_label (~80).

Предлагаемая раскладка в пакет idef0/: model.py, parse.py, layout.py, routing.py, scene.py, draw.py, render.py, с реэкспортом публичного API из __init__.py ради тестов. Выигрыша в скорости не даёт, только читаемость.

Отдельно там же: _Scene.to_png() и _Scene.to_svg() дважды обходят один и тот же список операций. Можно сгенерировать SVG и растеризовать его в PNG.

Разбиение gui.py

1695 строк (82 КБ) в одном классе Md2GostApp: главное окно, шесть диалогов, редактор UML-схем на ~270 строк, композер промптов, логика перезаписи файлов, потоки конвертации, загрузка ассетов.

Раскладка: gui/windows/, gui/widgets.py, gui/convert_runner.py, а Md2GostApp оставить тонкой оболочкой.

Ленивые импорты

md2gost/pipeline.py (строки 15-19) и md2gost/gui.py (строки 11-32) тянут весь конвейер на старте: docx, pygments, PIL, lxml. python -m md2gost --help платит за это полную цену. Matplotlib и playwright уже ленивые — сделать так же с остальным.

Общий сборщик ConvertRequest

gui.py (строки 1730-1760) и __main__.py (строки 272-317) дублируют маппинг примерно двадцати полей и уже разошлись: дефолт типа документа в GUI coursework, в CLI practice.

Флаг --open

__main__.py строки 315-316: open_when_done=bool(args.debug). Открытие готового файла привязано к дебагу, отдельного флага нет, хотя в GUI есть галочка.

Скачивание PlantUML блокирует Tk

gui.py строка 1537 — синхронный вызов fetch_plantuml_jar, тогда как Graphviz (1576) и Chromium (1622) рядом уже качаются в отдельном потоке.


P3 — документация не догоняет код

Таблицы модулей в PROJECT.md не знают про mdexport

Новый пакет mdexport не попал в разделы с картой репозитория и перечнем модулей — исполнитель не владел этим файлом и намеренно его не трогал. Заодно стоит убрать оттуда упоминания удалённых прототипов, если раздел 12 их ещё перечисляет.


P4 — замечания исполнителей, оставленные как есть

  • uv.lock в порядке. uv lock отработал с сетью, добавил matplotlib 3.11.1 с транзитивными зависимостями, uv lock --check проходит. Лок синхронен и по matplotlib, и по pywin32 — пересобирать не нужно.
  • Playwright закрывается в конце convert(). Это и было целью Фазы 3.4, но у GUI-сценария появилась плата: при каждой следующей конвертации браузер поднимается заново вместо переиспользования. Если mermaid-диаграммы конвертируются часто, стоит подумать про пул с таймаутом.
  • Кастомный --plantuml-jar другой версии не отражается в ключе кэша. Префикс использует прибитую константу PLANTUML_VERSION. Фингерпринт самого файла закрыл бы дыру, но заставлял бы кэш протухать при каждом появлении и исчезновении jar.
  • Версия jar в ключе кэша задевает и Kroki-рендеры, потому что не-mermaid типы делят один путь кэша между бэкендами. Бамп версии обесценит и записи, отрисованные через Kroki. Это лишняя перерисовка, не более.
  • Если одна диаграмма роняет батч-JVM, отбрасывается вся пачка и каждая диаграмма уходит на свою JVM. Корректно, но стоит одной впустую потраченной JVM.
  • --syntax-highlighting --strict --check теперь завершается с кодом 1, потому что новое правило listing.syntax_highlighting под --strict становится ошибкой. Это ровно то поведение, которое закладывалось, но про него надо помнить в скриптах.
  • Playwright изредка печатает Task was destroyed but it is pending на выходе интерпретера при большом комбинированном прогоне. Не воспроизвелось повторно, все тесты проходят, тот же путь закрытия вызывался и до правок.
  • Правила игнора /tmp_*.png и /tmp_*.puml захватили рабочие черновики tmp_org_full.*, tmp_org_uml.*, tmp_arch.*. Файлы на диске целы, но из git status пропали.
  • todo.txt в корне остался нетронутым — это твой личный блокнот, я его не трогал и не сливал с этим файлом.

Что стоит сделать перед коммитом

  1. git add mdexport/ — иначе всё сломается на свежем клоне.
  2. Просмотреть git diff --cached и git diff — там 34 файла изменений плюс 8095 удалённых строк.
  3. Прогнать .venv\Scripts\python.exe -m pytest -q ещё раз после git add.
  4. Собрать exe одним из build-exe*.bat — ни один из билд-скриптов в ходе аудита не проверялся, а pyproject.toml и состав пакетов поменялись.