- 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
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
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
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
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
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
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
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.Analyzerdonne 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 frameworkOn 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
gofmtpour Python. Ruff n’est pas un formateur mais un linter, mais l’orientation récente de l’écosystème Python est réjouissanteContrairement à 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
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
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
pyproject.tomlde 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 autreshttps://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
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 queline-length = 300