1 A table, and a tool for the docs
Read the tutorial. Build it yourself is the other way to read this part.
just setupA list of counts is hard to read at a glance. A table lines up the words and the counts. A small package, tabulate, draws tables, so tally depends on it. The docs come later, and their tool comes now, in a group of its own.
The code before this part. The code after it.
1.1 tabulate, in a range of versions
tally needs tabulate to draw a table. A new version 1.0 of tabulate could change how it draws one, so tally takes
any 0.9 version, and no later one. uv add with a range of versions puts the range in pyproject.toml, and the
exact version in uv.lock:
This change came from running uv add "tabulate>=0.9,<0.10".
In pyproject.toml, the list dependencies now holds tabulate>=0.9,<0.10. In uv.lock, tabulate has the version
0.9.0, the one version in that range.
uv run python -c "import tabulate; print(tabulate.__version__)"It prints 0.9.0.
What changed
pyproject.toml: tabulate, with the range of its versions. 3 lines added, 1 removed. It comes fromuv add "tabulate>=0.9,<0.10". The file.- look at
"tabulate>=0.9,<0.10",
- look at
uv.lock: the exact version of tabulate. 13 lines added. It comes fromuv add "tabulate>=0.9,<0.10". The file.
The diff of pyproject.toml
@@ -4,7 +4,9 @@ version = "0.1.0"
description = "Count the words in a text"
readme = "README.md"
requires-python = ">=3.12"
-dependencies = []
+dependencies = [
+ "tabulate>=0.9,<0.10",
+]
[project.scripts]
tally = "tally:main"1.2 tally --table
tally prints one line for each word, with the count first. A new option, --table, prints the same counts as a
table, with a header. main takes the option out of the arguments, and passes the rows to tabulate.
A patch to src/tally/__init__.py.
In main of src/tally/__init__.py, the flag as_table is true when the arguments hold --table. The rows then go
to tabulate, with the header word and times.
uv run tally --top 3 --table data/corpus.txtIt prints a header, word and times, a line of dashes, and the three words with their counts in a column on the
right.
What changed
src/tally/__init__.py: the option--table, which prints the rows with tabulate. 11 lines added, 3 removed. The file.- look at
print(tabulate(rows, headers=["word", "times"]))
- look at
The diff of src/tally/__init__.py
@@ -2,6 +2,8 @@
import sys
+from tabulate import tabulate
+
def count(text: str) -> dict[str, int]:
"How many times each word of `text` appears, ignoring case."
@@ -17,11 +19,17 @@ def top(counts: dict[str, int], n: int) -> list[tuple[str, int]]:
def main() -> None:
- "Count the words of a file, or of the standard input. With --top N, only the N most common."
- args, n = sys.argv[1:], None
+ "Count the words of a file, or of the standard input. Options: --top N, and --table."
+ args = sys.argv[1:]
+ as_table = "--table" in args
+ 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()
counts = count(text)
- for word, times in top(counts, n) if n else sorted(counts.items()):
+ rows = top(counts, n) if n else sorted(counts.items())
+ if as_table:
+ print(tabulate(rows, headers=["word", "times"]))
+ return
+ for word, times in rows:
print(times, word)1.3 mdformat, in the group docs
The docs will be Markdown files. mdformat formats Markdown, and its option --check says whether a file is
formatted. Only the people who write the docs need it, so it goes in a group of its own, docs:
This change came from running uv add --group docs mdformat.
uv sync installs the group dev and no other group, unless the project names more. One more line in the table
[tool.uv] of pyproject.toml names both groups, so that just setup installs mdformat too.
A patch to pyproject.toml.
pyproject.toml has a group docs with mdformat, and at its end a table [tool.uv] whose default-groups names
dev and docs.
uv sync -q && uv run --no-sync mdformat --versionuv sync installs mdformat. Then uv run --no-sync runs it without another sync, and it prints mdformat 1.0.0, or a
newer version.
What changed
pyproject.toml: the groupdocs, and the groups thatuv syncinstalls. 6 lines added. It comes fromuv add --group docs mdformat. The file.- look at
default-groups = ["dev", "docs"]
- look at
uv.lock: the exact versions of mdformat and of the packages it needs. 37 lines added. It comes fromuv add --group docs mdformat. The file.
The diff of pyproject.toml
@@ -19,6 +19,12 @@ build-backend = "uv_build"
dev = [
"ruff>=0.17.0",
]
+docs = [
+ "mdformat>=1.0.0",
+]
[tool.ruff]
line-length = 100
+
+[tool.uv]
+default-groups = ["dev", "docs"]