Практикум: report-periods от шаблона до установленного пакета¶
Создаём report-periods из шаблона Bedrock, добавляем расчёт границ месяца в UTC, проверяем его, собираем версию 0.1.0 и устанавливаем оба формата пакета. Запускаемый пример к статье «Python-библиотека от шаблона до релиза».
Запуск¶
Нужны Git, uv и доступ к сети для загрузки шаблона, интерпретаторов Python и зависимостей. Запустите из корня репозитория сайта:
uv run --no-project --python 3.13 --with-requirements docs/blog/lab/2026-09-07-twelve-libraries-one-standard/requirements.txt python docs/blog/lab/2026-09-07-twelve-libraries-one-standard/generate_and_check.py --output build/report-periods-lab
Каталог результата не должен существовать. Без --output скрипт создаст новый временный каталог и сохранит его после завершения. Первым позиционным аргументом можно передать путь к локальной копии python-library-template; в ней должен быть коммит a1a1e7d5eafdcac08aeed7c1a0daaff31c67ac8c. Это избавит от загрузки шаблона, но для зависимостей сеть всё ещё может понадобиться. generate_and_check.sh просто вызывает тот же Python-скрипт из shell.
Практикум включает доверенный режим Copier для расширения Jinja и задачи после генерации в зафиксированном шаблоне. Эта задача только печатает инструкции. Скрипт создаёт локальный Git-репозиторий, чтобы изолировать правила игнорирования файлов. Он не делает коммитов, не меняет GitHub, не создаёт тегов и не загружает пакеты на PyPI.
Что проверяем¶
| Этап | Ожидаемый результат |
|---|---|
| Исходная заготовка | Ruff, форматирование, mypy, один тест версии; выбор интеграционных тестов возвращает 5 |
| Полезное поведение | Семь тестов на Python 3.11, 3.12 и 3.13, включая перевод в UTC и переход года |
| Намеренные ошибки | Ruff обнаруживает DTZ005; неверный переход из декабря ломает тест |
| Итоговое задание CI | Условие вычисляется для всех 64 сочетаний результатов; проходит только полный успех, исходное пропускало ещё семь сочетаний с пропущенной задачей |
| Тег и версия | Новый шаг публикации принимает два формата тега и отклоняет четыре значения, сверяясь с закоммиченной версией |
| Сборка | Модули в wheel и sdist совпадают; метаданные и py.typed на месте |
| Потребитель | Wheel и sdist установлены отдельно на Python 3.11; проверены изолированный импорт, публичный API и версия |
Скрипт восстанавливает намеренно испорченные файлы, заменяет в созданном проекте итоговое задание CI и шаг публикации и локально воспроизводит изменения версии из релизного PR. GitHub Actions и Trusted Publishing он не запускает, а workflow публикации по-прежнему не ждёт CI на коммите с тегом.
Файлы и результаты¶
generate_and_check.py: генерация, проверки, намеренные ошибки, сборка и установка.periods.py,test_periods.py: поведение библиотеки и шесть сценариев; с тестом версии из шаблона их семь.ci-gate.yml: замена итогового задания; скрипт вычисляет его условие для всех сочетаний результатов.release-check.yml: замена шага публикации, который перезаписывал__version__.pyпо тегу; скрипт исполняет его Python-код.artifact_smoke.py: проверки установленного пакета в каждом чистом окружении.requirements.txt: Copier 9.18.2, jinja2-time 0.2.0 и PyYAML 6.0.3.
В результате сохраняются report-periods/ с uv.lock и dist/, исходные YAML для CI и публикации, каталог потребителя, два чистых окружения, пронумерованные логи команд и report.json. Зависимости для разработки выбираются по ограничениям шаблона, а не фиксируются в requirements практикума; выбранные версии записываются в созданный lock-файл и отчёт. Проверочный запуск 16.10.2026 использовал uv 0.10.2, Ruff 0.17.1, mypy 2.4.0, pytest 9.1.1 и pytest-cov 7.1.0.