Use um arquivo pyproject.toml para a configuração e os metadados do seu pacote#
Conclusões sobre o pyproject.toml
Há apenas duas tabelas que são obrigatórias para um pacote Python instalável: [build-system] e [project]. A tabela [project] armazena os metadados do seu pacote.
Há dois campos obrigatórios na tabela [project]: name= e version=.
Adicione metadados à seção classifiers do seu arquivo
pyproject.tomlpara facilitar que os usuários encontrem o seu projeto no PyPI.Ao adicionar classifiers à tabela [project], use apenas valores válidos da página de classifiers do PyPI. Um valor inválido aqui gerará um erro quando você fizer a build do seu pacote ou publicar no PyPI.
There is no specific order for tables in the
pyproject.tomlfile. However, fields need to be placed within the correct table sections. For examplerequires =always needs to be associated with the [build-system] table.
Sobre o arquivo pyproject.toml#
Todo pacote Python moderno deveria incluir um arquivo pyproject.toml. Para pacotes Python puros, esse arquivo substitui o arquivo setup.py e/ou setup.cfg para descrever os metadados do projeto.
Se o seu projeto não for Python puro, você ainda pode precisar de um arquivo setup.py para fazer a build das extensões não Python. No entanto, um arquivo pyproject.toml ainda deve ser usado para armazenar os metadados do seu projeto.
Tutorial
Se você está migrando de um arquivo setup.py ou setup.cfg e quer ajuda, confira este tutorial. especificar requisitos de build e metadados é chamado de pyproject.toml
Sobre o formato .toml#
O arquivo pyproject.toml é escrito no formato TOML (Tom’s Obvious, Minimal Language). O TOML é uma estrutura fácil de ler baseada em pares chave/valor. Cada seção no arquivo pyproject.toml contém um [identificador de tabela]. Abaixo desse identificador de tabela estão os pares chave/valor que dão suporte à configuração daquela tabela específica.
Abaixo,
[build-system]é considerado uma tabela na linguagem toml.Dentro da tabela
build-system,requires =é uma chave.O valor associado a
requiresé um array contendo o valor"hatchling".
[build-system]
requires = ["hatchling"]
Como o pyproject.toml é usado quando você faz a build de um pacote#
Quando você publica no PyPI, vai notar que cada pacote tem metadados listados. Vamos dar uma olhada no xclim, um dos nossos pacotes do pyOpenSci. Note que na página inicial do PyPI você vê alguns metadados sobre o pacote, incluindo python, informações do mantenedor e mais. O PyPI consegue preencher esses metadados porque eles foram definidos usando a sintaxe e os classifiers corretos pelos mantenedores do Xclim, arquivo pyproject.toml. Esses metadados, quando o pacote xclim é construído, são traduzidos em um arquivo de distribuição que permite ao PyPI ler os metadados e exibi-los no site deles.
Quando você adiciona a seção classifier ao seu pyproject.toml e o seu pacote é construído, a ferramenta de build organiza os metadados em um formato que o PyPI consegue entender e representar na página inicial do seu pacote no PyPI. Esses classifiers também permitem que os usuários filtrem os pacotes pela versão do python que eles suportam, categorias e mais.#
Benefícios de usar um arquivo pyproject.toml#
Incluir os metadados do seu pacote em um formato pyproject.toml separado e legível por humanos também permite que alguém visualize os metadados do projeto em um repositório do GitHub.
O Setup.py ainda é útil para builds de pacotes complexos
Usar o setup.py para gerenciar builds e metadados de pacotes pode causar problemas no desenvolvimento de pacotes. Em alguns casos em que a build de um pacote Python é complexa, um arquivo setup.py pode ser necessário. Embora este guia não cubra builds complexas, forneceremos recursos para trabalhar com builds complexas no futuro.
Campos opcionais vs. obrigatórios do arquivo pyproject.toml#
Quando você cria o seu arquivo pyproject.toml, há diversos campos de metadados que você pode usar. Abaixo, sugerimos campos específicos para você começar, que dão suporte à publicação no PyPI e ajudam os usuários a encontrar o seu pacote.
Uma visão geral de todos os elementos de metadados do projeto pode ser encontrada aqui.
Campos obrigatórios para a tabela [project]#
Como mencionado acima, o seu arquivo pyproject.toml precisa ter um campo name e version para fazer a build do seu pacote corretamente:
name: Este é o nome do seu projeto fornecido como uma stringversion: Esta é a versão do seu projeto. Se você está usando uma ferramenta de SCM para versionamento (usando tags do git para determinar as versões), então a versão pode ser dinâmica (mais sobre isso abaixo).
Campos opcionais para incluir na tabela [project]#
Recomendamos fortemente que você também adicione as chaves de metadados abaixo, pois elas ajudarão os usuários a encontrar o seu pacote no PyPI. Esses campos deixarão claro como o seu pacote está estruturado, quais plataformas você suporta e quais dependências o seu pacote requer.
Description: esta é uma breve descrição de uma linha do seu pacote.
Readme: Um link para o seu arquivo README.md é usado para a descrição longa. Essa informação será publicada na página inicial do seu pacote no PyPI.
Requires-python (usado pelo pip): este é um campo usado pelo pip. Aqui você informa ao instalador se está usando Python 2.x ou 3.x. A maioria dos projetos estará usando 3.x.
License: a licença que você está usando
Authors: estes são os autores originais do pacote. Às vezes os autores são diferentes dos mantenedores. Em outras ocasiões, podem ser os mesmos.
Maintainers: você pode escolher preencher isso ou não. Você pode preencher usando uma lista com um subelemento para o nome e e-mail de cada autor ou mantenedor
authors = [
{name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
project.dependencies: O grupo de dependências é opcional porque nem todos os pacotes requerem dependências. No entanto, se o seu projeto tiver dependências específicas, inclua esta seção no seu
pyproject.toml. As dependências declaradas no arquivo pyproject.toml serão instaladas pelo uv ou pip quando o seu projeto for instalado.project.optional-dependencies: Dependências opcionais ou de funcionalidade serão instaladas se alguém executar
python -m pip install projectname[feature]. Use este array para declarar dependências que adicionam funcionalidades específicas ao seu pacote e que não são instaladas por padrão quando um usuário executauv syncoupython -m pip install packagename.dependency-groups: Os grupos de dependências organizam os pacotes e ferramentas que um colaborador ou desenvolvedor precisaria para trabalhar no seu pacote. Essas dependências podem incluir ferramentas para construir e executar testes, linters e formatadores de código. Esta é uma forma opcional, mas altamente recomendada, de organizar e instalar dependências. Esta seção pode substituir um arquivo requirements.txt. Saiba mais sobre como adicioná-las ao seu pacote no guia da PyPA aqui.
keywords: Estas são as palavras-chave que aparecerão na página inicial do seu pacote no PyPI. Pense nelas como palavras que as pessoas poderiam usar para pesquisar o seu pacote.
classifiers: A seção classifiers dos seus metadados também é importante para a página inicial do seu pacote no PyPI e para a filtragem de pacotes no PyPI. Uma lista com todas as opções de classifiers pode ser encontrada aqui. Alguns dos classifiers que você deveria considerar incluir
Status de Desenvolvimento
Público-alvo
Tópico
Linguagem de programação
Opções avançadas no arquivo pyproject.toml#
[project.scripts](Pontos de entrada): Os pontos de entrada são opcionais. Se você tem uma ferramenta de linha de comando que executa um script específico hospedado no seu pacote, você pode incluir um ponto de entrada para chamar esse script diretamente na linha de comando (em vez de no shell do Python).Aqui está um exemplo de um pacote que tem script de ponto de entradas. Note que há vários scripts principais definidos nesse pacote que executam conjuntos de tarefas. O pyOpenSci está usando esses scripts para processar seus metadados.
Use Campos Dinâmicos se você tem campos que são preenchidos dinamicamente. Por exemplo, você pode querer atualizar automaticamente a versão do seu pacote usando tags do Git (versionamento baseado em SCM/controle de versão). Exemplo: dynamic = [«version»]
Adicione dependências ao seu arquivo pyproject.toml#
Required dependencies#
A requirements.txt file has been traditionally used to specify dependencies, but modern practice puts these
in the pyproject.toml file. Required dependencies are specified under the [project] section as a list of strings:
[project]
...
...
...
dependencies = [
"dependency-package-name-1",
"dependency-package-name-2",
"pandas",
"xarray",
"geopandas",
"matplotlib"
]
Optional dependencies#
Optional dependencies are specified under the [project.optional-dependencies] section and are intended to give users
options for including additional dependencies with their installation. Optional dependencies are collected together
as a list of strings and assigned to a name:
[project.optional-dependencies]
plot = ["bokeh"]
test = ["pytest", "pytest-cov"]
docs = ["sphinx", "pydata-sphinx-theme"]
Named dependency lists can be invoked by users on installation to include those specific dependencies on installation. Here is an example installing the test and docs dependencies using pip:
python -m pip install examplePy[test,docs]
Other installation tools tend to follow a similar pattern where optional dependencies are concatenated as a list to the package name.
Dependency Groups#
Dependency groups are a way to group package requirements in the pyproject.toml file but exclude them in the
project metadata when it is built. Because it is not included in the project metadadata, users will not be able to
invoke dependency groups when installing from a package index such as PyPI, but they can be accessed by developers
who have all the project data (e.g. through cloning a repository). Optional dependencies are intended for package
consumers and dependency groups are intended for package maintainers and contributors.
To add development dependencies to your build, add a [dependency-groups] array to your pyproject.toml file.
Then specify dependency groups as follows:
[dependency-groups]
test = [
"pytest",
"pytest-cov"
]
lint = [
"black",
"flake8",
"ruff"
]
docs = [
"sphinx",
"pydata-sphinx-theme"
]
One of the capabilities that dependency groups have is the ability to make composition groups.
For example, dev dependency group could be composed of a test dependency group and a lint dependency group:
[dependency-groups]
...
...
...
dev = [
{include-group = "test"},
{include-group = "lint"}
]
To access groups using pip (requires pip 25.1 or higher), you can invoke them during installation like this:
python -m pip install --group dev
Dependências recursivas
Você também pode configurar conjuntos de dependências recursivas. Veja este post de blog para saber mais.
Exemplo de pyproject.toml para build usando hatchling#
Abaixo está um exemplo de configuração de build para um projeto Python. Esta configuração de pacote de exemplo usa o hatchling para construir as distribuições sdist e wheel do pacote.
# pyproject.toml example build setup to use hatchling and hatch_vcs
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "examplePy"
authors = [
{name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
maintainers = [
{name = "All the contributors"},
]
description = "An example Python package used to support Python packaging tutorials"
keywords = ["pyOpenSci", "python packaging"]
readme = "README.md"
license = "BSD-3-Clause"
classifiers = [
# How mature is this project? Common values are
"Development Status :: 4 - Beta",
# Indicate who your project is intended for
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
dependencies = [
"dependency-package-name-1",
"dependency-package-name-2",
"pandas",
"xarray",
"geopandas",
"matplotlib"
]
[dependency-groups]
test = [
"pytest",
"pytest-cov"
]
lint = [
"black",
"flake8",
"ruff"
]
docs = [
"sphinx",
"pydata-sphinx-theme"
]
dev = [
{include-group = "test"},
{include-group = "lint"}
]
Note que as dependências são especificadas neste arquivo.
Exemplo de pyproject.toml para build usando setuptools#
Os metadados do pacote, incluindo autores, palavras-chave etc., também são fáceis de ler. Abaixo você pode ver o mesmo arquivo TOML que usa um sistema de build diferente (setuptools). Note como é simples trocar as ferramentas necessárias para construir este pacote!
Nesta configuração de pacote de exemplo você usa:
setuptools para construir as distribuições sdist e wheel do pacote
setuptools_scm para gerenciar as atualizações de versão do pacote usando tags de controle de versão
No exemplo abaixo, [build-system] é a primeira tabela de valores. Ela tem duas chaves que especificam a API do backend de build e o pacote que a contém:
requires =build-back-end =
[project]
name = "examplePy"
authors = [
{name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
maintainers = [
{name = "All the contributors"},
]
description = "A setuptools example Python package used to support Python packaging tutorials"
keywords = ["pyOpenSci", "python packaging"]
readme = "README.md"
license = "BSD-3-Clause"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Intended Audience :: Science/Research",
]
dependencies = []
dynamic = [
"version",
]
[build-system]
requires = [
"setuptools>=80",
"setuptools-scm",
"wheel",
]
build-backend = "setuptools.build_meta"
[tool.setuptools]
# Allow the package to be used directly from a zip archive.
zip-safe = true
# Do not automatically include non-Python package data in the wheel.
include-package-data = false
[tool.setuptools_scm]
write_to = "src/examplePy/_version.py"
version_scheme = "release-branch-semver"
[project.optional-dependencies]
test = [
"pytest",
"numpy",
"pandas",
"ruff",
]
contrib = [
"pre-commit>=4.1.0",
]