A estrutura de um projeto (2): passa na minha máquina, falha instalado
Por Dorian Chávez · fundador e CEO da Hábil ·
Os testes passam e o pacote quebra para quem o instala. O guia da PyPA pede src/, mas a instalação editável também lê a pasta do projeto. Com template.
A estrutura de um projeto · entrega 2 de 7 · Python
Cenário: os personagens e a história são inventados. Os dados técnicos e as citações levam a fonte no final.
Em 1 minuto
- Ao rodar os testes a partir da raiz do projeto, o Python pode encontrar a pasta antes do pacote instalado. Um arquivo que nunca entrou no pacote passa nos testes e quebra para quem o instala [1][3].
- O guia de empacotamento do Python (PyPA) resolve isso com uma pasta:
src/. Com ela, o código só roda se for instalado [1]. - Mas atenção: a instalação editável (
pip install -e .) também lê a pasta. Com o hatchling,src/inteira (medido) [5][6]. - Por isso o template desta entrega testa duas vezes: rápido contra a pasta, e de verdade contra o que foi instalado. E traz um script que demonstra isso ficando vermelho quando deve.
- Para segunda-feira: rode os testes contra o pacote instalado num ambiente novo. Se algo quebrar, já se sabe o que é.
Neste artigo
- O que aconteceu na sexta às 9:30?
- O que o guia de empacotamento pede?
- Quais são os cinco erros mais comuns?
- Exercício: dá para repetir o erro do Iván?
- Para levar
- O que vem depois?
- O template e o curso
- O que a Hábil faz?
- Referências
O que aconteceu na sexta às 9:30?
Os testes do Iván passavam todos. O pacote que a Sofía instalou não tinha o arquivo que esses testes usavam.
Quinta-feira, 18:10. Terceiro andar.
Depois do Go, a segunda tarefa pareceu fácil: «Fazer o verificador em Python exportar o relatório para CSV». O verificador era o mesmo programa da semana anterior, mas em Python: lia uma lista de serviços, consultava cada um e dizia quais respondiam.
O repositório, herdado outra vez, tinha esta cara:
revisor/ el paquete
tests/
pyproject.tomlIván escreveu a função num arquivo novo, exportar.py. Deixou-o na raiz, junto de tudo, porque era ali que o via. Em revisor/cli.py acrescentou uma linha: import exportar. Rodou os testes como tinham ensinado, a partir da raiz:
$ python -m pytest -q
. [100%]
1 passed in 0.00sVerde. Subiu a mudança e foi para casa.
Sexta-feira, 9:30.
Sofía, da operação, instalou a versão nova no ambiente dela com pip install . e rodou o comando. O terminal respondeu isto (os caminhos, cortados):
Traceback (most recent call last):
File ".../bin/revisor", line 3, in <module>
from revisor.cli import main
File ".../site-packages/revisor/cli.py", line 1, in <module>
import exportar
ModuleNotFoundError: No module named 'exportar'Iván abriu a pasta: exportar.py estava lá. Rodou os testes de novo. Verde outra vez.
— Na minha máquina passa — escreveu no canal.
Lucía, a líder técnica, respondeu com uma pergunta:
— Os testes testaram o que a Sofía instalou, ou a pasta?
Iván ficou olhando para a tela. Nunca tinha lhe ocorrido que fossem duas coisas diferentes.
— A partir da raiz, o Python vê tudo o que está na raiz — continuou Lucía. — A Sofía não tem essa raiz. Tem o pacote. E no pacote o exportar.py nunca entrou.
O que o guia de empacotamento pede?
Que o código importável viva em src/, para que só rode depois de instalado.
O guia oficial de empacotamento do Python, da PyPA, compara os dois layouts em src layout vs flat layout [1]. No layout plano, o pacote vive na raiz, junto do pyproject.toml. No layout src/, desce um nível.
A diferença que importa está na primeira linha da lista: com src/ é preciso instalar o projeto para rodar o código, e com o layout plano não [1]. Parece uma desvantagem. É justamente o ponto.
O guia explica por quê: o Python põe a pasta atual no começo do caminho de busca, então, se nela houver um pacote com o mesmo nome do instalado, ganha o da pasta. E isso, diz o guia, pode deixar a configuração do empacotamento errada sem que ninguém perceba, «which could result in files not being included in a distribution» [1]. Foi o que aconteceu com o Iván.
A pasta atual tem um detalhe: nem sempre entra. python -m pytest a acrescenta; pytest sozinho, não [3][8]. Iván usou a primeira forma, e com ela a raiz inteira ficou à vista.
O template desta entrega, estructura-python, usa o layout src/:
estructura-python/
├── pyproject.toml el proyecto en un solo archivo
├── servicios.toml el ejemplo
├── src/
│ └── revisor/ EL PAQUETE: lo único que viaja al instalar
│ ├── __init__.py · __main__.py
│ ├── cli.py opciones y código de salida
│ ├── servicio.py el vocabulario. Sin red ni archivos
│ ├── config.py lee servicios.toml
│ ├── revisar.py consulta muchos servicios a la vez
│ ├── reporte.py tabla y JSON
│ └── py.typed
├── tests/ las pruebas: no viajan
│ ├── conftest.py
│ └── test_*.py
├── herramientas/
│ ├── _comun.sh
│ ├── probar-instalado.sh
│ └── probar-frontera.sh
├── .github/workflows/verificar.yml
└── README.md · LICENSE · LICENSE-CONTENIDO.mdO que decide o que vai junto?
Uma linha do pyproject.toml.
[tool.hatch.build.targets.wheel]
packages = ["src/revisor"]O que se instala é uma wheel, um arquivo .whl montado a partir do projeto. Essa linha diz ao hatchling, a ferramenta que a constrói, que a wheel leva src/revisor e nada mais [6]. Sem ela, o hatchling adivinha: procura primeiro revisor/__init__.py e depois src/revisor/__init__.py [7]. O template a escreve para que se possa ler.
Assim, tudo o que vive dentro de src/revisor/ vai junto. O que vive fora, não.
Então src/ já protege?
Da raiz, sim. Da instalação editável, não totalmente.
Para trabalhar, o cômodo é instalar em modo editável: pip install -e .. Assim nada é copiado; o Python lê os arquivos onde estão e cada mudança no código aparece na execução seguinte [5]. O pip avisa que a instalação editável e a normal podem se comportar de forma diferente, conforme a ferramenta de build, e que quem usa o pacote «will see the behaviour of regular installs» [5].
E qual é a do hatchling? A documentação dele diz que, numa instalação editável, ele decide quais pastas acrescentar ao caminho de busca conforme os arquivos selecionados [6]. Medimos: acrescenta src/ inteira. Se alguém deixar um src/suelto.py fora do pacote, a instalação editável o encontra e a wheel não o leva.
A mesma página oferece uma saída, a opção dev-mode-exact [6]. Medido: com ela, import suelto dá ModuleNotFoundError. Mas tem custo, e a página avisa: «The dev-mode-exact mechanism is not supported by static analysis tools & IDEs» [6], então o editor deixa de autocompletar. E também não enxerga o que a wheel exclui dentro do pacote (medido). Por isso o template prefere testar a wheel, que é o que recebe quem instala.
O guia da PyPA já antecipa isso: o típico é usar a instalação editável para desenvolver «and a regular installation is used for testing» [1]. O template faz exatamente isso:
pytest # rápido: lee tu carpeta src/
bash herramientas/probar-instalado.sh # lo que ve quien instala tu paqueteO segundo comando cria um ambiente novo e vazio, instala o projeto sem -e (ou seja, constrói a wheel e a instala) e roda os mesmos testes. No fim, conta os resultados lendo o relatório do pytest, não o código de saída. Estas são as três últimas linhas:
revisor bajo prueba: …/site-packages/revisor (el paquete INSTALADO)
pruebas: 62 · pasaron 62 · fallaron 0 · con error 0 · saltadas 0
✅ lo instalado pasa sus pruebasPor que os testes vivem fora do pacote?
Para que não vão junto, e para que testem o pacote como qualquer um o veria.
tests/ fica ao lado de src/, não dentro. O pytest roda no modo importlib, o que a documentação dele recomenda para projetos novos [2]: nesse modo, ele não põe pastas do projeto no caminho de busca para importar os testes [4]. O que se testa é o que estiver instalado no ambiente.
E como saber o que está instalado? tests/conftest.py diz isso no cabeçalho de cada execução (o que pytest -q omite):
revisor bajo prueba: src/revisor (la CARPETA del proyecto)Com a variável REVISOR_EXIGIR_INSTALADO=1, além disso, ele se recusa a rodar se o revisor vier da pasta do projeto. O script do pacote instalado a ativa, e assim não tem como testar o src/revisor local achando que testou a wheel. Atenção: o guarda só olha de onde vem o revisor. Se outro módulo da pasta escapar para os testes, quem o barra é a fronteira, que vem logo a seguir.
O que há no pyproject.toml?
O projeto inteiro, num único arquivo.
O guia da PyPA descreve três tabelas: [build-system], que diz com o que se constrói; [project], com os dados do projeto; e [tool], para cada ferramenta [13]. O template usa as três, mais uma quarta: [dependency-groups], onde vivem pytest, ruff e mypy com a versão fixada. Esse grupo existe desde a PEP 735, que o define exatamente assim: requisitos guardados no pyproject.toml e que não são incluídos em nenhuma distribuição do projeto [16]. Quem instala o revisor não recebe o pytest.
Um detalhe medido: pip install --group dev precisa do pip 25.1 ou mais novo [17], e um ambiente recém-criado no Ubuntu 24.04, a base do Linux Mint 22 [10], vem com o pip 24.0 [11]. A resposta é no such option: --group. Por isso o README pede python -m pip install --upgrade pip antes de tudo.
E onde vai o CSV do Iván?
No pacote, junto dos outros formatos do relatório.
No template, o relatório já tem casa: reporte.py, que hoje converte resultados em tabela ou em JSON. Uma função a_csv vai ali, junto de a_json, e cli.py acrescenta csv às opções de --formato. Nenhum arquivo na raiz. Nenhuma pasta nova.
Na segunda-feira, Iván moveu a função para dentro do pacote e rodou os testes contra o que estava instalado. Verde. Desta vez, verde de verdade.
Como saber que a fronteira existe?
Porque um script a quebra de propósito e exige que o pacote instalado não veja o que ficou de fora.
herramientas/probar-frontera.sh trabalha numa cópia temporária do projeto. Planta src/suelto.py, um módulo que vive em src/ mas fora do pacote, e um teste que o importa. Depois roda a suíte completa duas vezes, em dois ambientes novos com o mesmo Python, a mesma cópia e a mesma versão do pytest. Entre as duas, muda só uma opção do pip, -e:
- Controle, com
pip install -e. O Python lê a pasta, então todos os testes têm que passar, o plantado incluído. Se não passarem, o experimento está mal montado e o script para no vermelho. - Violação, com
pip install. Instala-se a wheel. Tem que falhar um único teste, o plantado, e com a mensagem exata.
Esta é a saída real:
1/2 control: pip install -e (la carpeta) · src/suelto.py está fuera del paquete
revisor bajo prueba: src/revisor (la CARPETA del proyecto)
✅ 63 de 63 pasaron: desde la carpeta, suelto.py se ve
2/2 violación: pip install (la rueda) · el mismo archivo, la misma prueba
revisor bajo prueba: …/site-packages/revisor (el paquete INSTALADO)
✗ test_suelto_viaja_con_el_paquete: ModuleNotFoundError: No module named 'suelto'
✅ 62 de 63 pasaron; falló solo la que usa suelto.py, por la razón exacta
✅ frontera: se sostienePor que o controle? Porque um experimento que só espera um vermelho também fica «verde» quando falha pelo motivo errado: um teste mal escrito, um ambiente quebrado. Comprovamos: com o teste plantado quebrado de propósito, ou com o controle instalado sem -e, o script para em «o experimento está mal montado».
E se alguém mudar a linha de packages para que a wheel leve todo o src/, a violação passa e o script responde ❌ PASÓ: lo instalado vio src/suelto.py, que no está en el paquete. La frontera no existe. Também comprovamos isso.
O CI do GitHub está escrito para rodar tudo com Python 3.12 e 3.14, a cada mudança, manualmente e toda segunda-feira: ruff, mypy estrito, os testes contra o pacote instalado e a fronteira. Se o repositório público passar 60 dias sem atividade, o GitHub desliga a execução das segundas e é preciso religá-la [23].
Quais são os cinco erros mais comuns?
Os três primeiros vêm de não saber que pasta o Python enxerga; os dois últimos, de descrever o projeto pela metade.
1. Testar a pasta e achar que testou o pacote
O layout plano deixa a raiz à vista, e a raiz não é o que se instala.
É o erro do Iván. O guia da PyPA explica que src/ ajuda a evitar o uso acidental da cópia em desenvolvimento [1]. O pytest pede isso de frente: «it is strongly suggested to use a src layout», sobretudo com o modo padrão [2]. E a documentação do uv diz que uv init prefere pôr o código em src/<nombre>/ [18]; comprovamos com o uv 0.12.23.
A saída não é só trocar de pasta: é testar também o que foi instalado, como faz o template.
2. pip install no Python do sistema
O sistema operacional já administra esse Python, e desde a PEP 668 ele avisa.
A PEP 668 propõe que, por padrão, ferramentas como o pip não instalem nem removam pacotes num Python que o sistema marca como administrado por ele, e que orientem quem tentar para um ambiente virtual [9]. No Ubuntu 24.04, sem ambiente, esta é a resposta (medido):
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.A PEP pede que a opção para forçar «should carry some connotation that its use is risky» [9]. Por isso ela se chama --break-system-packages. Tudo vai dentro de um .venv, como no template.
3. Um arquivo com o nome de um módulo padrão
Um random.py solto esconde o random do Python.
O tutorial oficial avisa: a pasta do script que se executa vai para o começo do caminho de busca, então os arquivos dela são carregados no lugar dos módulos da biblioteca com o mesmo nome, e isso «is an error unless the replacement is intended» [19]. O Python 3.13 acrescentou uma mensagem que aponta isso [12]. Medido com um random.py que importa random:
Python 3.12:
AttributeError: partially initialized module 'random' has no attribute 'randint' (most likely due to a circular import)
Python 3.14:
AttributeError: module 'random' has no attribute 'randint' (consider renaming '…/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)No 3.12, a mensagem fala de uma importação circular e não do arquivo; o 3.12.3 do Ubuntu 24.04, o do Mint, diz o mesmo (medido). Dentro de um pacote, rodando como pacote (python -m revisor.cli ou o comando instalado), o choque não acontece: revisor/random.py se chama revisor.random. Mas, ao rodar o arquivo como script, python src/revisor/cli.py, ele volta (medido no 3.12 e no 3.14).
4. Dois arquivos de teste com o mesmo nome
No modo padrão do pytest, tests/config/test_formato.py e tests/reporte/test_formato.py se chocam.
A documentação do pytest explica: se os testes não estiverem organizados como pacotes, cada arquivo precisa de um nome único, senão o pytest acusa um erro [4]. Medido com o pytest 9.1.1:
import file mismatch:
imported module 'test_formato' has this __file__ attribute:
…/tests/config/test_formato.py
which is not the same as the test file we want to collect:
…/tests/reporte/test_formato.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modulesO conserto de sempre era acrescentar __init__.py a tests/, mas isso faz o pytest pôr a raiz do repositório no caminho de busca, e num layout plano o pacote volta a ser importado a partir da pasta [2]. O modo importlib não tem esse problema [2]: com ele, os dois arquivos passam (medido).
5. setup.py ou requirements.txt como única descrição do projeto
O pip não lê um requirements.txt ao instalar o pacote.
Para projetos novos, o guia da PyPA pede a tabela [project] do pyproject.toml, e manter o setup.py só se for preciso configurar algo com código, como compilar extensões em C [13]. E um requirements.txt não é analisado na instalação: só é usado quando alguém roda pip install -r [14]. Se as dependências vivem só ali, quem instala o pacote não as recebe.
Quer que cada máquina instale exatamente as mesmas versões? Para isso agora existe um formato padrão de arquivo de bloqueio, pylock.toml, da PEP 751 [15]. É outro arquivo, para outro problema.
| Erro | O que o denuncia | Fonte |
|---|---|---|
| 1. Testar a pasta | Verde na máquina local, ModuleNotFoundError instalado | [1][2] |
| 2. pip no Python do sistema | externally-managed-environment | [9] |
3. Um random.py solto | has no attribute num módulo que tem, sim | [12][19] |
| 4. Testes com o mesmo nome | import file mismatch | [2][4] |
5. requirements.txt como única descrição | Instalado, faltam dependências | [13][14] |
Exercício: dá para repetir o erro do Iván?
A ideia é pôr um arquivo fora do pacote, ver a pasta dizer que está tudo bem, e ver o pacote instalado dizer que não.
É preciso ter Python 3.12 ou mais novo (python3 --version), Git e bash, uns 20 minutos. O Linux Mint 22 traz o 3.12; se python3 -m venv reclamar que falta o ensurepip, rode sudo apt install python3.12-venv e repita o comando (a lição 1 do curso explica). No macOS, o python3 do sistema é o da Apple, «usually older» [24] (aqui, 3.9.6): instale um recente a partir do python.org. No Windows, use o WSL.
Passo 1. Clone, prepare o ambiente e confira que está tudo verde.
git clone https://github.com/HabilMX/estructura-python
cd estructura-python
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install --group dev -e .
pytest -q
bash herramientas/probar-instalado.shO que deve aparecer: 62 passed e, no fim, ✅ lo instalado pasa sus pruebas.
Passo 2. Preveja antes de mexer. A ideia é criar src/exportar.py, fora do pacote, e um teste que o importa. Anote: o que o pytest vai dizer? E o script do pacote instalado?
Passo 3. Repita o erro.
cat > src/exportar.py <<'EOF'
def a_csv(filas: list[tuple[str, str]]) -> str:
return "\n".join(",".join(fila) for fila in filas)
EOF
cat > tests/test_exportar.py <<'EOF'
from exportar import a_csv
def test_a_csv() -> None:
assert a_csv([("pagos", "ARRIBA")]) == "pagos,ARRIBA"
EOF
pytest -q
bash herramientas/probar-instalado.shO pytest diz 63 passed: a pasta garante que está tudo bem. O script diz outra coisa (o que importa; abaixo vêm a saída do pytest e um ❌):
pruebas: 63 · pasaron 62 · fallaron 0 · con error 1 · saltadas 0
✗ tests.test_exportar: ModuleNotFoundError: No module named 'exportar'Essa é a sexta-feira da Sofía, na máquina local.
Passo 4. Conserte como o Iván: ponha o arquivo dentro do pacote. Copie só a linha de sed do sistema em uso: o do macOS pede um argumento vazio depois de -i.
mv src/exportar.py src/revisor/exportar.py
# En Linux:
sed -i 's/^from exportar import/from revisor.exportar import/' tests/test_exportar.py
# En macOS:
sed -i '' 's/^from exportar import/from revisor.exportar import/' tests/test_exportar.py
bash herramientas/probar-instalado.shAgora sai pruebas: 63 · pasaron 63 e ✅ lo instalado pasa sus pruebas.
Passo 5. Tente enganar o guarda. Peça ao pytest que exija o pacote instalado, a partir do ambiente editável:
REVISOR_EXIGIR_INSTALADO=1 pytestERROR: REVISOR_EXIGIR_INSTALADO=1, pero revisor viene de la carpeta src/revisor. Estas pruebas probarían tu carpeta, no lo que se instala. Usa: bash herramientas/probar-instalado.shEle se recusou a dar um verde. Esse é o controle trabalhando.
Passo 6. Desfaça tudo.
git checkout -- . && git clean -fd
bash herramientas/probar-frontera.shAtenção: git clean -fd também apaga os arquivos novos criados ali, como anotações.
Como saber que deu certo: foram sete execuções e três desfechos. Verde, cinco vezes: as duas do passo 1, o pytest do passo 3, o passo 4 e a fronteira do passo 6. Vermelho, uma: o pacote instalado no passo 3, com No module named 'exportar'. E a recusa do guarda no passo 5. Se no passo 3 o script sair verde, confira se exportar.py ficou em src/ e não em src/revisor/. Se no passo 4 continuar vermelho, confira se a primeira linha de tests/test_exportar.py diz from revisor.exportar import a_csv.
Para ir mais longe (opcional): acrescente a_csv a reporte.py, some csv às opções de --formato em cli.py e escreva o teste. Antes de rodá-lo, preveja o que probar-instalado.sh vai contar.
Para levar
Três perguntas para fazer ao repositório esta semana.
- De onde rodam os testes? Se a resposta for «da raiz, com
python -m pytest», que arquivos da raiz o Python consegue ver que não vão no pacote? - Os testes já rodaram alguma vez contra o pacote instalado, num ambiente novo e sem
-e? Faça isso uma vez. Se quebrar, é um erro encontrado antes dos usuários. - O projeto está descrito no
pyproject.toml, ou ainda é preciso ler umsetup.pye umrequirements.txtpara saber do que ele precisa?
O que vem depois?
No Go, a fronteira é vigiada pela ferramenta. No Python, pela instalação. No Rust, pelo compilador, e ele é mais rigoroso do que se espera.
Duas semanas depois, o Iván pegou um programa em Rust. Toda a lógica vivia num main.rs de 900 linhas. Ele quis escrever um teste de integração, daqueles que vivem fora do código, em tests/.
O Cargo não encontrou nada para importar. O programa funcionava, mas de fora ninguém conseguia mexer nele.
Como se testa uma função que ninguém consegue importar? Na entrega 3: um arquivo chamado lib.rs, e por que o compilador está dando uma pista, não um castigo.
O template e o curso
- Template: github.com/HabilMX/estructura-python. Pode ser usado como template do GitHub ou clonado [22]. O README explica cada pasta e quando acrescentar cada coisa. O código é MIT; o texto e as explicações são CC BY-SA 4.0.
- Versões: pede Python 3.12 ou mais novo e foi testado até o 3.14, no macOS e no Linux: com o 3.14.9, o mais recente do 3.14 em 22 de outubro [21], com o 3.12.15 e com o 3.12.3, o do Ubuntu 24.04 [11]. O 3.15 ainda não. O 3.14 tem suporte até outubro de 2030; o 3.12 já só recebe correções de segurança, até outubro de 2028 [20]. Só usa a biblioteca padrão; pytest 9.1.1, ruff 0.17.1 e mypy 2.4.0 vão fixados no grupo de desenvolvimento.
- Curso de Python da Hábil: se
pyproject.toml,python -mou a instalação editável forem novidade, a lição 7 explica tudo do zero: Curso de Python · Lição 7, Um pacote com linha de comando.
Escrevo a partir do que vemos todos os dias na Hábil, onde construímos sistemas para bancos, seguradoras e empresas no México. Se no trabalho ou na faculdade aparecer um repositório em que ninguém sabe onde mexer, vamos conversar: habil.mx
O que a Hábil faz?
Ensinamos a programar com o mesmo que usamos para construir: código testado, explicado e aberto.
Esta série nasce do mesmo lugar que os nossos cursos. O Curso de Python vai do zero até um primeiro programa completo, e o publicamos aberto, com licença Creative Commons; a lição 7 explica o pacote com linha de comando, o pyproject.toml e a instalação editável que o template deste artigo usa. E no catálogo há mais cursos de programação, gratuitos e com código testado e explicado passo a passo.
Veja o Curso de Python e o catálogo de Cursos de programação.
Se a equipe herdar um sistema em que ninguém sabe onde mexer, ou precisar construir um que possa continuar sendo mantido, também fazemos isso: veja Construir um sistema sob medida. Peça a primeira conversa, sem custo. Nela avaliamos se convém configurar o que a equipe já tem, usar um produto ou construir, e o que ela receberia em cada caso. Escreva para nós pelo WhatsApp.
Fontes consultadas em 22 de outubro de 2026. As citações em inglês são reproduzidas tal como estão.
Referências
- Python Packaging Authority, «src layout vs flat layout», Python Packaging User Guide. https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/
- pytest, «Good Integration Practices», docs.pytest.org (pytest 9.1). https://docs.pytest.org/en/stable/explanation/goodpractices.html
- pytest, «How to invoke pytest»: «Calling pytest through python -m pytest», docs.pytest.org. https://docs.pytest.org/en/stable/how-to/usage.html
- pytest, «pytest import mechanisms and sys.path/PYTHONPATH», docs.pytest.org. https://docs.pytest.org/en/stable/explanation/pythonpath.html
- pip, «Local project installs»: «Editable installs», pip.pypa.io. https://pip.pypa.io/en/stable/topics/local-project-installs/
- Hatch, «Build configuration»: «Packages» e «Dev mode», hatch.pypa.io. https://hatch.pypa.io/latest/config/build/
- Hatch, «Wheel builder»: «Default file selection», hatch.pypa.io. https://hatch.pypa.io/latest/plugins/builder/wheel/
- Python, «Command line and environment»: opção
-m, docs.python.org. https://docs.python.org/3/using/cmdline.html - G. Thomas, M. Klose, F. Laíns, D. Stufft, T. Chung, S. Rivera, E. Hashman e P. Gedam, «PEP 668 – Marking Python base environments as “externally managed”», 18 de maio de 2021. https://peps.python.org/pep-0668/
- Linux Mint, «Linux Mint 22.3 Release Notes» («Linux Mint 22.x is based on Ubuntu 24.04»), linuxmint.com. https://www.linuxmint.com/rel_zena.php
- Launchpad (Canonical), pacotes publicados no Ubuntu 24.04 «noble»:
python3-defaults3.12.3 epython-pip24.0. https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=python3-defaults&exact_match=true · https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=python-pip&exact_match=true - Python, «What's New In Python 3.13»: «Improved error messages», docs.python.org. https://docs.python.org/3/whatsnew/3.13.html
- Python Packaging Authority, «Writing your pyproject.toml», Python Packaging User Guide. https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
- Python Packaging Authority, «install_requires vs requirements files», Python Packaging User Guide. https://packaging.python.org/en/latest/discussions/install-requires-vs-requirements/
- Brett Cannon, «PEP 751 – A file format to record Python dependencies for installation reproducibility», 24 de julho de 2024 (aceita em 31 de março de 2025). https://peps.python.org/pep-0751/
- Stephen Rosen, «PEP 735 – Dependency Groups in pyproject.toml», 20 de novembro de 2023 (aceita em 10 de outubro de 2024). https://peps.python.org/pep-0735/
- pip, «Changelog», versão 25.1 (26 de abril de 2025), pip.pypa.io. https://pip.pypa.io/en/stable/news/
- Astral, «Creating projects» (uv), docs.astral.sh. https://docs.astral.sh/uv/concepts/projects/init/
- Python, «The Python Tutorial», 6.1.2 «The Module Search Path», docs.python.org. https://docs.python.org/3/tutorial/modules.html
- Python Developer's Guide, «Status of Python versions». https://devguide.python.org/versions/
- Python Software Foundation, «Python 3.14.9», 21 de outubro de 2026. https://www.python.org/downloads/release/python-3149/
- GitHub Docs, «Creating a template repository». https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository
- GitHub Docs, «Disabling and enabling a workflow». https://docs.github.com/en/actions/how-tos/manage-workflow-runs/disable-and-enable-workflows
- Python, «Using Python on macOS» (§5.1), docs.python.org. https://docs.python.org/3/using/mac.html · Instaladores: https://www.python.org/downloads/macos/
A operação da empresa enfrenta esses desafios?
Prefere e-mail? Escreva para hola@habil.mx