grayhook 0230587040 Add installed package version to exported API docs.
Write api-<version>.md with version metadata in each file and index, sanitize
output for safe paths/markdown, atomically replace exports, and add
--keep-old-versions to retain prior exports as an archive.
2026-05-30 18:14:33 +07:00

py-export-api-docs

Экспорт Markdown-документации API для пакетов из requirements.txt.

Скрипт создаёт временное виртуальное окружение (не трогает системный Python), устанавливает зависимости и генерирует документацию через pydoc-markdown 4.x.

Требования

  • Python 3 с модулем venv (на Debian/Ubuntu: python3-venv)
  • pip внутри создаваемого venv (устанавливается автоматически)

Использование

Запускайте из каталога, куда нужно положить папку docs/:

./py-export-api-docs.py requirements.txt
./py-export-api-docs.py /path/to/requirements.txt --recreate-venv
./py-export-api-docs.py requirements.txt --strict
./py-export-api-docs.py requirements.txt --keep-old-versions

Или через интерпретатор:

python3 py-export-api-docs.py requirements.txt

Опции

Опция Описание
requirements Путь к файлу requirements.txt (обязательный аргумент)
--venv-dir PATH Каталог виртуального окружения. По умолчанию: /tmp/export-api-docs-<uid>-<hash>, где hash — SHA256 от текущей рабочей директории
--recreate-venv Удалить и пересоздать venv, переустановить пакеты
--strict Завершить с кодом 1, если хотя бы один пакет или модуль не удалось экспортировать
--keep-old-versions Не удалять предыдущие api-<version>.md и legacy api.md в каталогах модулей

Результат

В текущей рабочей директории создаётся:

docs/
├── README.md              # индекс текущего экспорта
├── <import-module>/
│   ├── api-<version>.md   # документация модуля
│   └── ...                # другие api-<version>.md — только с --keep-old-versions
└── ...

Версия в файлах

В каждом api-<version>.md в начале указаны имя пакета, фактически установленная версия (из метаданных venv, не из спецификатора в requirements.txt) и import-модуль:

<!-- py-export-api-docs: package=requests version=2.32.3 module=requests -->

> **Source:** `requests` **2.32.3** (import: `requests`)

Имя файла — filesystem-safe slug той же версии: небезопасные символы заменяются на _ (например, 1.0+localapi-1.0+local.md, 1.0 rc1api-1.0_rc1.md). В редких случаях разные строки версии могут дать один slug — тогда файл перезаписывается.

Очистка и архив

Режим Поведение
По умолчанию После успешного экспорта удаляются другие api-<version>.md и legacy api.md в каталоге модуля
--keep-old-versions Старые файлы остаются на диске как архив

docs/README.md перезаписывается при каждом запуске и содержит только модули текущего экспорта — архивные файлы в индекс не попадают.

Для каждого пакета определяются корневые import-модули (из top_level.txt в метаданных дистрибутива, из встроенных fallback-таблиц или по эвристике). Каждый модуль экспортируется один раз, даже если несколько пакетов его предоставляют.

Поддерживаемые строки requirements.txt

Обрабатываются:

  • PEP 508 спецификации имён пакетов (requests>=2.28, flask[async], с маркерами окружения после ;)
  • Включения -r other.txt — только если файл лежит внутри дерева каталога, где находится корневой requirements.txt

Устанавливаются pip'ом, но не экспортируются (имя пакета не извлекается):

  • -e (editable installs)
  • Прямые URL и прочие pip-опции, начинающиеся с -

Кэширование venv

Переустановка пакетов пропускается, если:

  • venv уже существует;
  • хеш дерева requirements-файлов (все -r включения) совпадает с сохранённым в .requirements.sha256 внутри venv.

При изменении requirements.txt или включённых файлов зависимости переустанавливаются автоматически. Флаг --recreate-venv принудительно пересоздаёт окружение.

Коды выхода

Код Причина
0 Документация экспортирована (в не-strict режиме допускаются предупреждения)
1 Файл requirements не найден; нет имён пакетов; ничего не экспортировано; или --strict и были ошибки

Предупреждения

Скрипт продолжает работу при частичных сбоях (без --strict):

  • пакет не установился в venv;
  • не удалось определить import-модуль;
  • небезопасное имя модуля;
  • ошибка pydoc-markdown при экспорте.

Для пакетов без top_level.txt используется guess по имени дистрибутива (my-packagemy_package) или встроенные соответствия (python-gitlabgitlab, pyyamlyaml, pillowPIL и др.).

Пример вывода

Creating virtualenv: /tmp/export-api-docs-1000-a1b2c3d4e5f6
Installing packages into temporary virtualenv…
requests -> requests
  wrote docs/requests/api-2.32.3.md (42 KiB)
Done. Documentation in /home/user/project/docs

Сгенерированный docs/README.md:

| Module | Version | File |
|--------|---------|------|
| `requests` | `2.32.3` | [requests/api-2.32.3.md](requests/api-2.32.3.md) |
S
Description
No description provided
Readme 40 KiB
Languages
Python 100%