refactor: replace black, isort and pylint with ruff - #1120
Conversation
Merges the linting and formatting dependency groups into a single ruff-only `linting` group, translates [tool.black]/[tool.isort]/ .pylintrc into [tool.ruff]/[tool.ruff.lint]/[tool.ruff.format], rewrites .pre-commit-config.yaml and the linting CI job, and auto-fixes/formats the codebase accordingly. Two pre-existing mixedCase public field names (zaehlertypSpezifikation, anzahlAblesungen) are left as-is with a scoped noqa since renaming a public BO4E field would be a breaking API change, not a tooling swap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Migrates the repository’s Python formatting/linting toolchain from black/isort/pylint to ruff, updates automation (pre-commit + CI) accordingly, and applies ruff-driven autofixes/formatting plus typing modernizations across the codebase.
Changes:
- Replace black/isort/pylint configuration and usage with ruff in
pyproject.toml, pre-commit, and GitHub Actions. - Update lockfile/dependency groups to remove black/isort/pylint and add ruff.
- Apply broad mechanical code updates (formatting +
Optional[T]→T | None) and update docs to reference ruff.
Reviewed changes
Copilot reviewed 107 out of 108 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Removes black/isort/pylint-related packages/groups; adds ruff to dev/linting groups. |
| tests/test_geschaeftspartner.py | Formatting-only changes to match new formatter output. |
| tests/serialization_helper.py | Formatting-only changes to assertions/strings. |
| src/bo4e/zusatzattribut.py | Typing modernization (Optional → ` |
| src/bo4e/com/zustaendigkeit.py | Typing modernization (Optional → ` |
| src/bo4e/com/zeitvariablepreisposition.py | Typing modernization for selected fields. |
| src/bo4e/com/zeitreihenwert.py | Typing modernization for wert. |
| src/bo4e/com/zeitraum.py | Typing modernization and import cleanup (now has an empty TYPE_CHECKING block). |
| src/bo4e/com/zahlungsinformation.py | Typing modernization (Optional → ` |
| src/bo4e/com/zaehlzeittagtyp.py | Typing modernization for optional list field. |
| src/bo4e/com/zaehlzeitsaison.py | Typing modernization (Optional → ` |
| src/bo4e/com/zaehlzeitregister.py | Typing modernization (Optional → ` |
| src/bo4e/com/zaehlwerk.py | Typing modernization + scoped noqa for pre-existing public mixedCase field. |
| src/bo4e/com/vorauszahlung.py | Typing modernization (Optional → ` |
| src/bo4e/com/verwendungszweckpromarktrolle.py | Typing modernization for optional list field. |
| src/bo4e/com/vertragsteil.py | Typing modernization (Optional → ` |
| src/bo4e/com/vertragskonditionen.py | Typing modernization (Optional → ` |
| src/bo4e/com/unterschrift.py | Typing modernization (Optional → ` |
| src/bo4e/com/umschaltzeit.py | Typing modernization (Optional → ` |
| src/bo4e/com/tarifpreiszeitscheibe.py | Typing modernization for several optional list fields. |
| src/bo4e/com/tarifpreisposition.py | Typing modernization for optional list field. |
| src/bo4e/com/tarifpreis.py | Typing modernization for beschreibung. |
| src/bo4e/com/tarifeinschraenkung.py | Typing modernization for several optional list fields. |
| src/bo4e/com/tarifberechnungsparameter.py | Typing modernization for several fields and optional list field. |
| src/bo4e/com/tagesparameter.py | Typing modernization (Optional → ` |
| src/bo4e/com/steuerbetrag.py | Typing modernization (Optional → ` |
| src/bo4e/com/standorteigenschaftenstrom.py | Typing modernization (Optional → ` |
| src/bo4e/com/standorteigenschaftengas.py | Typing modernization for optional list fields and import cleanup. |
| src/bo4e/com/sigmoidparameter.py | Typing modernization (Optional → ` |
| src/bo4e/com/relativepreisposition.py | Typing modernization (Optional → ` |
| src/bo4e/com/regionspreis.py | Typing modernization for optional list fields and import cleanup. |
| src/bo4e/com/regionsoperation.py | Typing modernization (Optional → ` |
| src/bo4e/com/rechnungsposition.py | Typing modernization (Optional → ` |
| src/bo4e/com/preisstaffel.py | Typing modernization (Optional → ` |
| src/bo4e/com/preisposition.py | Typing modernization and minor docstring formatting cleanup. |
| src/bo4e/com/preisgarantie.py | Typing modernization for beschreibung. |
| src/bo4e/com/preis.py | Typing modernization for wert. |
| src/bo4e/com/messwert.py | Typing modernization (Optional → ` |
| src/bo4e/com/menge.py | Typing modernization for wert. |
| src/bo4e/com/marktgebietinfo.py | Typing modernization (Optional → ` |
| src/bo4e/com/lastvariablepreisposition.py | Typing modernization for bezeichnung and optional list field. |
| src/bo4e/com/lastprofil.py | Typing modernization + formatter-driven line wrapping changes. |
| src/bo4e/com/kostenposition.py | Typing modernization (Optional → ` |
| src/bo4e/com/kostenblock.py | Typing modernization for optional list field. |
| src/bo4e/com/konzessionsabgabe.py | Typing modernization (Optional → ` |
| src/bo4e/com/kontaktweg.py | Typing modernization (Optional → ` |
| src/bo4e/com/konfigurationsprodukt.py | Typing modernization for several fields. |
| src/bo4e/com/katasteradresse.py | Typing modernization and import cleanup. |
| src/bo4e/com/geokoordinaten.py | Typing modernization and import cleanup. |
| src/bo4e/com/fremdkostenposition.py | Typing modernization + formatter-driven line wrapping changes. |
| src/bo4e/com/fremdkostenblock.py | Typing modernization for optional list field. |
| src/bo4e/com/energiemix.py | Typing modernization for many fields. |
| src/bo4e/com/energieherkunft.py | Typing modernization for anteil_prozent. |
| src/bo4e/com/einheitspreisposition.py | Typing modernization for bezeichnung. |
| src/bo4e/com/dienstleistung.py | Typing modernization for bezeichnung. |
| src/bo4e/com/com.py | Typing modernization for base fields and a TypeVar bound tweak. |
| src/bo4e/com/betrag.py | Typing modernization for wert. |
| src/bo4e/com/ausschreibungslos.py | Typing modernization for many fields. |
| src/bo4e/com/ausschreibungsdetail.py | Typing modernization for many fields. |
| src/bo4e/com/aufabschlag.py | Typing modernization for several fields. |
| src/bo4e/com/angebotsvariante.py | Typing modernization for datetime/list fields. |
| src/bo4e/com/angebotsteil.py | Typing modernization for list fields. |
| src/bo4e/com/angebotsposition.py | Typing modernization for positionsbezeichnung. |
| src/bo4e/com/adresse.py | Typing modernization for address string fields. |
| src/bo4e/bo/zeitreihe.py | Typing modernization for several fields. |
| src/bo4e/bo/zaehlzeitdefinition.py | Typing modernization for fields/lists. |
| src/bo4e/bo/zaehler.py | Typing modernization + scoped noqa for pre-existing public mixedCase field. |
| src/bo4e/bo/vertrag.py | Typing modernization for several fields/lists. |
| src/bo4e/bo/technischeressource.py | Typing modernization for IDs/list fields/flags. |
| src/bo4e/bo/tarifpreisblatt.py | Typing modernization for datetime/list fields. |
| src/bo4e/bo/tarifkosten.py | Formatting cleanup in TYPE_CHECKING block. |
| src/bo4e/bo/tarifinfo.py | Typing modernization for many fields. |
| src/bo4e/bo/tarif.py | Typing modernization for multiple fields and list types. |
| src/bo4e/bo/steuerbareressource.py | Typing modernization for IDs/list fields. |
| src/bo4e/bo/standorteigenschaften.py | Typing modernization for optional list field. |
| src/bo4e/bo/region.py | Typing modernization for strings/list field and import cleanup. |
| src/bo4e/bo/rechnung.py | Typing modernization for many fields/lists/flags. |
| src/bo4e/bo/preisblattnetznutzung.py | Formatter-driven consolidation of a multi-line annotated assignment. |
| src/bo4e/bo/preisblattmessung.py | Typing modernization for optional list fields + formatter-driven consolidation. |
| src/bo4e/bo/preisblattkonzessionsabgabe.py | Formatter-driven consolidation of a multi-line annotated assignment. |
| src/bo4e/bo/preisblatthardware.py | Typing modernization for optional list fields + formatter-driven consolidation. |
| src/bo4e/bo/preisblattdienstleistung.py | Typing modernization for optional list field + formatter-driven consolidation. |
| src/bo4e/bo/preisblatt.py | Typing modernization for bezeichnung and optional list field. |
| src/bo4e/bo/person.py | Typing modernization for many fields. |
| src/bo4e/bo/netzlokation.py | Typing modernization for IDs/list fields/flags. |
| src/bo4e/bo/messlokation.py | Typing modernization for IDs/list fields/flags. |
| src/bo4e/bo/marktteilnehmer.py | Typing modernization for strings/list field. |
| src/bo4e/bo/marktlokation.py | Typing modernization for many fields/lists/IDs. |
| src/bo4e/bo/lokationszuordnung.py | Typing modernization for many list fields and strings. |
| src/bo4e/bo/lastgang.py | Typing modernization for list/string fields. |
| src/bo4e/bo/kosten.py | Typing modernization for list fields. |
| src/bo4e/bo/geschaeftspartner.py | Typing modernization for many fields/lists. |
| src/bo4e/bo/geschaeftsobjekt.py | Typing modernization for base fields and import cleanup. |
| src/bo4e/bo/geraet.py | Typing modernization for string fields. |
| src/bo4e/bo/fremdkosten.py | Typing modernization for optional list field. |
| src/bo4e/bo/energiemenge.py | Typing modernization for string fields. |
| src/bo4e/bo/buendelvertrag.py | Typing modernization for many fields/lists. |
| src/bo4e/bo/bilanzierung.py | Typing modernization across many fields + annotated type update. |
| src/bo4e/bo/ausschreibung.py | Typing modernization for many fields/lists. |
| src/bo4e/bo/angebot.py | Typing modernization for IDs/datetimes/lists. |
| src/bo4e/init.py | Adjusts __all__ ordering to include COM earlier. |
| README.rst | Replaces black badge/commands with ruff equivalents and updates group list. |
| pyproject.toml | Removes black/isort/pylint groups/config and adds ruff config + dependency group updates. |
| generate_or_validate_json_schemas.py | Typing import modernization + small formatting tweaks and file open simplification. |
| docs/contributing_guide.rst | Updates contributor guidance from black/pylint to ruff. |
| .pylintrc | Removes legacy pylint configuration (deleted). |
| .pre-commit-config.yaml | Replaces black/isort hooks with ruff-check + ruff-format hooks. |
| .github/workflows/linting.yml | Switches CI linting step from pylint to ruff check. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if TYPE_CHECKING: | ||
| from ..enum.mengeneinheit import Mengeneinheit | ||
| pass |
There was a problem hiding this comment.
Good catch — that was pre-existing dead code (the Mengeneinheit TYPE_CHECKING-only import was already unused before this migration) that ruff's autofix exposed by removing the import but leaving the empty block behind. Removed both the block and the now-unused TYPE_CHECKING import in 8ae407e.
The only import in the block (Mengeneinheit) was already unused and got removed by ruff's autofix, leaving a no-op `if TYPE_CHECKING: pass`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
linting/formattingdependency groups into a singlelintinggroup containing justruff(matches the version resolved intouv.lock,0.16.1).[tool.black]/[tool.isort]/.pylintrc/[tool.pylint.'MESSAGES CONTROL']into[tool.ruff]/[tool.ruff.lint]/[tool.ruff.format], preserving old behavior:E501(line-too-long) is disabled repo-wide because.pylintrcexplicitly disabled it too (long German docstrings)..pylintrc'sgood-names→pep8-naming.ignore-names.PLR09xx/PLR2004noise ignored (pylint's default config never enforced these either).RUF001/002/003ignored (ambiguous-unicode) since this codebase's docstrings are largely German.mccabe(C90) intentionally left unselected —.pylintrchad no complexity threshold configured..pre-commit-config.yaml:psf/black+pycqa/isort→astral-sh/ruff-pre-commit(ruff-checkscoped tosrc/bo4e+generate_or_validate_json_schemas.py, matching pylint's old scope exactly;ruff-formatunscoped, matching black/isort's old repo-wide scope)..github/workflows/linting.yml'slintingmatrix leg to runruff checkinstead ofpylint(formatting.ymlneeds no change — it just runspre-commit/action, which picks up the new hooks automatically). Required-status-check names are unaffected since the matrix values (linting,type_check,dev) are unchanged.ruff check --fix --unsafe-fixes+ruff formatover the codebase (408 auto-fixed findings, mostlyUP045/UP006/UP035typing modernizations and black-compatible reformatting).zaehlertypSpezifikation,anzahlAblesungen) get a scoped# noqa: N815rather than a rename — renaming a public BO4E field is a breaking API change, out of scope for a tooling swap..pylintrc(fully translated) and updates README.rst/docs/contributing_guide.rst.Test plan
uv run --group linting ruff check src/bo4e generate_or_validate_json_schemas.py— cleanuv run --group linting ruff format --check .— clean, confirmed.mdfiles are excluded (extend-exclude)uv.lockdiff contains only the black/isort/pylint → ruff swap, no unrelated version bumps.pyfiles still parse (ast.parse) andimport bo4esucceedsruff-check,ruff-format) pass locallyCloses the tracking checklist in #1119.
🤖 Generated with Claude Code