3b Lint

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

If you start at this part, make your clone as Get the project says, and then run this command. It puts in your clone the files that this part starts from. A file that the project deleted before this part stays, so delete it if git check lists it:

git rm -rq --cached --ignore-unmatch -- :/ && git restore --source 909df18d1c02 --staged --worktree -- :/
just setup

ruff finds code that works but could be better, such as a file that nobody closes. It fixes some of what it finds by itself, and leaves the rest to us.

The code before this part. The code after it.

3b.1 What ruff fixes

ruff check --fix fixes what it can, and lists the rest. It writes its fixes, and then exits with code 1, because one problem is left.

uv run ruff check --fix
uv run ruff check --statistics

It fails, with exit code 1. It prints one line for the rule SIM115, open-file-with-context-handler, and then Found 1 error. main opens a file and never closes it, and ruff cannot fix that.

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check 429a29223911

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git restore --source 909df18d1c02 --staged -- :/ && git restore --source 429a29223911 --staged --worktree -- :/

What changed

  • scripts/corpus.py: a list of words, as ruff writes it. 1 line added, 1 removed. It comes from uv run ruff check --fix. The file.
    • look at WORDS = ["the", "a", "word", "count", "text", "tally", "test", "step", "move", "commit", "tag", "note", "slide", "class", "shell", "file", "line", "code"]
The diff that uv run ruff check --fix makes in scripts/corpus.py
@@ -3,7 +3,7 @@
 import sys
 from pathlib import Path
 
-WORDS = "the a word count text tally test step move commit tag note slide class shell file line code".split()
+WORDS = ["the", "a", "word", "count", "text", "tally", "test", "step", "move", "commit", "tag", "note", "slide", "class", "shell", "file", "line", "code"]
 
 
 def main() -> None:

This change on GitHub. The code after it.

3b.2 main closes its file

ruff cannot fix SIM115. A with block closes the file when the block ends.

Apply the patch to src/tally/__init__.py, from the top of the project:

curl -fsSL https://github.com/rahuldave/tally/commit/25f4f751628b8461806074ef35b6cd489e7c9ce8.diff | git apply --include=src/tally/__init__.py

In main of src/tally/__init__.py, the patch puts an if and a with block in place of the line text = open(args[0]).read() if args else sys.stdin.read().

uv run ruff check

It prints All checks passed!.

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check 25f4f751628b

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git restore --source 429a29223911 --staged -- :/ && git restore --source 25f4f751628b --staged --worktree -- :/

What changed

  • src/tally/__init__.py: a with block, which closes the file. 5 lines added, 1 removed. The file.
    • look at with open(args[0]) as file:
The patch to src/tally/__init__.py
@@ -21,7 +21,11 @@ def main() -> None:
     args, n = [arg for arg in args if arg != "--table"], None
     if args[:1] == ["--top"]:
         n, args = int(args[1]), args[2:]
-    text = open(args[0]).read() if args else sys.stdin.read()
+    if args:
+        with open(args[0]) as file:
+            text = file.read()
+    else:
+        text = sys.stdin.read()
     counts = count(text)
     rows = top(counts, n) if n else sorted(counts.items())
     if as_table:

This change on GitHub. The code after it.