5.2 to 5.4 ruff, the formatter and the linter

Read the tutorial. Build it yourself is the other way to read this part.

This walk goes through rahuldave/cheesecracker on GitHub. This part starts from the code at f77650600c11, partway through step-05. The code before this part

To look at this code on your machine, run these commands. The first one makes a clone, if this folder has none:

[ -d cheesecracker ] || git clone https://github.com/rahuldave/cheesecracker
cd cheesecracker
git fetch --quiet --tags --force origin
git switch --detach f77650600c11
just setup

ruff goes into a dependency group of its own, lint. Its settings allow lines of up to 120 characters, and check the rules that flake8, an older linter, checks. Two recipes run it. just fmt runs the formatter, and just lint runs the linter.

5.2 ruff, the formatter and the linter, in the group lint

ruff is a formatter and a linter in one tool, written in Rust by Astral, the makers of uv. ruff format writes the code in the layout of black, the formatter of most Python projects. ruff check checks the rules of flake8 and of many other linters, and can fix some of them. It takes the place of both black and flake8, and runs much faster.

ruff checks the code, and the server does not need it to run. So ruff goes into a group of its own, lint.

This change came from running uv add --group lint ruff.

uv run ruff --version

uv prints the version of ruff, ruff 0.17.1 on the day of the class.

What changed

  • pyproject.toml: ruff, in the group lint. 3 lines added. It comes from uv add --group lint ruff. The file
    • look at "ruff>=0.17.1",
  • uv.lock: the exact version of ruff. 29 lines added. It comes from uv add --group lint ruff. The file

The diff of pyproject.toml
@@ -16,6 +16,9 @@ package = false
 default-groups = "all"
 
 [dependency-groups]
+lint = [
+    "ruff>=0.17.1",
+]
 test = [
     "httpx2>=2.13.1",
     "pytest>=9.1.1",

This change on GitHub The code after it

5.3 ruff's settings: lines of 120 characters, and flake8's rules

By default, ruff allows lines of up to 88 characters, and this project allows 120. Its default rules also leave out some rules of flake8. Two tables in pyproject.toml set both.

± See the change to pyproject.toml

[tool.ruff] sets line-length = 120, for the formatter and the linter. [tool.ruff.lint] selects the rules E, W and F. They are the errors and warnings of pycodestyle, and the rules of pyflakes, which flake8 checks.

uv run ruff check

ruff finds 2 errors, and fails. F401 is the import of os, which nothing uses. E501 is the line of 187 characters. ruff says that it can fix the first one.

uv run ruff format --check

ruff says 2 files would be reformatted, and fails. --check changes no file.

What changed

  • pyproject.toml: the settings of ruff, the length of a line and the rules of the linter. 8 lines added. The file
    • look at select = ["E", "W", "F"]

The diff of pyproject.toml
@@ -30,3 +30,11 @@ test = [
 # The tests are in tests/, and import the package api from src/api-service/
 testpaths = ["tests"]
 pythonpath = ["src/api-service"]
+
+[tool.ruff]
+# The longest line, for the formatter and the linter
+line-length = 120
+
+[tool.ruff.lint]
+# The rules that flake8 checks: pycodestyle's errors (E) and warnings (W), and pyflakes (F)
+select = ["E", "W", "F"]

This change on GitHub The code after it

5.4 just fmt and just lint run ruff

Two recipes give the formatter and the linter short names. Each passes on to ruff any words that you type after it.

± See the change to justfile

The recipe fmt runs uv run ruff format, and lint runs uv run ruff check. So just fmt --check checks the layout, and just lint --fix fixes what ruff can fix.

just fmt --check

The recipe fails as ruff format --check did, with 2 files would be reformatted.

What changed

  • justfile: the recipes fmt and lint. 8 lines added. The file
    • look at uv run ruff check "$@"

The diff of justfile
@@ -44,3 +44,11 @@ stop:
 # Run the tests, and show which lines of the package api they ran. Extra arguments go to pytest: just cov tests/unit
 cov *args:
     uv run pytest --cov=api --cov-report=term-missing "$@"
+
+# Format the code, one way. Extra arguments go to ruff: just fmt --check, just fmt --diff
+fmt *args:
+    uv run ruff format "$@"
+
+# Check the code against the rules in pyproject.toml. Extra arguments go to ruff: just lint --fix
+lint *args:
+    uv run ruff check "$@"

This change on GitHub

This part ends at the code at b947593e84b7, partway through step-05. The code after this part