- O linter e formatter de Python Ruff v0.16.0, escrito em Rust, aumentou o número de regras ativadas por padrão de 59 para 413, detectando de forma mais ampla erros de sintaxe e erros de runtime imediatos sem configuração adicional
- Suporta formatação de blocos de código Python em Markdown marcados como
python, py, pyi, pycon etc., e também pode ser aplicado a notebooks Quarto
- Foram adicionados
ruff: ignore e ruff: file-ignore, permitindo suprimir diagnósticos em linhas lógicas de código ou em arquivos inteiros; com --add-ignore, os comentários podem ser inseridos automaticamente
check e format --check exibem as correções como diff abaixo dos diagnósticos por padrão, e a verificação do formatter também passa a oferecer suporte a JSON e a formatos de saída para comentários em CI do GitHub e GitLab
- A maioria dos projetos pode atualizar sem grandes mudanças, mas é preciso verificar o impacto das novas regras padrão e da mudança na saída JSON, em que alguns valores podem se tornar
null, sobre configurações existentes e ferramentas de automação
Regras padrão ampliadas para 413
- Ruff v0.16.0 é um linter e formatter de Python de alta velocidade escrito em Rust, instalável via PyPI ou com
uv tool install ruff@latest
- O conjunto total de regras do Ruff cresceu de 708 na época da v0.1.0 para 968, mas as regras ativadas por padrão permaneceram em 59 até agora
- A v0.16 amplia as regras padrão para 413, detectando sem configuração adicional problemas graves, incluindo erros de sintaxe e erros de runtime imediatos
- Inclui regras das categorias
B do flake8-bugbear, UP do pyupgrade, RUF do próprio Ruff, entre outras
- A lista completa pode ser consultada na documentação de Default Rules
- Projetos que já usam
select ou extend-select também podem descobrir regras úteis que antes desconheciam por meio das novas regras padrão
- Para voltar às regras padrão anteriores, configure da seguinte forma
[lint]
select = ["E4", "E7", "E9", "F"]
- Esta mudança está ligada ao esforço de longo prazo de reclassificação de regras, e o trabalho relacionado continuará
Formatação de blocos de código em Markdown
ruff format formata blocos de código Python cercados por fences incluídos em arquivos Markdown
- As info strings compatíveis são
python, py, python3, py3, pyi e pycon
pyi é tratado como formato de arquivo stub
pycon é tratado como formato de sessão REPL
- Os demais são formatados como arquivos Python comuns
- Também reconhece nomes de linguagem entre chaves, como
{python}, portanto pode ser usado em notebooks Quarto
- Se usar a extensão
.qmd, pode ser necessário configurar o mapeamento de extension
- Dentro de blocos de código, é possível suprimir parte da formatação com
fmt: off e fmt: on
- Áreas inteiras de documentos Markdown podem ser excluídas com comentários HTML
<!-- fmt: off --> e <!-- fmt: on -->
- Para excluir todos os arquivos Markdown, especifique um glob como
*.md em extend-exclude
- O comportamento detalhado pode ser consultado na documentação de formatação de código em Markdown
Novos comentários de supressão de diagnósticos
- Após as supressões por escopo
ruff: disable e ruff: enable da v0.15, a v0.16 adiciona ruff: ignore e ruff: file-ignore
ruff: ignore suprime diagnósticos na mesma linha, como noqa, ou pode ser escrito como comentário independente para se aplicar à próxima linha lógica inteira
- Em cabeçalhos de função escritos em várias linhas, do
def até os dois-pontos é tratado como uma única linha lógica
ruff: file-ignore, como ruff: noqa, suprime diagnósticos especificados no arquivo inteiro
- Em cada comentário de supressão, é possível escrever o motivo da aplicação após o código da regra
- A opção de CLI
--add-ignore adiciona automaticamente os comentários ruff: ignore necessários
- No modo preview, também é possível usar nomes de regras, como
unused-import, em vez de códigos como F401
- A especificação completa dos comentários está organizada na documentação do linter do Ruff
Diffs de correção e formatos de saída
check e format já davam suporte a --diff, mas isso funcionava separadamente dos diagnósticos comuns e não era exibido junto com o diagnóstico que explicava o motivo da correção
- A saída
full padrão da v0.16 exibe as possíveis correções do linter e do formatter como diff abaixo dos diagnósticos
format --check também pode usar todos os formatos de saída suportados pelo linter
- Pode gerar JSON legível por máquina
- Pode produzir formatos que GitHub e GitLab renderizam como comentários no CI
- Os formatos compatíveis podem ser consultados na ajuda da CLI e na documentação de formatos de saída
Compatibilidade e estabilização
- As breaking changes da v0.16 são poucas, então a maioria dos projetos pode atualizar sem mudar significativamente o código ou a configuração
- Na saída JSON,
filename, location, end_location, fix.edits[].location e fix.edits[].end_location podem ser null, em vez de usar string vazia ou linha 1, coluna 1 como valores padrão
- Atualmente, pouquíssimos diagnósticos são afetados, mas isso pode se tornar mais comum em regras futuras
- 12 regras passaram de preview para estáveis
- Compatibilidade de assinatura de funções do Airflow 3
AIR303, aviso de copyright CPY001, conversão de float FURB164, min/max ordenados FURB192
- Concatenação de strings em literais de coleção
ISC004, logging de exceções fora de handlers de exceção LOG004, tipo de retorno bool incorreto PLE0304
- Excesso de argumentos posicionais
PLR0917, retorno de StopIteration PLR1708, posição de None em Union RUF036
- Acesso a annotations no dicionário da classe
RUF063, itens duplicados em __all__ RUF068
- Alguns comportamentos estabilizados de regras existentes também passam a ser aplicados por padrão
BLE001 também é suprimida ao registrar exceções com métodos de logging diferentes de critical, error e exception
FA102 verifica APIs compatíveis com PEP 585 adicionais, como collections.abc
INT001, INT002 e INT003 também verificam usos comuns, como atribuir gettext a builtins._
S310 interpreta bindings locais de literais de string para reduzir falsos positivos
S508 e S509 oferecem suporte às APIs recomendadas do PySNMP mais recente
UP019 reconhece não apenas typing.Text, mas também typing_extensions.Text
- As mudanças completas podem ser consultadas no release do GitHub
1 comentários
Opiniões do Hacker News
Atualizei um projeto Python de cerca de 3 mil linhas da versão v0.15.x para a nova versão, não levou muito tempo, e ela encontrou vários problemas que a versão anterior deixava passar, melhorando também a qualidade do código
Correções manuais conforme as sugestões: https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...
Reativação da regra de comprimento de linha: https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...
Exigência do prefixo
_em variáveis não usadas: https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...Correções automáticas do Ruff: https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...
É bom ver que, mesmo depois da aquisição da Astral pela OpenAI, Ruff, ty e uv continuam sendo desenvolvidos ativamente
uv e Ruff são excelentes, e espero que o ty um dia chegue a esse nível
É surpreendente ver tanto entusiasmo por ferramentas de polícia sintática que implementam regras arbitrárias diferentes entre si e nem sequer chegam a um consenso sobre o que é bom código Python
Elas juntam dicionários de várias linhas em uma só, estragando a intenção dos comentários, e só corrigem detalhes triviais de formatação, como dois espaços ou aspas duplas. O problema real não é espaço no fim da linha nem ordenação de imports, mas uma list comprehension de 10 linhas difícil de interpretar, e essas ferramentas não pegam isso
No trabalho, usando pylint, flake8, black e Ruff, cada alteração gerava centenas de commits, e teria sido melhor gastar essa energia em outro lugar
Se você simplesmente aceita o resultado da execução automática, pode sair das discussões de lint; mas, em organizações sem essas ferramentas, era necessário gastar tempo real pensando e debatendo formatação
Em desenvolvimento em equipe, em vez de impor preferências pessoais com força, é preciso ouvir as opiniões ao redor e reavaliar as prioridades entre colaboração e artesanato
O comportamento de juntar linhas quando há comentários de linha parece inadequado. Aspas duplas em Python são apenas uma escolha de estilo, e, se houver aspas duplas dentro de aspas simples, o Ruff também deixa como está
Seria bom se Go tivesse uma ferramenta como o Ruff. Surgem ótimas ferramentas em várias linguagens, mas o ecossistema Go é fragmentado, e não há nenhuma ferramenta que pareça tão bem-acabada quanto Ruff, Oxc, Biome e Mago
Ele é relativamente novo e menos conhecido, mas é a base do go fix e do go vet, e parece que a equipe do Go está trabalhando para que autores de módulos consigam definir facilmente passes de análise personalizados que funcionem automaticamente ao executar go fix
Com a struct
analysis.Analyzer, é possível acessar informações de AST, tipos e SSA e combinar informações entre analisadores; ao compilar para um binário e passá-lo ao go fix, a cadeia de ferramentas lida até com o caching complexo. Como foi criado diretamente pela equipe do Go e incluído na toolchain, é bem provável que ferramentas como golangci-lint também acabem se integrando a esse framework no longo prazoVocê pode pedir a um agente de IA para escrever um analisador Go Analysis e executá-lo via go fix; nos meus projetos, também estou usando isso para impor automaticamente, de forma determinística, várias regras em vez de depender de instruções imprecisas em Markdown
gofmtpara Python. O Ruff é um linter, não um formatter, mas é animador ver a direção recente do ecossistema PythonAo contrário de Python ou TypeScript, em que as ferramentas oficiais não impõem um estilo específico, em Go é difícil obter o mesmo efeito dramático de quando se começa a usar Ruff ou Biome
Ativar 413 regras por padrão é uma boa mudança, pois a maioria dos projetos pode receber lint útil sem mexer na configuração
Hoje em dia, talvez dê para encarregar um agente de corrigir todos os avisos de lint conforme um critério definido e deixá-lo por algumas horas, mas o diagnóstico detalhado que o Ruff oferece em si é bem-vindo
O Ruff também precisa de algo como o stateVersion do Nix, que determine o conjunto de padrões a ser aplicado. Ao atualizar o Ruff em vários repositórios, sempre que uma nova regra padrão é adicionada é preciso desativá-la imediatamente ou corrigir as violações, tornando o resultado difícil de prever
Também daria para listar em uma allowlist todas as regras a ativar, mas é melhor manter a configuração simples e só aumentar a versão de estado quando todos puderem investir algumas horas
pyproject.tomlpara cada projeto. Assim, cada projeto sobe a versão quando estiver pronto, sem precisar coordenar vários projetos ao mesmo tempo, e se um ficar para trás os demais não ficam bloqueadoshttps://github.com/astral-sh/ruff/releases/tag/v0.1.0
Na era da codificação por agentes, linting forte é mais importante do que nunca, e seria bom ver ferramentas como forbidigo em mais linguagens
Agentes de codificação também gastam muitos tokens corrigindo problemas triviais ou, quando os testes falham, às vezes simplesmente desativam tudo. Passei a confiar na precisão geral dos resultados da IA, mas ainda é difícil confiar em seu julgamento sobre qualidade de código
Mesmo com 413 regras, toda vez que entro em uma nova codebase acabo repetindo as mesmas três discussões sobre ordenação de imports
Fico feliz que agora pareça recomendado usar sem configuração. No novo
.ruff.toml, basta deixarline-length = 300