Para configurar a deteção de pacotes para um projeto Python que utiliza a estrutura src no macOS, aponte o setuptools para src no ficheiro pyproject.toml e, em seguida, configure filtros para os nomes dos pacotes apenas se precisar de controlar quais são incluídos na distribuição. Para um projeto convencional, o setuptools consegue frequentemente detetar a estrutura de forma automática; configurações explícitas de deteção são úteis quando pretende inclusões ou exclusões previsíveis. Estas instruções aplicam-se ao setuptools, não a todos os backends de compilação de Python.
Verificar a estrutura do projeto e o backend de compilação
A partir do Terminal, mude para a raiz do projeto — a pasta que contém o pyproject.toml — e inspecione os ficheiros com a shell predefinida do macOS, o zsh, ou com o bash caso seja essa a sua shell configurada:
cd '/path/to/project'
find src -maxdepth 3 -type f -print
Substitua o caminho entre aspas pela localização real do projeto. As aspas simples impedem que espaços e carateres especiais da shell presentes num caminho sejam interpretados. Um pacote típico pode estar localizado em src/my_package/__init__.py, com subpacotes em diretórios abaixo deste. O nome de importação é my_package; o diretório denominado src é apenas um contentor e não faz parte desse nome.
Verifique se o pyproject.toml seleciona o setuptools em [build-system], por exemplo com requires = ["setuptools>=61"] e build-backend = "setuptools.build_meta". A documentação do setuptools descreve a deteção automática para estruturas comuns, incluindo src, quando as listas de pacotes e módulos não são fornecidas explicitamente. Outros backends possuem as suas próprias configurações, portanto não copie as definições do setuptools para a tabela de configuração de outro backend. Setuptools: Configuring setuptools using pyproject.toml files
Configurar a deteção explícita no pyproject.toml
Se pretender que a deteção tenha raiz especificamente em src, adicione a seguinte configuração do setuptools ao ficheiro existente:
[tool.setuptools.packages.find]
where = ["src"]
Isto indica ao setuptools onde procurar os pacotes. Não altera o nome do projeto nem o nome de importação do pacote. Se já tiver uma tabela [tool.setuptools.packages.find], edite essa tabela em vez de adicionar uma segunda. Os ficheiros TOML não podem conter definições duplicadas da mesma tabela.
Para restringir a deteção a um pacote e aos seus subpacotes, adicione um padrão include que corresponda ao nome completo do pacote separado por pontos:
[tool.setuptools.packages.find]
where = ["src"]
include = ["my_package*"]
Substitua my_package pelo nome real de importação do pacote. O * permite que o padrão corresponda a subpacotes como my_package.tools; os padrões são comparados com os nomes completos dos pacotes. Também pode excluir pacotes selecionados, por exemplo exclude = ["my_package.tests*"]. O Setuptools documenta estes padrões de inclusão e exclusão, bem como where, no seu guia de deteção de pacotes.
Escolher a forma como a deteção lida com namespace packages
Por predefinição, a deteção pyproject.toml do setuptools procura namespace packages implícitos: os diretórios podem ser tratados como pacotes mesmo quando não contêm um __init__.py. Mantenha este comportamento predefinido se o seu pacote utilizar intencionalmente namespace packages da PEP 420. Se todos os pacotes deverem ter um __init__.py, pode desativar o rastreio de namespaces:
[tool.setuptools.packages.find]
where = ["src"]
namespaces = false
Com esta definição, os diretórios sem __init__.py não são detetados como pacotes. A ausência de um pacote na distribuição compilada pode, portanto, ser explicada pelo local de pesquisa, por um padrão include ou exclude, ou pela definição de namespaces. O guia de empacotamento aborda este comportamento e demonstra como a deteção pode ser limitada a namespace packages selecionados. Python Packaging User Guide: Packaging namespace packages
Saber quando a deteção automática é suficiente
Num projeto src/my_package simples, pode nem necessitar de uma tabela de deteção. O Setuptools consegue reconhecer estruturas comuns quando packages e py-modules não são especificados. Adicione configuração explícita quando necessitar de restringir a seleção de pacotes, lidar com uma árvore menos convencional ou tornar o diretório de origem inequívoco. Evite definir manualmente listas de pacotes em código, a menos que pretenda mantê-las à medida que a árvore de pacotes se altera; listas explícitas podem fazer com que subpacotes recentemente adicionados sejam facilmente omitidos.
Uma estrutura src também significa que executar o Python a partir da raiz do repositório não coloca automaticamente o pacote no caminho de importação. Isto é expectável: a documentação do setuptools refere que é necessária uma instalação editável para utilizar o pacote a partir de um checkout do código-fonte desta forma. A configuração de deteção controla o que é incluído numa distribuição; não substitui a instalação do projeto no ambiente Python utilizado para desenvolvimento. Setuptools: Package Discovery and Namespace Packages
Fontes
Configuring setuptools using pyproject.toml files — setuptools
Package Discovery and Namespace Packages — setuptools
Packaging namespace packages — Python Packaging Authority