You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
✨ Add CLI, harden font cache, and fix review issues
- Add `quickthumb/cli.py` with `typer`: `render` subcommand with `-o`,
`--format`, `--quality`, `--var` flags and proper exit codes (0/1/2)
- Validate `--format` (PNG/JPEG/WEBP), `--quality` range (1-95), and
`--var` KEY=VALUE syntax; raise on unresolved `$VAR` placeholders
- Catch `FileNotFoundError`, `PermissionError`, `json.JSONDecodeError`
in `render` and map to exit code 1; narrow render errors to
`RenderingError`/`OSError` to avoid masking real bugs
- Add `quickthumb[cli]` optional dependency and entry point in
`pyproject.toml`
- Support `QUICKTHUMB_FONT_CACHE_DIR` env var for font cache location;
auto-create the directory if it does not exist (`makedirs exist_ok`)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-[TODO] Implement `Canvas.from_template(spec_or_path, variables={})` with `$var` / `${var}` string substitution
@@ -47,6 +47,25 @@
47
47
-[TODO] Add "Why not X" section: brief comparison vs raw Pillow and html2image to help developers justify the dependency
48
48
-[TODO] Add community entry point: link to GitHub issues/discussions for bug reports and questions
49
49
50
+
### P1 — CLI Hardening (from code review)
51
+
-[DONE] CLI `render`: catch `FileNotFoundError` / `PermissionError` from `spec.read_text()` and exit with code 1
52
+
-[DONE] CLI `render`: catch `json.JSONDecodeError` from `Canvas.from_json()` and exit with code 1
53
+
-[DONE]`_substitute_vars`: raise `ValidationError` on unresolved `$VAR` / `${VAR}` placeholders (currently passes them through silently)
54
+
-[TODO] Guard CLI entrypoint import: print a helpful message and exit if `typer` is not installed instead of crashing with `ImportError`
55
+
-[DONE] CLI `render`: validate `--var` entries contain `=`; raise a clear error when `--var keyonly` is passed (currently silently maps to empty string)
56
+
-[DONE] CLI `render`: replace bare `except Exception` with `except (RenderingError, OSError)` to avoid masking real bugs
57
+
-[DONE] CLI `render`: validate `--quality` is in `1–95` range (`typer.Option(..., min=1, max=95)`)
58
+
-[DONE] CLI `render`: validate `--format` is one of `PNG`, `JPEG`, `WEBP`; reject unknown values early
59
+
60
+
### P2 — Font Cache Hardening (from code review)
61
+
-[TODO] Use `tempfile.gettempdir()` instead of hardcoded `"/tmp"` as the default font cache dir (fixes Windows compatibility)
62
+
-[TODO] Validate downloaded font content before writing to cache (currently writes arbitrary data from any URL)
63
+
-[DONE] Call `os.makedirs(cache_dir, exist_ok=True)` before writing cached font; `QUICKTHUMB_FONT_CACHE_DIR` pointing to a non-existent dir currently crashes with `FileNotFoundError`
64
+
65
+
### P2 — CLI Polish (from code review)
66
+
-[TODO] Rename `format` parameter to `fmt` or `output_format` internally — currently shadows Python's built-in `format()`
67
+
-[TODO] Widen typer version pin from `>=0.24.1,<0.25.0` to `>=0.24.1,<1.0` to avoid unnecessary resolver conflicts
68
+
50
69
### P3 — Lower Priority
51
70
-[TODO] Fix color tuple JSON round-trip: `BackgroundLayer.color` accepts RGB tuples but they break `to_json()` / `from_json()`
52
71
-[TODO] Font metadata reading: use `fonttools` to read font weight/style from file metadata instead of relying on filename parsing
0 commit comments