1 points par GN⁺ 1 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Ruff v0.16.0, le linter et formateur Python écrit en Rust, porte le nombre de règles activées par défaut de 59 à 413, afin de détecter plus largement, sans configuration particulière, les erreurs de syntaxe et les erreurs d’exécution immédiates
  • Prend en charge le formatage des blocs de code Python signalés en Markdown par python, py, pyi, pycon, etc., avec une application possible aux notebooks Quarto
  • Ajout de ruff: ignore et ruff: file-ignore, qui permettent de supprimer les diagnostics sur une ligne logique de code ou sur tout un fichier ; --add-ignore peut insérer automatiquement les commentaires
  • check et format --check affichent les corrections sous forme de diff sous les diagnostics par défaut, et la vérification du formateur prend aussi en charge JSON ainsi que les formats de sortie pour les annotations CI GitHub et GitLab
  • La plupart des projets peuvent mettre à jour sans gros changement, mais il faut vérifier l’impact des règles par défaut plus nombreuses et des changements de sortie JSON, où certaines valeurs peuvent devenir null, sur les configurations et outils d’automatisation existants

Les règles par défaut passent à 413

  • Ruff v0.16.0 est un linter et formateur Python rapide écrit en Rust, installable depuis PyPI ou via uv tool install ruff@latest
  • L’ensemble des règles de Ruff est passé de 708 à l’époque de la v0.1.0 à 968, mais les règles activées par défaut étaient jusque-là restées au nombre de 59
  • La v0.16 étend les règles par défaut à 413, afin de détecter sans configuration particulière les problèmes graves, notamment les erreurs de syntaxe et les erreurs d’exécution immédiates
    • Sont notamment incluses les règles B de flake8-bugbear, UP de pyupgrade et la catégorie RUF propre à Ruff
    • La liste complète est disponible dans la documentation Default Rules
  • Les projets qui utilisent déjà select ou extend-select peuvent aussi découvrir, via les nouvelles règles par défaut, des règles utiles qu’ils ne connaissaient pas auparavant
  • Pour revenir aux anciennes règles par défaut, configurez comme suit
[lint]
select = ["E4", "E7", "E9", "F"]
  • Ce changement est lié au chantier de long terme de reclassification des règles, et les travaux associés se poursuivront

Formatage des blocs de code Markdown

  • ruff format formate les blocs de code fenced Python inclus dans les fichiers Markdown
  • Les chaînes d’information prises en charge sont python, py, python3, py3, pyi et pycon
    • pyi est traité comme un format de fichier stub
    • pycon est traité comme un format de session REPL
    • Les autres sont formatés comme des fichiers Python ordinaires
  • Les noms de langage entourés d’accolades, comme {python}, sont également reconnus, ce qui permet l’utilisation avec les notebooks Quarto
    • Si vous utilisez l’extension .qmd, une configuration de mapping extension peut être nécessaire
  • À l’intérieur d’un bloc de code, il est possible de désactiver une partie du formatage avec fmt: off et fmt: on
  • Toute une zone d’un document Markdown peut être exclue avec les commentaires HTML <!-- fmt: off --> et <!-- fmt: on -->
  • Pour exclure tous les fichiers Markdown, indiquez un glob comme *.md dans extend-exclude
  • Le comportement détaillé est décrit dans la documentation sur le formatage du code Markdown

Nouveaux commentaires de suppression de diagnostics

  • Après les suppressions de portée ruff: disable et ruff: enable de la v0.15, la v0.16 ajoute ruff: ignore et ruff: file-ignore
  • ruff: ignore supprime, comme noqa, les diagnostics de la même ligne, ou peut être écrit comme commentaire indépendant pour s’appliquer à toute la ligne logique suivante
    • Dans un en-tête de fonction sur plusieurs lignes, la portion allant de def jusqu’aux deux-points est considérée comme une seule ligne logique
  • ruff: file-ignore supprime les diagnostics indiqués dans tout le fichier, comme ruff: noqa
  • Chaque commentaire de suppression peut inclure une raison d’application après le code de règle
  • L’option CLI --add-ignore ajoute automatiquement les commentaires ruff: ignore nécessaires
  • En mode preview, il est aussi possible d’utiliser des noms de règles, comme unused-import, plutôt que des codes comme F401
  • La spécification complète des commentaires est disponible dans la documentation du linter Ruff

Diff des corrections et formats de sortie

  • check et format prenaient déjà en charge --diff, mais cela fonctionnait séparément des diagnostics ordinaires et ne s’affichait pas avec les diagnostics expliquant la raison des corrections
  • La sortie full par défaut de la v0.16 affiche les corrections possibles du linter et du formateur sous forme de diff sous les diagnostics
  • format --check peut également utiliser l’ensemble des formats de sortie pris en charge par le linter
    • Il peut générer du JSON lisible par machine
    • Il peut produire des formats que GitHub et GitLab affichent sous forme d’annotations en CI
  • Les formats pris en charge sont indiqués dans l’aide CLI et dans la documentation des formats de sortie

Compatibilité et stabilisation

  • Les breaking changes de la v0.16 sont peu nombreux, si bien que la plupart des projets peuvent mettre à jour sans modifier fortement leur code ou leur configuration
  • Dans la sortie JSON, filename, location, end_location, fix.edits[].location et fix.edits[].end_location peuvent désormais être null au lieu d’utiliser une chaîne vide ou la ligne 1, colonne 1 comme valeur par défaut
    • Très peu de diagnostics sont actuellement concernés, mais cela pourrait devenir plus fréquent dans de futures règles
  • 12 règles passent du mode preview à l’état stable
    • Compatibilité des signatures de fonctions Airflow 3 AIR303, avis de copyright CPY001, conversion en float FURB164, min/max triés FURB192
    • Concaténation de chaînes dans les littéraux de collection ISC004, journalisation d’exceptions hors d’un gestionnaire d’exceptions LOG004, type de retour booléen incorrect PLE0304
    • Trop d’arguments positionnels PLR0917, retour de StopIteration PLR1708, position de None dans une union RUF036
    • Accès aux annotations dans le dictionnaire de classe RUF063, éléments dupliqués dans __all__ RUF068
  • Certains comportements stabilisés de règles existantes s’appliquent aussi par défaut
    • BLE001 est supprimée même lorsque les exceptions sont journalisées avec des méthodes logging autres que critical, error ou exception
    • FA102 vérifie des API supplémentaires compatibles PEP 585, comme collections.abc
    • INT001, INT002 et INT003 vérifient aussi les usages courants, comme l’assignation de gettext à builtins._
    • S310 interprète les bindings locaux de littéraux de chaîne afin de réduire les faux positifs
    • S508 et S509 prennent en charge les API recommandées de la version récente de PySNMP
    • UP019 reconnaît non seulement typing.Text, mais aussi typing_extensions.Text
  • L’ensemble des changements est disponible dans la release GitHub

1 commentaires

 
GN⁺ 1 시간 전
Avis Hacker News
  • J’ai fait passer un projet Python d’environ 3 000 lignes de la v0.15.x à la nouvelle version ; cela n’a pas pris longtemps, et elle a détecté de nombreux problèmes que la version précédente manquait, ce qui a aussi amélioré la qualité du code
    Corrections manuelles suivant les suggestions : https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...
    Réactivation de la règle de longueur de ligne : https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...
    Préfixe _ imposé pour les variables inutilisées : https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...
    Correction automatique par Ruff : https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...

  • Heureux de voir que Ruff, ty et uv restent activement développés même après le rachat d’Astral par OpenAI

    • J’attendais beaucoup de ty, mais il était très en retrait par rapport à basedpyright, donc j’ai fini par arrêter de l’utiliser. Plus que le manque de vérifications, c’étaient les faux positifs qui étaient rédhibitoires, et il n’y avait pas non plus de fonction de baselining très utile pour les grosses codebases
      uv et Ruff sont excellents, et j’espère que ty atteindra ce niveau un jour
  • Je suis surpris de voir un tel enthousiasme pour des outils de police de la syntaxe qui implémentent chacun des règles arbitraires sans même parvenir à s’accorder sur ce qu’est un bon code Python
    Ils fusionnent des dictionnaires multilignes sur une seule ligne en ruinant l’intention des commentaires, et ne corrigent que des détails de forme mineurs comme deux espaces ou des guillemets doubles. Le vrai problème, ce n’est pas les espaces en fin de ligne ni le tri des imports, mais les compréhensions de liste de 10 lignes impossibles à lire, et ces outils ne les détectent pas
    Au travail, on utilisait pylint, flake8, black et Ruff, et cela produisait des centaines de commits à chaque changement ; on aurait mieux fait d’employer cette énergie ailleurs

    • Le but de ces outils est justement de permettre de se concentrer sur les vrais problèmes. En automatisant les décisions de lint, on évite de gaspiller de l’attention dans les PR à débattre de la mise en forme
      Si on accepte simplement le résultat automatique, on peut se retirer des discussions sur le lint, alors que dans les organisations sans ce type d’outils il fallait réellement passer du temps à réfléchir et débattre de la forme
    • L’hostilité envers les linters comme perte de temps semble dépasser ce qui est raisonnable. En pratique, il y a au contraire suffisamment d’éléments pour dire qu’ils font gagner du temps ; au fond, le principal reproche est juste que le linter fait parfois des changements qu’on n’aime pas
      Dans un travail d’équipe, il faut peut-être moins chercher à imposer fortement ses préférences personnelles, et davantage écouter les autres ainsi que reconsidérer les priorités entre collaboration et artisanat
    • Ruff reconnaît les commentaires de fin de ligne, garde donc chaque élément sur une ligne séparée, et n’ajoute que la virgule finale et les espaces. S’il y a une virgule finale, il ne fusionne pas non plus les lignes, et le résultat montré semble venir de Black
      Fusionner des lignes en présence de commentaires de ligne paraît inapproprié. Les guillemets doubles sont en Python un simple choix de style, et Ruff les laisse aussi tels quels s’il y a des guillemets doubles à l’intérieur de guillemets simples
    • Ces outils permettent au contraire d’économiser l’énergie de l’équipe. Sans eux, chaque développeur a ses propres critères pour le format, la qualité du code et la lisibilité, ce qui mène à des discussions sans fin ; mieux vaut donc laisser Ruff trancher
    • Si cela a été fusionné en une seule ligne, c’est parce qu’il manquait une virgule après le dernier élément. Du moins avec Black, si on garde la virgule finale, les éléments ne sont pas compressés, mais comme il casse souvent la mise en forme voulue, je ne le branche plus à mon code
  • J’aimerais qu’il existe un outil comme Ruff pour Go. On voit d’excellents outils dans plusieurs langages, mais l’écosystème Go est fragmenté et il n’y a rien qui me semble aussi abouti que Ruff, Oxc, Biome ou Mago

    • Go dispose d’un meilleur Go Analysis Framework : https://pkg.go.dev/golang.org/x/tools/go/analysis
      C’est relativement récent donc moins connu, mais c’est la base de go fix et go vet, et l’équipe Go semble travailler à permettre aux auteurs de modules de définir facilement des passes d’analyse personnalisées qui s’exécuteront automatiquement lors d’un go fix
      La structure analysis.Analyzer donne accès à l’AST, aux types et aux informations SSA, et permet de combiner les informations entre analyseurs ; il suffit de compiler cela en binaire et de le passer à go fix, la toolchain gérant toute la mise en cache complexe. Comme cela a été conçu directement par l’équipe Go et intégré à la toolchain, il y a de fortes chances que des outils comme golangci-lint convergent à long terme vers ce framework
      On peut demander à un agent IA d’écrire un analyseur Go Analysis et de l’exécuter avec go fix ; c’est aussi ce que j’utilise dans mon projet pour appliquer automatiquement et de manière déterministe plusieurs règles, au lieu de consignes Markdown imprécises
    • Jusqu’à récemment, l’ambiance était exactement inverse : la communauté Python souffrait du manque d’outils et tout le monde voulait un gofmt pour Python. Ruff n’est pas un formateur mais un linter, mais l’orientation récente de l’écosystème Python est réjouissante
    • Je ne comprends pas bien l’idée que l’écosystème Go serait fragmenté. Go a des outils officiels de formatage et de lint, et le langage lui-même est délibérément limité pour produire une forme cohérente même chez les débutants
      Contrairement à Python ou TypeScript, où les outils officiels n’imposent pas un style précis, il est difficile d’obtenir avec Go un effet aussi spectaculaire que lors d’une première utilisation de Ruff ou Biome
    • Go possède l’un des meilleurs écosystèmes d’outillage de langage utilisables sans énorme IDE, et golangci-lint est aussi assez complet. La distribution Go elle-même résout déjà une grande partie du problème
    • golangci-lint existe depuis longtemps et est largement utilisé
  • Activer 413 règles par défaut est une bonne évolution : la plupart des projets peuvent ainsi bénéficier d’un linting utile sans toucher à la configuration

    • On peut toutefois se demander si voir soudainement apparaître 413 avertissements potentiels dans un projet existant est vraiment utile ; cela semble mieux convenir aux nouveaux projets
      De nos jours, on peut sans doute demander à un agent de corriger tous les avertissements de lint selon des critères définis et laisser tourner quelques heures, mais le niveau de diagnostic granulaire fourni par Ruff reste bienvenu
  • Ruff aurait aussi besoin d’un mécanisme comparable au stateVersion de Nix pour décider de l’ensemble de valeurs par défaut à appliquer. Quand on met à jour Ruff dans plusieurs dépôts, il devient difficile de prévoir le résultat, car il faut soit désactiver immédiatement les nouvelles règles par défaut, soit corriger les violations
    On peut aussi inscrire en liste blanche toutes les règles à activer, mais il vaut mieux garder une configuration simple et ne relever que la version d’état quand tout le monde peut y consacrer quelques heures

    • Il serait plus approprié de figer la version de Ruff souhaitée dans le pyproject.toml de chaque projet. Chaque projet peut alors monter de version quand il est prêt, sans devoir coordonner plusieurs projets en même temps, et le retard de l’un ne bloque pas les autres
    • D’après le texte original, l’ensemble de règles par défaut de Ruff n’a pas changé depuis plus de deux ans, et la dernière modification remonte à la v0.1.0
      https://github.com/astral-sh/ruff/releases/tag/v0.1.0
  • À l’ère du codage par agents, un linting rigoureux est plus important que jamais, et j’aimerais voir des outils comme forbidigo dans davantage de langages

    • Je mets mes projets à niveau, mais avec des sentiments mitigés. Quand j’écrivais moi-même le code, je savais d’instinct quand contourner ou ignorer une règle ; mais dans des projets où la plupart des règles pylint sont activées, le code est au contraire devenu plus difficile à lire à cause d’astuces destinées uniquement à satisfaire pylint
      Les agents de codage dépensent eux aussi beaucoup de tokens pour corriger des problèmes mineurs ou désactivent carrément quelque chose quand les tests échouent. Je fais désormais confiance à la précision globale des résultats de l’IA, mais il reste difficile de faire confiance à son jugement sur la qualité du code
  • Même avec 413 règles, on continue à répéter les mêmes trois débats sur le tri des imports à chaque arrivée sur une nouvelle base de code

  • Je suis content de voir que l’utilisation sans configuration semble désormais recommandée. Dans un nouveau .ruff.toml, il suffit de ne mettre que line-length = 300