1 pontos por GN⁺ 1 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • 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

 
GN⁺ 1 시간 전
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

    • Eu estava animado com o ty, mas ele ficou muito atrás do basedpyright, então acabei parando de usá-lo. Mais do que a falta de verificações, os falsos positivos eram fatais, e também não havia o recurso de baseline, que é muito útil em bases de código grandes
      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

    • O objetivo dessas ferramentas é permitir que você foque nos problemas reais. Ao automatizar decisões de lint, não é preciso desperdiçar raciocínio discutindo formatação em PRs
      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
    • A aversão à ideia de que linters desperdiçam tempo parece ter passado do ponto razoável. Na prática, há bastante evidência de que eles economizam tempo; no fim, a questão central é só que linters às vezes fazem mudanças de que você não gosta
      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 Ruff reconhece comentários no fim da linha, mantém cada item em uma linha separada e só adiciona vírgulas finais e espaços. Se houver uma vírgula final, ele também não junta as linhas; o resultado apresentado parece ter vindo do Black
      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á
    • Essas ferramentas, na verdade, economizam a energia da equipe. Sem elas, cada desenvolvedor tem critérios diferentes de formatação, qualidade de código e legibilidade, o que leva a discussões sem fim; é melhor deixar isso com o Ruff
    • Isso foi juntado em uma linha porque faltou uma vírgula depois do último item. Pelo menos no Black, se você mantiver a vírgula final, os itens não são comprimidos, mas ele quebra o formato que eu pretendia com frequência, então não o conecto mais ao meu código
  • 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

    • Go tem um Go Analysis Framework melhor: https://pkg.go.dev/golang.org/x/tools/go/analysis
      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 prazo
      Você 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
    • Até pouco tempo atrás, o clima era exatamente o oposto: a comunidade Python sofria com a falta de ferramentas, e todos queriam um gofmt para Python. O Ruff é um linter, não um formatter, mas é animador ver a direção recente do ecossistema Python
    • Não entendo muito bem a afirmação de que o ecossistema Go é fragmentado. Go tem ferramentas oficiais de formatação e linting, e a própria linguagem é deliberadamente restrita para que, mesmo escrita por iniciantes, o código tenha uma forma consistente
      Ao 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
    • Go tem um dos melhores ecossistemas de ferramentas de linguagem para usar sem uma IDE enorme, e o golangci-lint também é bastante abrangente. A própria distribuição do Go já resolve muita coisa
    • O golangci-lint existe há muito tempo e é amplamente usado
  • Ativar 413 regras por padrão é uma boa mudança, pois a maioria dos projetos pode receber lint útil sem mexer na configuração

    • Fica a dúvida se despejar de repente 413 possíveis avisos em projetos existentes é realmente útil; parece mais adequado para projetos novos
      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

    • Uma abordagem mais adequada é fixar a versão desejada do Ruff em pyproject.toml para 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 bloqueados
    • Segundo o texto original, o conjunto de regras padrão do Ruff não mudava havia mais de 2 anos, e a última alteração tinha sido na v0.1.0
      https://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

    • Estou atualizando os projetos, mas fico com sentimentos mistos. Quando eu escrevia o código diretamente, julgava pela intuição quando pular ou ignorar regras; em projetos com a maioria das regras do pylint ativadas, porém, o código acabou ficando mais difícil de ler por causa de gambiarras para satisfazer o pylint
      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 deixar line-length = 300