Deixe seu pacote Python pronto para o PyPI - pyproject.toml#
Na lição de código instalável, você aprendeu a adicionar as informações mínimas necessárias a um arquivo pyproject.toml para torná-lo instalável. Em seguida, aprendeu a publicar uma versão mínima do seu pacote no PyPI.
Depois disso, você aprendeu a adicionar um:
na raiz do diretório do seu projeto.
To enhance the visibility of your package on PyPI and provide information
about its development status and maintainers, you should add additional
metadata to your pyproject.toml file. This lesson will guide you through
the process.
Objetivos de Aprendizagem
Nesta lição você aprenderá:
Mais sobre o arquivo
pyproject.tomle como ele é usado para armazenar diferentes tipos de metadata sobre o seu pacoteComo declarar informações (metadata) sobre o seu projeto para ajudar os usuários a encontrá-lo e entendê-lo no PyPI.
Se você quiser saber mais sobre o formato pyproject.toml, confira esta página.
Clique para ver os principais pontos da lição
Ao criar seu arquivo pyproject.toml, considere o seguinte:
Há apenas duas tabelas de metadata obrigatórias para instalar e publicar seu pacote Python:
[build-system]
[project].
A tabela [project] armazena a metadata do seu pacote. Dentro da tabela [project], há apenas dois campos obrigatórios:
name=
version=
Você deve adicionar mais metadata à tabela
[project], pois isso facilitará para os usuários encontrarem seu projeto no PyPI. E também facilitará para os instaladores entenderem como instalar seu pacote.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 build e publicar seu pacote no PyPI.
Não há uma ordem específica para as tabelas no arquivo
pyproject.toml. No entanto, os campos precisam estar nas tabelas corretas. Por exemplo,requires =sempre precisa estar na tabela [build-system].Sugerimos que você inclua a tabela [build-system] no topo do seu arquivo
pyproject.toml.
O que é um arquivo pyproject.toml?#
O arquivo pyproject.toml é um arquivo legível por humanos e por máquinas que serve como arquivo de configuração principal do seu pacote Python.
Dica
Fazer build do seu pacote é a etapa que criou os arquivos de distribuição necessários para você publicar no PyPI.
Sobre o formato .toml#
O arquivo pyproject.toml é escrito no formato TOML. TOML é uma estrutura fácil de ler baseada em pares chave/valor. Cada seção no arquivo pyproject.toml contém um [identificador da tabela]. O formato TOML pode ser comparado a outros formatos estruturados, como .json.
Abaixo você pode ver a tabela [build-system]. Dentro dessa tabela há dois pares chave/valor obrigatórios.
requires = é a chave e o valor é ["hatchling"] dentro do array [build-system] especificado por colchetes [].
[build-system] # <- This is a table
requires = ["hatchling"]
# The build backend defines the tool that should be used to build your package distribution files.
build-backend = "hatchling.build"
Para que serve o pyproject.toml?#
O arquivo pyproject.toml informa à sua ferramenta de build:
what Build backend to use to build your package (we are using Hatchling in this tutorial but there are many others to choose from).
how and where to retrieve your package’s version:
estaticamente, onde você declara a versão
version = "0.1.0"oudinamicamente, quando a ferramenta consulta a tag mais recente no seu histórico para determinar a versão atual.
what Dependencies your package needs,
it can also declare Python-version requirements if your package has them.
O arquivo pyproject.toml também facilita para qualquer pessoa que navegue no seu repository GitHub entender rapidamente a estrutura do seu pacote, como:
Como seu pacote é construído,
Quais versões do Python e sistemas operacionais ele suporta
O que ele faz,
Quem o mantém
Por fim, o arquivo pyproject.toml também é frequentemente usado para configurar ferramentas como verificadores estáticos de tipos (por exemplo, mypy) e formatadores/linters de código (por exemplo, black, ruff).
Dica
Confira a documentação da PyPA se você estiver interessado em definir configurações de build para outras ferramentas.
Observe que algumas ferramentas de build podem divergir na forma como armazenam metadata do projeto. Portanto, você pode querer consultar a documentação delas se decidir usar uma ferramenta diferente de Hatch e hatchling. Selecionamos hatchling e hatch como nossa ferramenta de escolha neste tutorial porque ela segue as regras e diretrizes da PyPA.
Como a metadata do pyproject.toml é usada?#
O arquivo pyproject.toml é o arquivo que sua ferramenta de build usa para preencher um METADATA incluído nos arquivos de distribuição do Python que são publicados no PyPI. Esse arquivo METADATA é então usado pelo PyPI para preencher a página inicial do seu pacote no PyPI e ajudar os usuários a filtrar entre as dezenas de milhares de pacotes publicados lá.
Quando você adiciona a seção de classifiers ao seu pyproject.toml e seu pacote é construído, a ferramenta de build organiza a metadata 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 pacotes por versão do Python que suportam, categorias e mais.#
Dica
Uma visão geral mais aprofundada dos arquivos pyproject.toml
Nossa página do guia tem uma visão geral mais aprofundada deste arquivo
Como atualizar seu arquivo pyproject.toml#
Na lição anterior, você criou um arquivo pyproject.toml básico que continha os elementos principais necessários para fazer build do seu pacote:
Uma tabela
[build-system]onde você definiu a ferramenta de build backend do projeto (hatchling)Uma tabela
[project]onde você definiu a versão e o nome do projeto.
O arquivo pyproject.toml que você criou ficou assim:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
Seu próximo passo é adicionar campos de metadata recomendados adicionais que ajudarão os usuários a encontrar seu pacote no PyPI e também descreverão melhor o escopo do seu pacote. Depois de adicionar essa metadata, você não precisará fazer isso novamente. Esses campos de metadata só serão atualizados periodicamente quando você fizer algo como:
remover uma dependência do pacote
modificar quais versões do Python o seu pacote suporta.
Mais sobre hatchling
A documentação do back-end hatchling está aqui
Passo 2: Adicionar README e license#
Nas lições anteriores, você adicionou tanto um arquivo README.md quanto um LICENSE ao repository do seu pacote. Depois de ter esses arquivos, você pode referenciar o README a partir do seu arquivo pyproject.toml e adicionar um código curto indicando sua escolha de LICENSE seguindo o exemplo abaixo.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
description = """
Tools that update the pyOpenSci contributor and review metadata
that is posted on our website
"""
authors = [
{ name = "Firstname Lastname", email = "email@pyopensci.org"},
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" }
]
maintainers = [
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" },
{ name = "New Friend", email = "newbie@pyopensci.org" }
]
readme = "README.md"
license = "MIT"
A entrada license no seu arquivo pyproject.toml deve usar a sintaxe de expressão de license. Muitas vezes é um nome curto (sem espaços) para a license, como «MIT», «BSD-3-Clause» ou «Apache-2.0». Mais precisamente, deve ser uma expressão de license SPDX válida, conforme documentado na especificação SPDX,seja a versão 2.2 ou uma versão compatível posterior.
Se você tiver múltiplas licenses ou uma license personalizada, também pode expressá-las usando uma expressão de license.
Se quiser distribuir arquivos de license ou outros arquivos com informações legais junto com seu pacote, pode incluí-los usando a entrada license-files, mas isso não é obrigatório.
Mas como descubro quais versões do Python devo suportar?
Boa pergunta. O guia do desenvolvedor Python fornece uma página de status (e uma visualização útil) que explica o status de cada release do Python. Os releases do Python passam por várias fases diferentes, explicadas no PEP 602.
Recomendamos que você use o release mais recente do Python na fase de bugfix. Se o seu release do Python estiver na fase de security, recomendamos migrar para uma versão mais nova do Python.
When should I use requires-python?
You do not need to specify requires-python for every package. However, if you
know that your package will not work with older versions of Python, use requires-python
to prevent installers from installing it with those versions. For example, if your package
requires features introduced in Python 3.10:
[project]
requires-python = ">=3.10"
This helps pip select a compatible release of your package for the Python version a user is running.
Step 3: Specify dependencies#
Next add your dependencies table to the project table.
The dependencies = section contains a list (or array in the toml language) of
the Python packages that your package requires to run properly in a Python
environment. Similar to the requirements listed in the [build-system]
table above:
[build-system] # <- this is a table
requires = ["hatchling"] # this is an array (or list) of requirements
as dependencies são adicionadas em uma estrutura de array (semelhante a uma lista Python).
dependencies = ["numpy", "requests", "pandas", "pydantic"]
Uma dependency pode ser limitada a versões específicas usando um especificador de versão. Se a dependency não tiver especificador de versão após o nome da dependency, seu pacote pode usar qualquer versão do pacote dependente. O código muda com o tempo, bugs são corrigidos, APIs mudam, e por isso é bom ser claro sobre qual versão da dependency seu código foi escrito para ser compatível — um pacote que você escreveu este ano provavelmente não é compatível com numpy v0.0.1!
Saiba mais sobre várias formas de especificar intervalos de versões de pacotes aqui.
O especificador de versão mais comum é um limite inferior, permitindo qualquer versão superior à versão especificada. Idealmente você deve definir isso para a versão mais baixa que ainda é compatível com seu pacote, mas na prática, para pacotes novos, isso costuma ser definido na versão que estava atual no momento em que o pacote foi escrito[1].
Limites inferiores ficam assim:
dependencies = [ "numpy>=1.0" ]
Vírgulas são usadas para separar dependencies individuais, e cada pacote na sua seção dependencies pode usar diferentes tipos de especificadores de versão:
dependencies = [
"numpy>=1.0", # Greater than or equal to 1.0
"requests==10.1", # Exactly 10.1
"pandas", # Any version
"pydantic>=1.7,<2" # Greater than or equal to 1.7, but less than 2
]
Seu arquivo pyproject.toml agora ficará assim:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
description = """
Tools that update the pyOpenSci contributor and review metadata
that is posted on our website
"""
authors = [
{ name = "Firstname Lastname", email = "email@pyopensci.org"},
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" }
]
maintainers = [
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" },
{ name = "New Friend", email = "newbie@pyopensci.org" }
]
readme = "README.md"
license = "MIT"
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"]
Fixe dependencies com cautela
«Fixar» (pinning) uma dependency significa defini-la para uma versão específica, assim:
numpy == 1.0.
Se você está construindo um pacote de biblioteca do qual outros desenvolvedores dependerão, deve ser cauteloso antes de fixar uma dependency em uma versão precisa. Aplicações, como sites de produção, frequentemente fixam suas dependencies, já que outros pacotes não dependerão do projeto delas. Isso porque os usuários instalarão seu pacote em vários ambientes. Uma dependency fixada em uma única versão específica pode tornar a resolução de um ambiente Python mais desafiadora. Portanto, fixe dependencies em uma versão específica somente se você absolutamente precisar fazer isso.
Da mesma forma, você deve ser cauteloso ao especificar um limite superior em um pacote. Essas duas especificações são equivalentes:
pydantic>=1.10,<2
pydantic^1.10
Uma ferramenta de build que você deve conhecer e que fixa dependencies com um limite superior por padrão é o Poetry. Leia mais sobre como adicionar dependencies com segurança usando Poetry, aqui.
Step 4: Add PyPI classifiers#
Em seguida, você adicionará classifiers ao seu arquivo pyproject.toml. O valor de cada classifier que você adicionar ao seu arquivo pyproject.toml deve vir da lista de valores de classifiers aceitos pelo PyPI encontrada aqui. Qualquer desvio na ortografia e no formato causará problemas quando você publicar no PyPI.
O que acontece quando você usa classifiers incorretos?
Se você não usar valores de classifiers padrão, ao tentar publicar seu pacote no PyPI ele será rejeitado. 😔 Não se preocupe se o PyPI rejeitar você na primeira tentativa! Isso aconteceu com todos nós.
Revise essa lista e adicione os itens abaixo ao seu arquivo pyproject.toml:
development status
intended audiences
topic
programming language support
A chave classifier deve se parecer com o exemplo abaixo. Algumas observações:
Seus valores de classifiers podem ser diferentes dependendo do público-alvo, do status de desenvolvimento do seu pacote e das versões do Python que você suporta
Você pode adicionar quantos classifiers quiser, desde que use os valores de classifiers designados pelo PyPI.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
description = """
Tools that update the pyOpenSci contributor and review metadata
that is posted on our website
"""
authors = [
{ name = "Firstname Lastname", email = "email@pyopensci.org"},
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" }
]
maintainers = [
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" },
{ name = "New Friend", email = "newbie@pyopensci.org" }
]
readme = "README.md"
license = "MIT"
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
Observe que, embora os classifiers não sejam obrigatórios no seu arquivo pyproject.toml, eles ajudarão os usuários a encontrar seu pacote. Por isso, recomendamos fortemente que você os adicione.
Step 5: Add the [project.urls] table#
Por fim, adicione a tabela project.urls ao seu arquivo pyproject.toml.
project.urls contém links relevantes para o seu projeto. Você pode querer incluir:
Homepage: Um link para a documentação publicada do seu projeto. Se você está seguindo este tutorial, talvez ainda não tenha esse link. Tudo bem, você pode pular por enquanto.
Bug reports: um link para suas issues/discussions ou para onde você quer que os usuários reportem bugs.
Fonte: o link do GitHub / GitLab do seu projeto.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
description = """
Tools that update the pyOpenSci contributor and review metadata
that is posted on our website
"""
authors = [
{ name = "Firstname Lastname", email = "email@pyopensci.org"},
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" }
]
maintainers = [
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" },
{ name = "New Friend", email = "newbie@pyopensci.org" }
]
readme = "README.md"
license = "MIT"
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
[project.urls] # Optional
"Homepage" = "https://www.pyopensci.org"
"Bug Reports" = "https://github.com/pyopensci/pyosmeta/issues"
"Source" = "https://github.com/pyopensci/pyosmeta/"
Dica
Há muitas outras URLs que você pode adicionar aqui. Confira o arquivo README aqui para uma visão geral.
Juntando tudo — seu arquivo pyproject.toml completo#
Abaixo está um exemplo de um arquivo pyproject.toml completo, com comentários em todas as seções que discutimos acima.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.0"
description = """
Tools that update the pyOpenSci contributor and review metadata
that is posted on our website
"""
authors = [
{ name = "Firstname Lastname", email = "email@pyopensci.org"},
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" }
]
maintainers = [
{ name = "Secondperson Fullname", email = "email2@pyopensci.org" },
{ name = "New Friend", email = "newbie@pyopensci.org" }
]
readme = "README.md"
license = "MIT"
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
[project.urls] # Optional
"Homepage" = "https://www.pyopensci.org"
"Bug Reports" = "https://github.com/pyopensci/pyosmeta/issues"
"Source" = "https://github.com/pyopensci/pyosmeta/"
Apêndice — Clique para ver um arquivo pyproject.toml totalmente comentado
Abaixo está um arquivo pyproject.toml totalmente comentado, caso queira usá-lo como referência.
# You can delete all of the comments once you have created your own pyproject.toml file.
# The build system table. Here we use hatchling as the build back end tool.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# The [project] section contains your package's metadata
# notice that the version is setup to be dynamically generated using dynamic=[“version”]
[project]
name = "pyospackage"
# dynamic = ["version"] # you will learn how to dynamically set the version in a future lesson
version = "0.1.0" # manually assign version (not preferred)
description = "Tools that update the pyOpenSci contributor and review metadata that is posted on our website"
authors = [{ name = "Firstname lastname", email = "email@pyopensci.org" }]
# maintainers section is optional but suggested.
maintainers = [
{ name = "firstname lastname", email = "admin@pyopensci.org" }, # Optional
]
# Classifiers have set values - be sure to only use classifier values from the
# PyPI page here: https://PyPI.org/classifiers/
classifiers = [
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
"Development Status :: 4 - Beta",
# Indicate who your project is intended for
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
# Specify the Python versions ensuring that you indicate you support Python 3.
# this is only for PyPI and other metadata associated with your package - for your users to see
"Programming Language :: Python :: 3 :: Only", # BE sure to specify that you use python 3.x
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"]
# This is the metadata that pip reads to understand what versions your package supports
readme = "README.md"
# Pick your license using the license expression syntax specified here:
# https://packaging.python.org/en/latest/specifications/license-expression/
# We suggest MIT, BSD-3-Clause or Apache-2.0
license = "MIT"
# Add urls for your home page, issue tracker and source code
[project.urls] # Optional
"Homepage" = "https://www.pyopensci.org"
"Bug Reports" = "https://github.com/pyopensci/pyospackage/issues"
#"Funding" = ""
"Source" = "https://github.com/pyopensci/pyospackage"
Exemplos de arquivos pyproject.toml#
Abaixo estão alguns exemplos de arquivos pyproject.toml de vários pacotes no ecossistema científico e pyOpenSci.
Encerramento#
Neste ponto, você já criou:
Um arquivo README.md para seu pacote
Um arquivo CODE_OF_CONDUCT.md para apoiar sua comunidade de usuários
E um arquivo LICENSE que define limites legais sobre como as pessoas podem e não podem usar seu software
Você também aprendeu como publicar seu pacote no (test)PyPI.
Publicar uma nova versão do seu pacote no PyPI#
Agora você está pronto para publicar uma nova versão do seu pacote Python no (test) PyPI. Ao fazer isso, verá que a página do seu pacote agora contém muito mais informações.
Tente republicar agora.
Primeiro, atualize a versão do seu pacote no arquivo pyproject.toml. Abaixo, a versão é atualizada de 0.1 para 0.1.1.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "pyospackage"
version = "0.1.1"
Agora use o Hatch para publicar a nova versão do seu pacote em test.PyPI.org.
> hatch publish -r test
Próximo passo (opcional) — publicar no conda-forge#
Agora você tem todas as habilidades necessárias para publicar seu pacote no PyPI.
Se você também quiser publicar seu pacote no conda-forge (que é um canal dentro do ecossistema conda), aprenderá como fazer isso na próxima lição.