- Ruff v0.16.0, ein in Rust geschriebener Python-Linter und -Formatter, erhöht die standardmäßig aktivierten Regeln von 59 auf 413 und erkennt damit ohne separate Konfiguration deutlich mehr Syntaxfehler und sofort auftretende Laufzeitfehler
- Unterstützt die Formatierung von Python-Codeblöcken in Markdown, die etwa mit
python, py, pyi oder pycon gekennzeichnet sind, und kann auch auf Quarto-Notebooks angewendet werden
ruff: ignore und ruff: file-ignore wurden hinzugefügt, um Diagnosen für logische Codezeilen oder ganze Dateien zu unterdrücken; mit --add-ignore lassen sich Kommentare automatisch einfügen
check und format --check zeigen Änderungen standardmäßig als Diff unterhalb der Diagnose an; die Formatter-Prüfung unterstützt außerdem Ausgabeformate für JSON sowie GitHub- und GitLab-CI-Kommentare
- Die meisten können ohne große Änderungen upgraden, sollten aber prüfen, wie sich die erweiterten Standardregeln und Änderungen an der JSON-Ausgabe, bei denen einige Werte
null sein können, auf bestehende Konfigurationen und Automatisierungs-Tools auswirken
Standardregeln auf 413 erweitert
- Ruff v0.16.0 ist ein in Rust geschriebener schneller Python-Linter und -Formatter und kann über PyPI oder mit
uv tool install ruff@latest installiert werden
- Die Gesamtzahl der Ruff-Regeln ist seit v0.1.0 von 708 auf 968 gestiegen, die standardmäßig aktivierten Regeln blieben bislang jedoch bei 59
- v0.16 erweitert die Standardregeln auf 413 und erkennt damit ohne zusätzliche Konfiguration schwerwiegende Probleme, darunter Syntaxfehler und sofort auftretende Laufzeitfehler
- Enthalten sind unter anderem Regeln aus den Kategorien
B von flake8-bugbear, UP von pyupgrade sowie Ruffs eigene Kategorie RUF
- Die vollständige Liste steht in der Dokumentation Default Rules
- Auch Projekte, die bereits
select oder extend-select verwenden, können über die neuen Standardregeln nützliche Regeln entdecken, die ihnen zuvor nicht bekannt waren
- Wer zu den bisherigen Standardregeln zurückkehren möchte, konfiguriert dies wie folgt
[lint]
select = ["E4", "E7", "E9", "F"]
- Diese Änderung hängt mit der langfristigen Aufgabe der Neuklassifizierung von Regeln zusammen; die entsprechenden Arbeiten sollen weitergehen
Formatierung von Markdown-Codeblöcken
ruff format formatiert Python-Fenced-Codeblöcke, die in Markdown-Dateien enthalten sind
- Unterstützte Info-Strings sind
python, py, python3, py3, pyi, pycon
pyi wird als Stub-Dateiformat behandelt
pycon wird als REPL-Sitzungsformat behandelt
- Alle übrigen werden wie normale Python-Dateien formatiert
- Auch wenn der Sprachname wie bei
{python} in geschweifte Klammern gesetzt ist, wird er erkannt, sodass sich dies auch in Quarto-Notebooks verwenden lässt
- Bei Verwendung der Erweiterung
.qmd kann eine extension-Mapping-Konfiguration erforderlich sein
- Innerhalb von Codeblöcken kann die Formatierung teilweise mit
fmt: off und fmt: on unterdrückt werden
- Ganze Bereiche eines Markdown-Dokuments lassen sich mit den HTML-Kommentaren
<!-- fmt: off --> und <!-- fmt: on --> ausschließen
- Um alle Markdown-Dateien auszuschließen, wird in
extend-exclude ein Glob wie *.md angegeben
- Details zum Verhalten stehen in der Dokumentation Markdown code formatting
Neue Kommentare zur Diagnose-Unterdrückung
- Nach der Bereichsunterdrückung mit
ruff: disable und ruff: enable in v0.15 ergänzt v0.16 nun ruff: ignore und ruff: file-ignore
ruff: ignore kann wie noqa Diagnosen in derselben Zeile unterdrücken oder als eigenständiger Kommentar für die gesamte folgende logische Zeile gelten
- Bei mehrzeiligen Funktions-Headern wird der Bereich von
def bis zum Doppelpunkt als eine logische Zeile behandelt
ruff: file-ignore unterdrückt wie ruff: noqa die angegebenen Diagnosen für die gesamte Datei
- Bei jedem Unterdrückungskommentar kann nach dem Regelcode auch der Grund der Anwendung angegeben werden
- Die CLI-Option
--add-ignore fügt die benötigten ruff: ignore-Kommentare automatisch hinzu
- Im Preview-Modus können statt Codes wie
F401 auch Regelnamen wie unused-import verwendet werden
- Die vollständige Spezifikation der Kommentare ist in der Ruff-linter-Dokumentation zusammengefasst
Fix-Diffs und Ausgabeformate
check und format unterstützten bereits zuvor --diff, dies arbeitete jedoch getrennt von normalen Diagnosen und wurde daher nicht zusammen mit Diagnosen angezeigt, die den Grund für Korrekturen zeigen
- Die Standardausgabe
full von v0.16 zeigt mögliche Korrekturen des Linters und Formatters als Diff unterhalb der Diagnose an
format --check kann nun auch alle vom Linter unterstützten Ausgabeformate verwenden
- Es kann maschinenlesbares JSON erzeugen
- Es kann Formate ausgeben, die von GitHub und GitLab in CI als Kommentare gerendert werden
- Unterstützte Formate sind in der CLI-Hilfe und in der Dokumentation Output Format aufgeführt
Kompatibilität und Stabilisierung
- Die Breaking Changes in v0.16 sind überschaubar, sodass die meisten ohne größere Änderungen an Code oder Konfiguration aktualisieren können
- In der JSON-Ausgabe können
filename, location, end_location, fix.edits[].location, fix.edits[].end_location nun null sein, statt standardmäßig leere Strings oder Zeile 1, Spalte 1 zu verwenden
- Aktuell betrifft dies nur sehr wenige Diagnosen, bei künftigen Regeln könnte dies aber häufiger werden
- 12 Regeln wechseln vom Preview- in den stabilen Status
- Airflow-3-Funktionssignatur-Kompatibilität
AIR303, Copyright-Hinweis CPY001, Float-Konvertierung FURB164, sortiertes min/max FURB192
- String-Verkettung in Collection-Literalen
ISC004, Exception-Logging außerhalb eines Exception-Handlers LOG004, ungültiger bool-Rückgabetyp PLE0304
- Zu viele Positionsargumente
PLR0917, Rückgabe von StopIteration PLR1708, Position von None in Union RUF036
- Zugriff auf Annotationen im Klassen-Dictionary
RUF063, doppelte Einträge in __all__ RUF068
- Auch das stabilisierte Verhalten einiger bestehender Regeln wird standardmäßig angewendet
BLE001 wird auch dann unterdrückt, wenn Exceptions mit anderen logging-Methoden als critical, error, exception protokolliert werden
FA102 prüft zusätzliche mit PEP 585 kompatible APIs wie collections.abc
INT001, INT002, INT003 prüfen auch gängige Nutzungsmuster wie die Zuweisung von gettext an builtins._
S310 wertet lokale String-Literal-Bindings aus, um False Positives zu reduzieren
S508 und S509 unterstützen die empfohlenen APIs aktueller PySNMP-Versionen
UP019 erkennt neben typing.Text auch typing_extensions.Text
- Alle Änderungen sind im GitHub-Release einsehbar
1 Kommentare
Hacker-News-Meinungen
Ich habe ein Python-Projekt mit rund 3.000 Zeilen von v0.15.x auf die neue Version aktualisiert; es dauerte nicht lange, und die neue Version fand viele Probleme, die die vorherige übersehen hatte, wodurch auch die Codequalität besser wurde.
Manuelle Korrekturen gemäß Vorschlägen: https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...
Reaktivierung der Zeilenlängen-Regel: https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...
Erzwingen eines
_-Präfixes für ungenutzte Variablen: https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...Automatische Ruff-Korrekturen: https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...
Es ist erfreulich, dass Ruff, ty und uv auch nach der Übernahme von Astral durch OpenAI aktiv weiterentwickelt werden.
uv und Ruff sind großartig, und ich hoffe, dass ty irgendwann dieses Niveau erreicht.
Es ist erstaunlich, wie sehr man sich für Syntax-Polizei-Tools begeistert, die jeweils willkürliche Regeln implementieren und sich nicht einmal darüber einig sind, was guter Python-Code ist.
Sie fassen mehrzeilige Dictionaries zu einer Zeile zusammen und zerstören damit die Absicht von Kommentaren, während sie nur Kleinigkeiten wie zwei Leerzeichen oder doppelte Anführungszeichen korrigieren. Das eigentliche Problem sind nicht Leerzeichen am Zeilenende oder die Sortierung von Imports, sondern schwer verständliche zehnzeilige List Comprehensions, die solche Tools nicht erkennen.
Auf der Arbeit haben wir pylint, flake8, black und Ruff verwendet, wodurch bei jeder Änderung Hunderte Commits entstanden; diese Energie wäre an anderer Stelle besser aufgehoben gewesen.
Wenn man die automatisch ausgeführten Ergebnisse einfach akzeptiert, kann man sich aus Lint-Diskussionen heraushalten; in Organisationen ohne solche Tools musste man aber tatsächlich Zeit darauf verwenden, über Formatierung nachzudenken und zu diskutieren.
In der Teamentwicklung sollte man weniger stark auf persönlichen Vorlieben beharren, mehr auf die Meinungen im Umfeld hören und die Prioritäten von Zusammenarbeit und Handwerkskunst neu abwägen.
Ein Verhalten, das Zeilen trotz Zeilenkommentaren zusammenfasst, wirkt unpassend. Doppelte Anführungszeichen sind in Python einfach eine Stilentscheidung, und wenn in einfachen Anführungszeichen doppelte Anführungszeichen vorkommen, lässt Ruff sie ebenfalls unverändert.
Ich wünschte, es gäbe für Go ein Tool wie Ruff. In vielen Sprachen entstehen hervorragende Tools, aber das Go-Ökosystem ist fragmentiert, und es gibt kein Tool, das sich so ausgereift anfühlt wie Ruff, Oxc, Biome oder Mago.
Es ist relativ neu und daher weniger bekannt, bildet aber die Grundlage von go fix und go vet; offenbar arbeitet das Go-Team daran, dass Modulautoren einfach eigene Analyse-Passes definieren können, die beim Ausführen von go fix automatisch greifen.
Über die Struktur
analysis.Analyzererhält man Zugriff auf AST-, Typ- und SSA-Informationen und kann Informationen zwischen Analysatoren kombinieren; kompiliert man das Ganze zu einem Binary und übergibt es an go fix, kümmert sich die Toolchain sogar um komplexes Caching. Da das Go-Team es selbst gebaut und in die Toolchain aufgenommen hat, ist es sehr wahrscheinlich, dass sich auch Tools wie golangci-lint langfristig in dieses Framework integrieren.Man kann einen AI-Agenten anweisen, einen Go-Analysis-Analyzer zu schreiben und ihn mit go fix auszuführen; auch in meinem Projekt nutze ich das, um mehrere Regeln deterministisch und automatisch durchzusetzen, statt mich auf ungenaue Markdown-Anweisungen zu verlassen.
gofmtfür Python. Ruff ist zwar kein Formatter, sondern ein Linter, aber die jüngste Entwicklungsrichtung des Python-Ökosystems ist erfreulich.Anders als bei Python oder TypeScript, wo offizielle Tools keinen bestimmten Stil erzwingen, ist es in Go schwierig, einen so drastischen Effekt zu erzielen wie beim ersten Einsatz von Ruff oder Biome.
Wenn standardmäßig 413 Regeln aktiviert sind, ist das eine gute Änderung, weil die meisten Projekte nützliches Linting bekommen, ohne an der Konfiguration drehen zu müssen.
Heutzutage kann man zwar einen Agenten damit beauftragen, alle Lint-Warnungen nach festgelegten Kriterien zu beheben, und ihn ein paar Stunden laufen lassen, aber die detaillierten Diagnosen, die Ruff bietet, sind an sich willkommen.
Ruff braucht ebenfalls eine Funktion wie Nix’ stateVersion, die festlegt, welche Defaults gelten sollen. Wenn man Ruff in mehreren Repositories aktualisiert, muss man jedes Mal, wenn neue Standardregeln hinzukommen, diese sofort deaktivieren oder die Verstöße beheben, was die Ergebnisse schwer vorhersagbar macht.
Man könnte auch alle zu aktivierenden Regeln in eine Allowlist schreiben, aber es ist besser, die Konfiguration einfach zu halten und die Statusversion erst dann anzuheben, wenn alle ein paar Stunden investieren können.
pyproject.tomlfestzupinnen. Dann kann jedes Projekt die Version anheben, wenn es bereit ist; man muss nicht mehrere Projekte gleichzeitig koordinieren, und wenn eines zurückbleibt, blockiert das die anderen nicht.https://github.com/astral-sh/ruff/releases/tag/v0.1.0
Im Zeitalter des Agentic Coding ist starkes Linting wichtiger denn je, und ich würde mir Tools wie forbidigo für mehr Sprachen wünschen.
Coding-Agenten verbrauchen ebenfalls viele Tokens, um Kleinigkeiten zu beheben, oder deaktivieren Regeln ganz, wenn Tests fehlschlagen. Der allgemeinen Korrektheit von AI-Ergebnissen vertraue ich inzwischen, aber ihrem Urteilsvermögen bei der Codequalität kann man weiterhin nur schwer trauen.
Obwohl es ganze 413 Regeln gibt, führt man jedes Mal, wenn man zu einer neuen Codebasis stößt, wieder dieselben drei Debatten über die Sortierung von Imports.
Schön zu sehen, dass nun offenbar Nutzung ohne Konfiguration empfohlen wird. In einer neuen
.ruff.tomlreicht dannline-length = 300.