Padrões Python
Este skill é a fonte da verdade para ferramentas Python e regras entre projetos. Os skills de arquitetura, estilo, teste e revisão devem referenciá-lo em vez de repeti-lo.
Para prosa de projeto, carregue também technical-writing. Ele invoca humanizer e é proprietário da localização do documento, timestamps, metadados de revisão, acessibilidade e qualidade de escrita.
Precedência de regras
Aplique as regras nesta ordem:
- Requisitos explícitos do usuário ou organização
- Configuração do repositório e decisões de arquitetura aceitas
- Este skill e os outros skills Python
- PEP 8 e padrões das ferramentas
Não enfraqueça o piso de segurança silenciosamente. Registre uma exceção necessária, seu escopo, risco, proprietário (quando conhecido) e condição de remoção no registro de decisão do projeto.
Runtime e layout
- Alveje Python 3.11 ou mais novo. Respeite um repositório que tenha como alvo uma versão mais nova.
- Use
from __future__ import annotationsquando melhorar a compatibilidade futura ou resolver a ordenação de anotações. Não adicione mecanicamente a arquivos que não precisam dela. - Prefira um layout
src/para novos pacotes distribuíveis. - Mantenha os metadados do projeto e a configuração de ferramentas suportada em
pyproject.toml. - Use
uvpara ambientes, resolução de dependências, travamento e execução de comandos.
Cadeia de ferramentas suportada
| Propósito | Padrão | Uso obrigatório |
|---|---|---|
| Formatação e lint | Ruff | Todos os projetos mantidos |
| Verificação de tipos | mypy strict | Pacotes de produção e APIs públicas |
| Testes e cobertura | pytest, pytest-cov, coverage.py | Todas as alterações de comportamento |
| Lint de segurança | Regras S do Ruff e Bandit | Pacotes de produção |
| SAST | Semgrep com regras do repositório | CI para produtos mantidos |
| Auditoria de dependências | pip-audit | CI e verificações de release |
| Logging estruturado | structlog | Aplicações e serviços |
| Tracing | OpenTelemetry | Serviços em rede e pipelines traceados |
| Gerenciamento de pacotes | uv | Todos os projetos |
| Hooks Git | pre-commit | Repositórios mantidos |
| Entrega de segredos | Infisical por padrão da organização | Cargas de trabalho que usam segredos |
Uma decisão de arquitetura aceita pode selecionar um fornecedor equivalente ou omitir uma ferramenta operacional que não se adequa a uma pequena biblioteca local ou script. Ruff, tipagem, testes e manipulação segura de dependências permanecem a linha de base.
Ferramentas experimentais, incluindo scanners de vulnerabilidade baseados em modelos e revisores de IA, são consultivas. Elas não devem ser portões obrigatórios até que a equipe defina uma versão suportada, comando, política de falha e proprietário.
Política de dependências e versões
- Declare ranges de runtime compatíveis em
pyproject.toml. - Faça commit do
uv.lockpara aplicações e ambientes de desenvolvimento reproduzíveis. O lockfile é proprietário das versões resolvidas exatas. - Para bibliotecas publicadas, declare limites inferiores honestos, teste versões Python suportadas e limites inferiores importantes, e não dependa do lockfile como contrato do consumidor.
- Coloque ferramentas de qualidade e teste em grupos de dependências nomeados.
- Execute comandos de qualidade através do ambiente uv travado. Não mantenha um segundo conjunto de versões de ferramentas Python em pre-commit.
- Atualize intencionalmente com
uv lock --upgrade-package <nome>ou uma atualização completa revisada do lock.
Auditoria canônica de dependências para um projeto uv:
requirements_file="$(mktemp)"
trap 'rm -f "$requirements_file"' EXIT
uv export \
--frozen \
--no-dev \
--no-emit-project \
--no-hashes \
--format requirements.txt \
--output-file "$requirements_file"
uv run --frozen pip-audit \
--strict \
--no-deps \
--requirement "$requirements_file"
A exportação audita dependências de runtime travadas exatas sem pedir ao pip-audit para resolver um segundo grafo. A descoberta de projeto --locked atual do pip-audit suporta pyproject.toml e pylock.*.toml, não uv.lock, então não use pip-audit --locked . como uma auditoria uv.
pip-audit deve estar presente no grupo de dependências de qualidade. Uma isenção de vulnerabilidade deve nomear o advisory, escopo afetado, controle compensatório, proprietário (quando conhecido) e data de expiração ou revisão.
Comandos de qualidade canônicos
Adapte os caminhos dos pacotes ao repositório, mas mantenha uma fonte de comando para uso local e CI:
uv sync --frozen
uv run --frozen ruff check .
uv run --frozen ruff format --check .
uv run --frozen mypy <raizes-do-pacote>
uv run --frozen bandit -c pyproject.toml -r <raizes-do-pacote>
uv run --frozen semgrep scan --config .semgrep.yml <raizes-do-pacote>
uv run --frozen pytest
# Execute a auditoria de dependências canônica com lock exportado acima.
CI registra o comando e o resultado. Uma ferramenta ou configuração ausente é unavailable, não uma aprovação.
Ownership pre-commit
Fixe hooks de higiene não Python por release. Invoque ferramentas Python de qualidade como hooks locais através de uv run --frozen, para que hooks locais e CI usem as versões exatas em uv.lock.
repos:
- repo: local
hooks:
- id: ruff-check
name: ruff check
entry: uv run --frozen ruff check --fix
language: system
types_or: [python, pyi]
- id: ruff-format
name: ruff format
entry: uv run --frozen ruff format
language: system
types_or: [python, pyi]
- id: mypy
name: mypy
entry: uv run --frozen mypy
language: system
pass_filenames: false
args: [<raizes-do-pacote>]
Execute Bandit, Semgrep, testes e auditoria de dependências em CI. Adicione-os ao pre-commit apenas quando sua latência e dependências se adequarem ao repositório.
Decisões mínimas de pyproject.toml
Use nomes e raízes de pacotes do repositório em vez de copiar placeholders.
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "B", "S", "UP", "C4", "SIM", "RUF", "D"]
ignore = ["E501"]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = false
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra --strict-markers --tb=short --import-mode=importlib"
[tool.coverage.run]
branch = true
source_pkgs = ["seu_pacote"]
[tool.coverage.report]
fail_under = 80
show_missing = true
[tool.bandit]
exclude_dirs = ["tests"]
skips = ["B101"]
Documente cada ignore com escopo restrito e motivo. Prefira ignores por arquivo a ignores globais.
Contrato de log estruturado
Aplicativos emitem estes campos. Bibliotecas podem usar a fachada de logging do aplicativo host e não devem configurar handlers globais na importação.
| Campo | Requisito | Significado |
|---|---|---|
timestamp | Sempre | ISO 8601 UTC |
level | Sempre | DEBUG, INFO, WARNING, ERROR ou CRITICAL |
event | Sempre | Nome de evento estável em snake_case |
service | Sempre para aplicativos | Nome do serviço ou aplicativo |
trace_id | Quando existe uma trace | ID de trace OpenTelemetry |
span_id | Quando existe um span | ID de span OpenTelemetry |
error | Em falhas | Tipo de exceção e mensagem seguros |
duration_ms | Em operações medidas | Milissegundos decorridos |
Processadores de nível do structlog comumente recebem nomes de método em minúsculas. Normalize após adicionar o nível:
from typing import Any
import structlog
def uppercase_log_level(
_logger: Any,
_method_name: str,
event_dict: dict[str, Any],
) -> dict[str, Any]:
"""Normalize o nível do log estruturado para o esquema compartilhado."""
level = event_dict.get("level")
if isinstance(level, str):
event_dict["level"] = level.upper()
return event_dict
processors = [
structlog.processors.add_log_level,
uppercase_log_level,
structlog.processors.TimeStamper(fmt="iso", utc=True),
]
Teste o evento final renderizado, não apenas o processador isoladamente.
Piso de segurança
Nunca:
- faça commit ou hardcode credenciais, tokens, chaves privadas ou valores de segredo reais
- armazene segredos reais em
.envou arquivos TOML - registre em log segredos, tokens de acesso, dados pessoais sensíveis ou corpos de requisição sem restrição
- interpole valores externos em SQL
- use
shell=Truecom entrada externa ou variável - desserialize dados pickle não confiáveis
- execute entrada não confiável com
eval,execoucompile - use argumentos padrão mutáveis
- use imports curinga, exceto uma re-exportação pública documentada
- descarte silenciosamente um valor de retorno ou exceção sensível à segurança
- use um
except:puro
Capture Exception apenas em uma fronteira de processo, worker, tarefa ou framework onde o handler registre em log com segurança e então re-lance, mapeie a falha para um status de saída ou retorne um erro de protocolo definido. Capture exceções específicas dentro da lógica da aplicação.
Armazene configurações comuns e referências a segredos em arquivos de configuração. Entregue valores secretos na inicialização através da injeção do Infisical ou um equivalente aprovado. Valide a configuração necessária antes de aceitar trabalho.