# py-export-api-docs Экспорт Markdown-документации API для пакетов из `requirements.txt`. Скрипт создаёт временное виртуальное окружение (не трогает системный Python), устанавливает зависимости и генерирует документацию через [pydoc-markdown](https://github.com/NiklasRosenstein/pydoc-markdown) 4.x. ## Требования - Python 3 с модулем `venv` (на Debian/Ubuntu: `python3-venv`) - `pip` внутри создаваемого venv (устанавливается автоматически) ## Использование Запускайте из каталога, куда нужно положить папку `docs/`: ```bash ./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 ``` Или через интерпретатор: ```bash python3 py-export-api-docs.py requirements.txt ``` ### Опции | Опция | Описание | |-------|----------| | `requirements` | Путь к файлу `requirements.txt` (обязательный аргумент) | | `--venv-dir PATH` | Каталог виртуального окружения. По умолчанию: `/tmp/export-api-docs--`, где `hash` — SHA256 от текущей рабочей директории | | `--recreate-venv` | Удалить и пересоздать venv, переустановить пакеты | | `--strict` | Завершить с кодом 1, если хотя бы один пакет или модуль не удалось экспортировать | | `--keep-old-versions` | Не удалять предыдущие `api-.md` и legacy `api.md` в каталогах модулей | ## Результат В текущей рабочей директории создаётся: ``` docs/ ├── README.md # индекс текущего экспорта ├── / │ ├── api-.md # документация модуля │ └── ... # другие api-.md — только с --keep-old-versions └── ... ``` ### Версия в файлах В каждом `api-.md` в начале указаны имя пакета, **фактически установленная** версия (из метаданных venv, не из спецификатора в `requirements.txt`) и import-модуль: ```markdown > **Source:** `requests` **2.32.3** (import: `requests`) ``` Имя файла — filesystem-safe slug той же версии: небезопасные символы заменяются на `_` (например, `1.0+local` → `api-1.0+local.md`, `1.0 rc1` → `api-1.0_rc1.md`). В редких случаях разные строки версии могут дать один slug — тогда файл перезаписывается. ### Очистка и архив | Режим | Поведение | |-------|-----------| | По умолчанию | После успешного экспорта удаляются другие `api-.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-package` → `my_package`) или встроенные соответствия (`python-gitlab` → `gitlab`, `pyyaml` → `yaml`, `pillow` → `PIL` и др.). ## Пример вывода ``` 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`: ```markdown | Module | Version | File | |--------|---------|------| | `requests` | `2.32.3` | [requests/api-2.32.3.md](requests/api-2.32.3.md) | ```