Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: Use ruff format instead of black . for improved user experience #5023

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

echoix
Copy link
Member

@echoix echoix commented Feb 1, 2025

Closes #4922

As discussed in #4922, I'm implementing the switch from black to ruff format. It is a drop in replacement with some limited known deviations

From ruff's docs: https://docs.astral.sh/ruff/formatter/#philosophy

The initial goal of the Ruff formatter is not to innovate on code style, but rather, to innovate on performance, and provide a unified toolchain across Ruff's linter, formatter, and any and all future tools.

As such, the formatter is designed as a drop-in replacement for Black, but with an excessive focus on performance and direct integration with Ruff. Given Black's popularity within the Python ecosystem, targeting Black compatibility ensures that formatter adoption is minimally disruptive for the vast majority of projects.

Specifically, the formatter is intended to emit near-identical output when run over existing Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines are formatted identically. (See: _Style Guide.)

Given this focus on Black compatibility, the formatter thus adheres to Black's (stable) code style, which aims for "consistency, generality, readability and reducing git diffs".

Like black, ruff format commits to keeping a stable style for a year, and they work together to stay aligned with black choices, if black does it in time.

Black, while faster that it was, is still python, and was becoming slow sometimes, and if used regularly, or even as a save hook on your IDE, is slow.

For example, just before preparing this PR, I compared black 25 and ruff 0.9.4, both without cache, on a performing computer from 2019:
black:

vscode ➜ ~/grass (black-25) $ rm -r  ~/.cache/black
vscode ➜ ~/grass (black-25) $ time black .
reformatted /home/vscode/grass/python/grass/exceptions/__init__.py
reformatted /home/vscode/grass/gui/wxpython/tplot/frame.py
reformatted /home/vscode/grass/python/grass/pydispatch/errors.py
reformatted /home/vscode/grass/python/grass/script/__init__.py
reformatted /home/vscode/grass/python/grass/imaging/images2gif.py

All done! ✨ 🍰 ✨
5 files reformatted, 951 files left unchanged.

real    0m21.272s
user    2m42.879s
sys     0m3.288s

ruff:

vscode ➜ ~/grass (ruff-format) $ ruff clean
vscode ➜ ~/grass (ruff-format) $ time ruff format --no-cache
99 files reformatted, 857 files left unchanged

real    0m0.255s
user    0m1.643s
sys     0m0.300s

The experience is simply unmatched.

As for concerns about immatureness: Black has slow developpement, and this repo started when it was young. Ruff is still new, but rapid development. ruff format has been available since their 0.0.289 release in september 2023 (according to their pre-commit repo), which is found on the 8th page of tags on github: https://github.com/astral-sh/ruff/tags?after=v0.1.3. They announced the availability in october 2023 https://astral.sh/blog/the-ruff-formatter. At their developpement cadence, and from following them since a while (before their formatter existed), I estimate that it equates to more than 3 years maturity. I don't see any fear to go there, its way "simpler" that the rules and fixes we rely on here from ruff itself.

For the differences, its a one-time change, and this PR here contains the deviations that they choose to be better than black, amongst other enabling work and fixes.
Some other nice additions ruff format brings that black doesn't yet:

  • Ruff can format the expressions inside f-strings, that otherwise either a pylint or flake8 rule would flag and require manual fixes
  • Can format code in docstrings: doctests, inside markdown fenced code blocks, inside rst style, etc. (Disabled by default, opt-in). Skips formatting if it cannot parse or the formatted text produces invalid code.

Upcoming work, after introducing ruff format:

  • Enable docstring formatting

This PR also includes 2 small fixes noted in the black 25 preparatory PR:

  • Comments of "# to" and "# from" that were already misplaced since grass82 at least (https://grass.osgeo.org/grass82/manuals/libpython/_modules/pygrass/raster/category.html) for a libraster.Rast_copy_cats() invocation
  • An extra comma since it was introduced 11 years ago that meant to create a tuple without using it, in rlisetup.wizard. Formatting with ruff format introduces parentheses to make the tuple obvious, that made it possible to catch that unexpected behavior (that's another + for ruff format here :) )

Other:

  • disables flake8 E501 (line too long) checks, as now it is checked by other means. Ruff format current style sometimes choses to exceed the line length if it is only for an inline exclusion, and breaking the line would be worse. Flake8 line length check would be way stricter, and isn't relevant anymore.
  • Adapts the CI to use ruff formatting with suggestions. It is batched with the ruff rules suggestions, as ruff fixes may require formatting (as explained and suggested in their pre-commit docs). Ruff formatting doesn't introduce new linting errors.
  • Adapts pre-commit config to use ruff format.

@echoix echoix requested a review from wenzeslaus February 1, 2025 15:17
@github-actions github-actions bot added GUI wxGUI related CI Continuous integration vector Related to vector data processing raster Related to raster data processing temporal Related to temporal data processing Python Related code is in Python libraries module general imagery tests Related to Test Suite notebook labels Feb 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI Continuous integration general GUI wxGUI related imagery libraries module notebook Python Related code is in Python raster Related to raster data processing temporal Related to temporal data processing tests Related to Test Suite vector Related to vector data processing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant