Linting & Formatting¶
This project uses three tools for three different file types:
| Language | Tool | Config | VS Code extension |
|---|---|---|---|
| Python | Ruff | pyproject.toml → [tool.ruff] |
charliermarsh.ruff |
| JS / CSS | Biome | biome.jsonc |
biomejs.biome |
| HTML templates (lint) | j2lint | pyproject.toml → [tool.j2lint] |
- (CLI only) |
| HTML templates (format) | js-beautify | package.json script args + --templating django |
vscode.html-language-features |
Quick Reference¶
# Python
ruff check . # lint
ruff check . --fix # lint + auto-fix
ruff format . # format
# JS / CSS (requires: npm install)
npm run lint # lint
npm run lint:fix # lint + fix
npm run lint:fix:unsafe # lint + fix (safe + unsafe)
npm run format # format only
# HTML templates - lint
j2lint web/templates --extensions html --ignore jinja-statements-indentation
# HTML templates - format (requires: npm install)
npm run format:templates
VS Code Setup¶
Install the recommended extensions (listed below), then:
- Python - Ruff formats and fixes imports on save.
- JS / CSS - Biome formats and organizes imports on save.
- HTML - formatted on save by VS Code's built-in HTML formatter (
vscode.html-language-features, which uses js-beautify). Thehtml.format.templatingsetting is enabled so the formatter preserves Jinja2{% %}/{{ }}tags intact. Biome can't be used here because its HTML parser panics on Jinja2{% %}block tags. Linting is still j2lint via CLI.
Biome is also told to only process web/static/** (via files.includes in biome.jsonc), so it will never touch Python files, config files, or HTML templates regardless of the VS Code setting.
Ruff Rules¶
Configured in pyproject.toml under [tool.ruff.lint]. Highlights:
- Google-style docstrings (
pydocstylewithconvention = "google") - Import sorting (
isort-compatible via theIruleset) T20(noprint) - exceptrun.py, which is the CLI entrypointARG001ignored insrc/lastfm/fetch.py- its signature must matchsocket.getaddrinfo
Biome Rules¶
Configured in biome.jsonc. Scope is strictly web/static/**.
Formatter uses 2-space indent, 150-char line width (matching Ruff), no semicolons, trailing commas.
Rule severity rationale is documented inline as comments in biome.jsonc.
j2lint Rules¶
Only S4 (statement indentation) is ignored - it expects pure-Jinja nesting levels, not the surrounding HTML context, producing false positives on every indented Jinja tag. Since j2lint doesn't support config-file ignore for CLI runs, S4 is also passed via --ignore in CI.
Pre-commit Script¶
The repo includes a convenience script that runs every linting, formatting, and i18n step in one go:
It runs the following in order (aborting on the first failure):
- Fix & format - Ruff auto-fix, Ruff format, Biome lint+fix, Biome format, js-beautify templates
- Lint checks - Ruff lint, Ruff format check, Biome lint, j2lint templates
- Translations - Babel extract, update, and compile translation catalogs
This saves you from running all the individual commands listed above. Run it before committing to make sure everything is clean.
CI¶
All three linters (+ HTML formatter) run on every push/PR via .github/workflows/lint.yml.
Jobs run in parallel; all must pass before merging.
| Job | Command |
|---|---|
| python | ruff check + ruff format --check |
| js-css | npm ci && npm run lint |
| templates-lint | j2lint web/templates --extensions html --ignore jinja-statements-indentation |
| templates-format | npm run format:templates |