Секции в Poetry: Полное руководство по pyproject.toml
Содержание
- Введение
- Два стиля конфигурации
- Старый стиль конфигурации
- Новый стиль (PEP 621)
- Секция [tool.poetry] в новом стиле
- Секция [build-system]
- Дополнительные секции инструментов
- Распространённые ошибки
- Автоматическое обнаружение пакетов
- Рекомендации по выбору стиля
- Заключение
- Чек-листы
Секции в Poetry: Полное руководство по pyproject.toml
Введение
Poetry использует файл pyproject.toml для управления конфигурацией проекта. Понимание структуры секций этого файла критически важно для правильной настройки Python-проектов. В этой статье разберём все основные секции, их назначение и правильное использование.
Файл pyproject.toml стал стандартом для определения метаданных и зависимостей Python-пакетов, заменяя старые форматы вроде setup.py и requirements.txt. Poetry реализует этот стандарт и добавляет свои расширения для упрощения управления проектами.
Два стиля конфигурации
Начиная с Poetry 1.2.0+ и poetry-core 2.0.0+, поддерживаются два стиля конфигурации. Это связано с эволюцией стандарта Python Packaging: сообщество разработало PEP 621 для стандартизации метаданных пакетов, и Poetry адаптировался к этому изменению.
| Стиль | Секция метаданных | Описание |
|---|---|---|
| Старый (Legacy) | [tool.poetry] |
Все метаданные в секции Poetry. Используется во всех версиях Poetry до 1.2.0 и по-прежнему поддерживается. |
| Новый (PEP 621) | [project] |
Стандартизированные метаданные Python согласно PEP 621. Рекомендуется для новых проектов. |
Важно: Смешивание стилей — главная причина ошибок конфигурации! Выберите один стиль и придерживайтесь его во всем файле.
Старый стиль предоставляет более удобный синтаксис для указания зависимостей, но ограничен экосистемой Poetry. Новый стиль следует стандарту Python и обеспечивает лучшую совместимость с другими инструментами, такими как pip, setuptools и hatch.
Старый стиль конфигурации
Старый стиль конфигурации размещает все метаданные проекта внутри секции [tool.poetry]. Этот подход использовался в Poetry с самого начала и до сих пор полностью поддерживается. Он предлагает более удобный синтаксис для определения зависимостей и групп.
Полный пример
Этот пример демонстрирует полную конфигурацию проекта в старом стиле. Обратите внимание на структуру: все основные метаданные находятся в секции [tool.poetry], зависимости разделены на основные и группы разработки, а также определены скрипты командной строки.
[tool.poetry]
name = "my-project"
version = "0.1.0"
description = "Описание проекта"
authors = ["Your Name <Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. >"]
readme = "README.md"
license = "MIT"
packages = [
{ include = "my_package", from = "src" }
]
[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.31.0"
pydantic = "^2.0"
[tool.poetry.group.dev.dependencies]
pytest = "^8.0"
black = "^24.0"
mypy = "^1.0"
[tool.poetry.scripts]
my-cli = "my_package.cli:main"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Секции старого стиля
Рассмотрим каждую секцию старого стиля подробнее.
[tool.poetry]
Основная секция с метаданными проекта. Здесь определяются базовые атрибуты пакета, такие как имя, версия, описание и авторы. Все поля в этой секции являются обязательными, за исключением некоторых дополнительных параметров вроде homepage или keywords.
[tool.poetry]
name = "project-name" # Имя пакета (обязательно)
version = "1.0.0" # Версия (обязательно)
description = "Описание" # Краткое описание
authors = ["Name <email>"] # Список авторов
license = "MIT" # Лицензия
readme = "README.md" # Файл README
homepage = "https://..." # Домашняя страница
repository = "https://..." # Репозиторий
documentation = "https://..." # Документация
keywords = ["keyword1"] # Ключевые слова
classifiers = [...] # PyPI классификаторы
Важно: имя пакета должно соответствовать правилам именования Python-пакетов (только буквы, цифры и подчеркивания, не начинается с цифры).
[tool.poetry.dependencies]
Основные зависимости проекта, необходимые для его работы. В этой секции определяются все пакеты, которые будут установлены при установке вашего проекта. Синтаксис позволяет легко указывать версии, источники и дополнительные параметры для каждой зависимости.
[tool.poetry.dependencies]
python = "^3.10" # Версия Python
requests = "^2.31.0" # Из PyPI
numpy = { version = "^1.24", optional = true } # Опциональная
local-pkg = { path = "../local" } # Локальный путь
git-pkg = { git = "https://..." } # Из Git
Для указания версий используются семантические версии (SemVer). Оператор ^ означает совместимость с указанной версией (разрешает обновления не ниже текущей минорной версии). Для Python версия указывается в формате ^3.10, что означает любую версию 3.10.x и выше, но ниже 4.0.
[tool.poetry.group.{name}.dependencies]
Группы зависимостей позволяют организовать дополнительные зависимости по категориям. Например, зависимости для разработки (dev), документации (docs) или тестирования (test). Это помогает управлять окружением и устанавливать только необходимые зависимости для конкретной задачи.
[tool.poetry.group.dev.dependencies]
pytest = "^8.0"
black = "^24.0"
[tool.poetry.group.docs.dependencies]
sphinx = "^7.0"
mkdocs = "^1.5"
[tool.poetry.group.test]
optional = true # Опциональная группа
[tool.poetry.group.test.dependencies]
coverage = "^7.0"
Группа может быть помечена как опциональная с помощью параметра optional = true. Это означает, что зависимости в этой группе не будут установлены по умолчанию, только если явно запросить их установку.
[tool.poetry.extras]
Дополнительные функции (extras) позволяют определять именованные наборы зависимостей, которые могут быть установлены дополнительно к основным. Это полезно, когда ваш пакет имеет необязательные функции, требующие дополнительных зависимостей.
[tool.poetry.extras]
postgres = ["psycopg2"]
mysql = ["mysqlclient"]
all-databases = ["psycopg2", "mysqlclient"]
Пользователи могут установить эти дополнительные зависимости с помощью синтаксиса pip install my-package[postgres], что установит основной пакет вместе с зависимостями для PostgreSQL.
[tool.poetry.scripts]
CLI точки входа определяют команды, которые будут доступны после установки пакета. Эти команды становятся доступны в командной строке и вызывают указанные функции в вашем коде.
[tool.poetry.scripts]
my-command = "my_package.cli:main"
another-cmd = "my_package.commands:run"
Синтаксис "module:callable" указывает, какую функцию вызывать при запуске команды. В примере выше, команда my-command будет вызывать функцию main из модуля my_package.cli.
[tool.poetry.plugins]
Плагины для других пакетов позволяют регистрировать точки входа для фреймворков и инструментов, которые поддерживают плагин-систему. Это часто используется для расширения функциональности инструментов вроде pytest или Poetry.
[tool.poetry.plugins."poetry.plugin"]
my-plugin = "my_plugin:MyPlugin"
[tool.poetry.plugins."pytest11"]
my-fixture = "my_package.pytest_plugin"
В первом примере регистрируется плагин для самой Poetry, во втором — расширение для pytest. Это мощный механизм для интеграции вашего пакета с экосистемой Python.
Новый стиль (PEP 621)
Новый стиль конфигурации основан на стандарте PEP 621, который определяет стандартный формат для метаданных Python-пакетов. Этот подход делает файлы конфигурации совместимыми с различными инструментами сборки и управления пакетами в экосистеме Python.
Хотя синтаксис PEP 621 может показаться более многословным по сравнению со старым стилем Poetry, он обеспечивает лучшую переносимость и будущую совместимость. Стандарт принят не только Poetry, но и другими инструментами, такими как Hatch, PDM и даже setuptools при использовании pyproject.toml.
Полный пример
Этот пример демонстрирует полную конфигурацию проекта в стиле PEP 621. Обратите внимание на разделение зон ответственности: метаданные в секции [project], а специфичные для Poetry настройки — в секции [tool.poetry].
[project]
name = "my-project"
version = "0.1.0"
description = "Описание проекта"
authors = [
{ name = "Your Name", email = "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. " }
]
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"
dependencies = [
"requests>=2.31.0",
"pydantic>=2.0",
]
optional-dependencies.dev = [
"pytest>=8.0",
"black>=24.0",
]
[project.scripts]
my-cli = "my_package.cli:main"
[tool.poetry]
packages = [
{ include = "my_package", from = "src" }
]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
Важное отличие: версия poetry-core в новом стиле должна быть не ниже 2.0.0.
Секции нового стиля
Рассмотрим каждую секцию нового стиля подробнее.
[project]
Стандартизированные метаданные проекта в соответствии с PEP 621. Эта секция содержит всю информацию о пакете, необходимую для его сборки и публикации. Формат соответствует стандарту, что делает его совместимым с множеством инструментов Python.
[project]
name = "project-name"
version = "0.1.0"
description = "Описание"
authors = [
{ name = "Name", email = "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. " }
]
maintainers = [
{ name = "Maintainer", email = "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. " }
]
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"
keywords = ["keyword1", "keyword2"]
classifiers = [
"Development Status :: 3 - Alpha",
"Programming Language :: Python :: 3.10",
]
В отличие от старого стиля, авторы и сопровождающие указываются как массив объектов, что позволяет предоставить более структурированную информацию. Поля maintainers и keywords являются необязательными, но улучшают метаданные пакета.
[project.dependencies] / dependencies
Зависимости в формате PEP 508. В этом стиле зависимости указываются как массив строк в формате, стандартизированном Python Packaging Authority. Каждая строка представляет собой спецификацию пакета в формате, понятном pip и другим инструментам.
[project]
dependencies = [
"requests>=2.31.0",
"pydantic>=2.0,<3.0",
"numpy>=1.24; python_version >= '3.10'",
]
Формат PEP 508 позволяет указывать не только версии, но и условия установки, такие как версия Python или операционная система. В примере выше numpy будет установлен только если версия Python 3.10 или выше.
[project.optional-dependencies]
Опциональные зависимости в формате PEP 621. Эта секция заменяет комбинацию [tool.poetry.extras] и групп зависимостей из старого стиля. Каждая группа опциональных зависимостей определяется как отдельный ключ в этой секции.
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"black>=24.0",
]
docs = [
"sphinx>=7.0",
]
all = [
"my-project[dev,docs]",
]
Особенно интересна последняя группа all, которая ссылается на другие опциональные зависимости через синтаксис my-project[dev,docs]. Это позволяет создать "универсальный" набор зависимостей для всех функций проекта.
[project.scripts]
CLI команды в стандартизированном формате. Эта секция имеет тот же функционал, что и [tool.poetry.scripts] в старом стиле, но следует стандарту Python Packaging.
[project.scripts]
my-cli = "my_package.cli:main"
Синтаксис идентичен старому стилю: "module:callable", где callable обычно является функцией main().
[project.gui-scripts]
GUI приложения. Эта особая секция предназначена для приложений с графическим интерфейсом в Windows, где требуется специальный обработчик для предотвращения появления консольного окна при запуске.
[project.gui-scripts]
my-gui = "my_package.gui:start"
Этот функционал доступен только в новых версиях инструментов сборки, поддерживающих PEP 621.
[project.entry-points]
Точки входа для плагинов в стандартизированном формате. Эта секция заменяет [tool.poetry.plugins] из старого стиля и предоставляет единый способ регистрации точек входа для различных систем плагинов.
[project.entry-points."pytest11"]
my-fixture = "my_package.pytest_plugin"
В примере выше регистрируется плагин для pytest. Синтаксис [project.entry-points."pytest11"] соответствует группе точек входа pytest11, определенной в документации pytest.
Секция [tool.poetry] в новом стиле
При использовании PEP 621, секция [tool.poetry] содержит только специфичные для Poetry настройки, которые не имеют эквивалента в стандарте. Основные метаданные и зависимости определяются в секции [project], а Poetry использует свою секцию для управления деталями сборки и упаковки.
Это разделение ответственности улучшает совместимость и читаемость конфигурационного файла. Стандартизированные метаданные находятся в одном месте, а специфичные для Poetry детали — в другом.
[tool.poetry]
# Указание пакетов для включения
packages = [
{ include = "my_package" },
{ include = "my_package", from = "src" },
{ include = "scripts", format = "sdist" },
]
# Исключение файлов
exclude = [
"my_package/tests",
"**/*.pyc",
]
# Включение дополнительных файлов
include = [
"CHANGELOG.md",
{ path = "data/*.json", format = ["sdist", "wheel"] },
]
Параметр packages указывает, какие директории или модули включать в пакет. Параметр format позволяет контролировать, в какие типы дистрибутивов включать файлы (sdist, wheel или оба).
Секция [build-system]
Эта секция является обязательной для всех Python-пакетов, использующих pyproject.toml. Она определяет инструменты, необходимые для сборки пакета. Эта секция не зависит от выбора стиля (старый или PEP 621), но версия poetry-core должна соответствовать используемому стилю.
Для старого стиля
Для старого стиля достаточно базовой версии poetry-core:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Для нового стиля (PEP 621)
Для нового стиля требуется более новая версия poetry-core, которая поддерживает PEP 621:
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
Обратите внимание на ограничение версии <3.0.0. Это обеспечивает совместимость и предотвращает возможные проблемы при выходе новых мажорных версий.
Дополнительные секции инструментов
Файл pyproject.toml может содержать конфигурации для различных инструментов в секциях [tool.*]. Это позволяет централизовать все настройки проекта в одном файле, что упрощает управление и совместную работу.
[tool.pytest.ini_options]
Настройки pytest позволяют управлять поведением фреймворка тестирования без необходимости создания отдельного файла pytest.ini. Это удобно для централизации настроек.
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
addopts = "-v --tb=short"
Параметр testpaths определяет, где искать тесты. python_files указывает шаблон имен файлов с тестами. addopts добавляет дополнительные опции командной строки по умолчанию.
[tool.black]
Настройки форматтера Black. Хотя Black позиционируется как "форматтер без настроек", некоторые базовые параметры все же можно настроить.
[tool.black]
line-length = 88
target-version = ['py310']
include = '\.pyi?$'
Параметр line-length устанавливает максимальную длину строки. target-version определяет версии Python, для которых будет форматироваться код.
[tool.mypy]
Настройки проверки типов с помощью mypy. Эти настройки заменяют файл mypy.ini или .mypy.ini.
[tool.mypy]
python_version = "3.10"
strict = true
ignore_missing_imports = true
Параметр strict включает строгий режим проверки типов. ignore_missing_imports подавляет ошибки для модулей, которые не могут быть импортированы во время проверки (например, для C-расширений).
[tool.ruff]
Настройки линтера Ruff. Ruff — это быстрый линтер и форматтер Python, написанный на Rust. Он может заменить множество инструментов, включая pylint, flake8 и его плагины.
[tool.ruff]
line-length = 88
select = ["E", "F", "I"]
ignore = ["E501"]
[tool.ruff.isort]
known-first-party = ["my_package"]
Параметр select включает определенные правила (в данном случае ошибки, ошибки синтаксиса и импорты). ignore отключает конкретные правила (здесь E501 — слишком длинная строка). Вложенная секция [tool.ruff.isort] содержит настройки для сортировки импортов.
Распространённые ошибки
При работе с файлом pyproject.toml часто встречаются определенные ошибки. Разберем наиболее частые из них и как их избежать.
Ошибка 1: Смешивание стилей
Попытка использовать одновременно старый и новый стили приведет к ошибкам или неожиданному поведению.
Неправильно:
[project]
name = "my-project"
version = "0.1.0"
[tool.poetry.dependencies] # Старый стиль с новым!
requests = "^2.31.0"
Правильно (PEP 621):
[project]
name = "my-project"
version = "0.1.0"
dependencies = [
"requests>=2.31.0",
]
Решение: чётко выберите один стиль и придерживайтесь его во всем файле.
Ошибка 2: Неправильный формат packages
Некорректный синтаксис при определении пакетов для включения в дистрибутив.
Неправильно:
[tool.poetry.packages]
packages = ["my_package"] # Неверный синтаксис
Правильно:
[tool.poetry]
packages = [
{ include = "my_package" }
]
Решение: всегда используйте массив объектов с параметром include.
Ошибка 3: Несовместимая версия poetry-core
Использование устаревшей версии poetry-core с новым стилем конфигурации.
Вызовет проблемы:
[project] # PEP 621
name = "my-project"
[build-system]
requires = ["poetry-core>=1.0.0"] # Старая версия!
Правильно:
[project]
name = "my-project"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
Решение: для PEP 621 всегда используйте poetry-core версии 2.0.0 или новее.
Автоматическое обнаружение пакетов
Poetry может автоматически определять пакеты в проекте при определенных условиях. Это упрощает конфигурацию, так как в простых случаях секцию packages можно не указывать вовсе.
Poetry автоматически находит пакеты, если:
my-project/
├── pyproject.toml
├── my_project/ # Имя совпадает с name (с заменой - на _)
│ └── __init__.py
└── README.md
Или в структуре src:
my-project/
├── pyproject.toml
├── src/
│ └── my_project/
│ └── __init__.py
└── README.md
Для автоматического обнаружения важно:
- Имя директории с пакетом должно соответствовать имени в поле
name, с заменой дефисов на подчеркивания - Директория должна содержать файл
__init__.py(если используется обычный пакет, а не namespace-пакет) - Для структуры src, пакет должен находиться внутри директории src
Если автоматическое обнаружение невозможно или нужно кастомизировать какие пакеты включать, используйте секцию packages:
[tool.poetry]
packages = [
{ include = "my_project", from = "src" }
]
Параметр from указывает базовую директорию, относительно которой искать пакеты.
Рекомендации по выбору стиля
Выбор между старым и новым стилем зависит от конкретных потребностей проекта и команды. Рассмотрим критерии для принятия решения.
| Критерий | Старый стиль | PEP 621 |
|---|---|---|
| Совместимость с другими инструментами | ⚠️ Только Poetry | ✅ Универсальный |
| Простота синтаксиса зависимостей | ✅ requests = "^2.31" |
⚠️ "requests>=2.31.0" |
| Группы зависимостей | ✅ Полная поддержка | ⚠️ Ограниченная |
| Будущее развитие | ⚠️ Legacy | ✅ Стандарт Python |
Рекомендации:
- Для новых проектов — используйте PEP 621. Это будущее экосистемы Python, и со временем инструменты будут лучше поддерживать стандарт.
- Для существующих проектов — продолжайте использовать старый стиль, если нет необходимости в совместимости с другими инструментами.
- Для библиотек с открытым исходным кодом — PEP 621 предпочтителен, так как обеспечивает лучшую совместимость с различными инструментами сборки.
- Для внутренних проектов — выбирайте стиль, с которым команда знакома и комфортно работает.
Заключение
При создании новых проектов рекомендуется использовать PEP 621 для лучшей совместимости с экосистемой Python. Для существующих проектов на старом стиле — продолжайте его использовать, не смешивая подходы.
Ключевые преимущества правильной конфигурации pyproject.toml:
- Предсказуемое управление зависимостями
- Упрощенная установка и развертывание
- Совместимость с инструментами экосистемы Python
- Четкое разделение окружений разработки и продакшена
Ключевые правила:
- Выберите один стиль и придерживайтесь его
- Используйте правильную версию poetry-core
- Проверяйте синтаксис секции packages
- При ошибках — удалите
poetry.lockи запуститеpoetry lockзаново
Правильная настройка pyproject.toml — это фундамент для надежного управления зависимостями и сборки вашего Python-проекта.
Чек-лист 1: Валидация конфигурации Poetry
Используйте этот чек-лист для проверки корректности вашего файла pyproject.toml:
| ✓ | Задача |
|---|---|
| Выбран один стиль конфигурации (либо Legacy, либо PEP 621) | |
Секция [tool.poetry.dependencies] отсутствует при использовании PEP 621 |
|
Версия poetry-core соответствует используемому стилю |
|
Синтаксис packages корректен (используется массив объектов) |
|
| Все зависимости указаны в правильной секции | |
Файл poetry.lock пересоздан после изменений |
|
| Автоматическое обнаружение пакетов работает или явно указаны пакеты | |
| Лицензия указана корректно и соответствует требованиям проекта | |
| Версия Python указана корректно и соответствует используемым фичам | |
| Скрипты и точки входа протестированы и работают корректно |
