Python package guidelines (Português)

Status de tradução:
Esse artigo é uma tradução de
Python package guidelines
. Data da última tradução: 2024-02-27. Você pode ajudar a sincronizar a tradução, se houver
alterações
na versão em inglês.
Diretrizes de pacotes do Arch
32-bit
–
CLR
–
CMake
–
Cross
–
DKMS
–
Eclipse
–
Electron
–
Fonte
–
Free Pascal
–
GNOME
–
Go
–
Haskell
–
Java
–
KDE
–
Kernel
–
Lisp
–
Meson
–
MinGW
–
Node.js
–
Nonfree
–
OCaml
–
Perl
–
PHP
–
Python
–
R
–
Ruby
–
Rust
–
Shell
–
VCS
–
Web
–
Wine
Esse documento cobre padrões e diretrizes na escrita de
PKGBUILDs
para softwares
Python
.
Nome do pacote
Para módulos de biblioteca do
Python 3
, use
python-
nomemódulo
. Também use o prefixo se o pacote fornece um programa fortemente atrelado ao ecossistema do Python (p. ex.
pip
or
tox
). Para outros aplicativos, use apenas o nome do programa.
Nota
O nome do pacote deve estar todo em minúsculo.
Arquitetura
Veja
PKGBUILD (Português)#arch
.
Um pacote Python que contenha extensões C é dependente de arquitetura. Do contrário, muito provavelmente terá nenhuma dependência de arquitetura.
Pacotes compilados usando
setuptools
definem suas extensões C usando a palavra-chave
ext_modules
no
setup.py
.
Fonte
Nota
Com
RFC0020
, o padrão é usar tarballs fonte fornecidas pelo upstream, em vez dos tarballs sdist fornecidos pelo PyPI.
As URLs de download vinculadas do site do PyPI incluem um hash imprevisível que precisa ser obtido no site do PyPI sempre que um pacote precisar ser atualizado. Isso os torna inadequados para uso em um PKGBUILD. PyPI
fornece
um esquema estável alternativo: array
PKGBUILD (Português)#source
source=()
deve usar os seguintes modelos de URL:
Pacote fonte
https://files.pythonhosted.org/packages/source/${_name::1}/$_name/$_name-$pkgver.tar.gz
Pacote wheel Python puro
https://files.pythonhosted.org/packages/py2.py3/${_name::1}/$_name/${_name//-/_}-$pkgver-py2.py3-none-any.whl
(Bilíngue compatível com Python 2 e Python 3):
https://files.pythonhosted.org/packages/py3/${_name::1}/$_name/${_name//-/_}-$pkgver-py3-none-any.whl
(Python 3 apenas)
Note que o nome da distribuição pode conter traços, enquanto sua representação em um nome de arquivo wheel não pode (eles são convertidos em sublinhados).
Pacote wheel específico para arquitetura
Arrays adicionais específicos para arquiteturas podem ser adicionados adicionando ao final um underscore e o nome da arquitetura, por exemplo,
source_x86_64=('...')
. Também
_py=cp310
pode ser usado para não repetir a versão do Python:
https://files.pythonhosted.org/packages/$_py/${_name::1}/$_name/{_name//-/_}-$pkgver-$_py-${_py}m-manylinux1_x86_64.whl
Note que uma variável personalizada
$_name
é usada em vez de
pkgname
já que nomes de pacotes python são geralmente prefixados com
python-
. Essa variável pode ser definida genericamente da seguinte forma:
_name=${pkgname#python-}
Métodos de instalação
Os pacotes Python geralmente são instalados usando um gerenciador de pacotes específico da linguagem, como o
pip
, o qual busca pacotes de um repositório online (geralmente
PyPI
, o Python Package Index) e rastreia os arquivos relevantes.
No entanto, para gerenciar pacotes Python de dentro de
PKGBUILD
s, é necessário "instalar" o pacote Python no local temporário
$pkgdir
/usr/lib/python
<versão do Python>
/site-packages/
$pkgname
.
Para pacotes Python usando
metadados padrão
para especificar seu back-end de compilação em
pyproject.toml
, isso pode ser alcançado mais facilmente usando
python-build
e
python-installer
.
Pacotes antigos podem não especificar que usam
setuptools
e oferecer apenas um
setup.py
que deve ser invocado manualmente.
Nota
As dependências dos metadados do pacote devem ser definidas no array
depends
caso contrário elas não serão instaladas.
Baseado em padrões (PEP 517)
Dica
Ao construir a partir de tarballs fonte fornecidos pelo upstream e o upstream depende do git para derivar uma string de versão para o projeto, é necessário definir variáveis de ambiente específicas da ferramenta para
$pkgver
antes de construir uma wheel:
python-setuptools-scm
and
python-hatch-vcs
:
SETUPTOOLS_SCM_PRETEND_VERSION
python-pbr
:
PBR_VERSION
python-pdm-backend
:
PDM_BUILD_SCM_VERSION
Um fluxo de trabalho baseado em padrões é simples: gere um wheel usando
python-build
e instale-o em
$pkgdir
usando
python-installer
:
makedepends=(python-build python-installer python-wheel)

build() {
    cd "$_name-$pkgver"
    python -m build --wheel --no-isolation
}

package() {
    cd "$_name-$pkgver"
    python -m installer --destdir="$pkgdir" dist/*.whl
}
sendo:
--wheel
resulta em apenas um arquivo wheel a ser construído, sem distribuição de código-fonte.
--no-isolation
significa que o pacote é compilado usando o que está instalado em seu sistema (que inclui pacotes que você especificou em
depends
), por padrão a ferramenta cria um pacote isolado ambiente virtual e executa a construção lá.
--destdir="$pkgdir"
evita a tentativa de instalar diretamente  no sistema hospedeiro em vez do arquivo de pacote, que resultaria em um erro de permissão
--compile-bytecode=...
ou
--no-compile-bytecode
pode ser passado para
installer
, mas o padrão é escolhido com sensatez, então isso não deve ser necessário.
Atenção
Ignorar
build
e colocar o arquivo
.whl
em seu array
source
é desencorajado em favor da compilação a partir do código-fonte e só deve ser usado quando o esta última não é uma opção viável (por exemplo, pacotes que
apenas
vêm com fontes wheel e, portanto, não podem ser compilados a partir do código-fonte).
Atenção
Se o seu pacote for um
pacote VCS
(
python-…-git
), inclua o comando
git -C "${srcdir}/${pkgname}" clean -dfx
em sua função
prepare
. Isso remove wheels obsoletos junto com outros artefatos de compilação e ajuda a evitar problemas futuros. Consulte também problemas upstream para
setuptools
e
Poetry
.
setuptools ou distutils
Se nenhum
pyproject.toml
puder ser encontrado ou não contiver uma tabela
[build-system]
, significa que o projeto está usando o antigo formato legado, que usa um
setup.py
arquivo que invoca
setuptools
ou
distutils
. Observe que embora
distutils
esteja incluído na biblioteca padrão do Python, ter
setuptools
instalado significa que você usa uma versão corrigida de
distutils
.
makedepends=('python-setuptools')  # a menos que exiga somente distutils

build() {
    cd "$_name-$pkgver"
    python setup.py build
}

package() {
    cd "$_name-$pkgver"
    python setup.py install --root="$pkgdir" --optimize=1
}
sendo:
--root="$pkgdir"
funciona igual ao
--destdir
acima
--optimize=1
compila arquivos de bytecode otimizados (
.opt-1.pyc
) para que possam ser rastreados pelo
pacman
em vez de serem criados no sistema host em demanda.
Adicionar
--skip-build
otimiza a tentativa desnecessária de executar novamente as etapas de construção já executadas na função
build()
, se for esse o caso.
Alguns pacotes tentam usar
setuptools
e voltam para
distutils
se
setuptools
não puder ser importado. Neste caso,
setuptools
deve ser adicionado como
makedepends
, para que os metadados Python resultantes sejam melhores.
Se um pacote precisar que
setuptools
seja compilado devido à inclusão de executáveis (o que não é suportado por
distutils
), mas apenas importa
distutils
, então a compilação gerará um aviso, e o pacote resultante estará quebrado (não conterá os executáveis):
/usr/lib/python3.8/distutils/dist.py:274: UserWarning: Unknown distribution option: 'entry_points'
  warnings.warn(msg)
Neste caso, deve-se relatar um bug no upstream. Para contornar o problema, um recurso de ferramentas de configuração não documentado pode ser usado:
# fails because of distutils
python setup.py build

# works by using a setuptools shim
python -m setuptools.launch setup.py build
Se um pacote usar
python-setuptools-scm
, o pacote provavelmente não será compilado com um erro como:
LookupError: setuptools-scm was unable to detect version for /build/python-jsonschema/src/jsonschema-3.2.0.

Make sure you're either building from a fully intact git repository or PyPI tarballs. Most other sources (such as GitHub's tarballs, a git checkout without the .git folder) don't contain the necessary metadata and will not work.
Para corrigir a compilação,
SETUPTOOLS_SCM_PRETEND_VERSION
deve ser exportado como uma variável de ambiente com
$pkgver
como valor:
export SETUPTOOLS_SCM_PRETEND_VERSION=$pkgver
Verificação
Atenção
Evite usar o
tox
para executar os
testsuites
, pois ele é projetado explicitamente para testar as configurações repetidas baixadas do PyPI enquanto
tox
está sendo executado, e não testa a versão que será instalado pelo pacote. Isso anula o propósito de ter uma função
check
.
A maioria dos projetos Python que fornecem
testsuites
(que são conjunto ou coleção de testes) usam
nosetests
ou
pytest
para executar os testes com
test
no nome do arquivo ou diretório contendo a
testsuite
. Em geral, só executar
nosetests
ou
pytest
é o suficiente para executar a
testsuite
.
check(){
    cd "$srcdir/foo-$pkgver"

    # Para nosetests
    nosetests

    # Para pytest
    pytest
}
Se houver uma extensão C compilada, os testes precisam ser executados usando um
$PYTHONPATH
, que reflete a versão maior e menor do Python, para localizá-la e carregá-la.
check(){
  cd "$pkgname-$pkgver"
  local python_version=$(python -c 'import sys; print("".join(map(str, sys.version_info[:2])))')
  # Para nosetests
  PYTHONPATH="$PWD/build/lib.linux-$CARCH-cpython-${python_version}" nosetests

  # Para pytest
  PYTHONPATH="$PWD/build/lib.linux-$CARCH-cpython-${python_version}" pytest
}
Alguns projetos fornecem pontos de entrada no
setup.py
para executar o teste. Isso funciona para
pytest
e
nosetests
.
check(){
    cd "$srcdir/foo-$pkgver"

    # para nosetests
    python setup.py nosetests

    # Para pytest - precisa de python-pytest-runner
    python setup.py pytest
}
Dicas e truques
Descobrindo assinaturas PGP desanexadas no PyPI
Atenção
Em
2023-05-23
, o PyPI removeu a funcionalidade para fornecer assinaturas
OpenPGP
desanexadas.
Se existirem assinaturas PGP desanexadas para um determinado tarball sdist do Python, elas deverão ser usadas para verificar o tarball. No entanto, os arquivos de assinatura não aparecem diretamente na seção de download de arquivos de qualquer projeto em pypi.org. Para descobrir os tarballs sdist e seus possíveis arquivos de assinatura, é possível usar este serviço para obter uma visão geral por projeto:
https://pypi.debian.net/
Para
python-requests
, seria
https://pypi.debian.net/requests
.
Usando versão do Python
Às vezes, durante a preparação, compilação, teste ou instalação, é necessário consultar a versão principal e secundária do Python do sistema. Não codifique isso (por exemplo,
3.9
ou
3.10
) e, em vez disso, use uma chamada ao interpretador Python para recuperar as informações e armazená-las em uma variável local:
check(){
  local python_version=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
  ...
}
Usando site-packages
Às vezes, durante a compilação, o teste ou a instalação, é necessário consultar o diretório
site-packages
do sistema. Não adicione este diretório literalmente (
hardcoded
) e, em vez disso, use uma chamada para o interpretador Python para recuperar o caminho e armazená-lo em uma variável local:
check(){
  local site_packages=$(python -c "import site; print(site.getsitepackages()[0])")
  ...
}
Diretório de teste em site-package
Certifique-se de não instalar um diretório de nome
tests
ao
site-packages
(ou seja,
/usr/lib/pythonX.Y/site-packages/tests/
). Projetos de pacotes Python que usam
setuptools
às vezes são configurados incorretamente para incluir o diretório que contém seus testes como um pacote Python de nível superior. Se você encontrar isso, você pode ajudar registrando um problema no projeto do pacote e pedindo que eles corrijam isso. Por exemplo,
assim
.