Repository navigation
Commit cfe47e7
authored
feat: upgrade to ggsql 0.5.2 with native SVG/PDF/HEP writers (#9)
* chore: bump ggsql crate to 0.5.2 and Python package to 0.5.2
Test expectation update: point's position aesthetics became optional in
ggsql 0.4.0, so the missing-required-aesthetic test now uses a text layer
missing its required label aesthetic.
* feat: add SVGWriter for native SVG rendering
* feat: add PDFWriter and HepWriter for native rendering
* feat: add ggsql.save() for exporting specs to svg/pdf/hep/json
* docs: document native writers and ggsql.save()
* docs: document py/v* release tag workflow
* fix: address Copilot review findings
- Bump declared Rust MSRV to 1.88: the native-writer dependency graph (parley 0.9) requires it, so 1.86 was not actually supported.
- Validate dpi in SVGWriter/PDFWriter constructors (rejects non-positive and non-finite values) instead of letting them reach the renderer.
- Add Python integration tests for builtin datasets (ggsql:penguins, ggsql:airquality) and dpi validation.
* ci: pin Windows jobs to windows-2022
windows-latest now resolves to a Windows Server 2025 image with the VS2026/v145 toolchain, whose STL removed stdext::checked_array_iterator. ggsql 0.5.2 pins duckdb ~1.10502, and duckdb 1.5.2's vendored fmt still uses that symbol under #ifdef _SECURE_SCL, so the bundled duckdb build hard-fails on windows-latest (duckdb/duckdb-rs#783, fixed upstream in libduckdb-sys 1.10506).
windows-2022's VS2022/v143 STL still has the (deprecated) symbol, and upstream ggsql pins windows-2022 for its own release builds for the same reason. This is a stopgap: revert to windows-latest once ggsql releases with duckdb ~1.10506.
* docs: add missing 0.3.3 changelog section and release checklist
The 0.3.3 release went out with its changelog entries still under
UNRELEASED (and the altair.Chart fallback entry misfiled under 0.3.2).
Record them under a proper 0.3.3 section, and add a release checklist
to CLAUDE.md so the changelog/version steps aren't skipped again.
* fix: derive __version__ from package metadata; validate width/height
ggsql.__version__ was hardcoded and drifted from pyproject (it read
0.3.0 in the published 0.3.1-0.3.3 wheels). Read it via
importlib.metadata instead, with a test pinning it to pyproject.toml.
Also reject non-positive width/height in SVGWriter/PDFWriter/save()
with a clear ValueError, matching the existing dpi validation, instead
of surfacing a raw PyO3 OverflowError (negative) or silently clamping
(zero).
* perf: release the GIL while native writers render
SVG/PDF/HEP rendering is pure Rust work on immutable data, but it ran
while holding the GIL, blocking other Python threads for the duration.
Wrap the render calls in Python::detach so concurrent Python code (e.g.
a web server or async event loop) keeps running during a slow render.
Safety is compiler-checked: detach requires a Send closure, so this
only builds because the writer and spec types are Sync. Single-threaded
behavior is unchanged.
* feat: expose the crate's writer options as **options on native writers
The crate's native writers take more than width/height/dpi: units,
background, and per-format settings (svg: text/embed-fonts/id-prefix;
pdf: compress/links; hep: lossy/embed-fonts). Route constructor kwargs
through the crate's WriterOptions/from_options so ggsql itself validates
keys per writer — an unknown key or unusable value raises ValueError
naming the option and listing the supported ones. Python booleans become
"true"/"false"; underscore spellings match the crate's hyphenated keys
via its key normalisation.
This goes beyond the R bindings' surface (width/height/dpi only) by
design: routing through from_options means options added upstream become
available here without binding changes.
HepWriter also gains optional width/height/dpi, recorded as consumer
hints only when given (an optionless writer still records no hint).
save() passes **options through to the native writer.
* Revert "feat: expose the crate's writer options as **options on native writers"
This reverts commit 97c5a28.
* fix: address Copilot review — document fontconfig runtime dep, add wheel smoke test and writer warning tests
- README: document that native SVG/PDF/HEP writers dlopen libfontconfig.so.1
on Linux and need installed fonts; renders silently lose text otherwise
- CI: smoke-test the built wheel in a python:3.12-slim container
provisioned per the README, asserting rendered SVG retains its text
- tests: exercise the render-issue warning path with a stubbed inner
writer returning non-empty issues (pytest.warns + output preserved),
plus a no-warning case for an empty issue list
* feat: point raster save() attempts at SVG conversion
.png/.jpg/.jpeg/.tif/.tiff/.webp now raise a targeted ValueError
explaining that ggsql's raster writers need a GPU adapter (unavailable
in some environments) and suggesting .svg/.pdf plus a converter of the
user's choice, instead of the generic unsupported-extension message
they previously shared with typos. The GPU-backed raster writers stay
disabled; this only improves the error UX.
* feat: add __repr__ to writer classes
SVGWriter/PDFWriter show their constructor dimensions; HepWriter and
VegaLiteWriter show the bare call. Pure Python-layer change on the
public wrappers.
* ci: checkout before downloading wheel artifact (checkout cleans workspace)1 parent 2fffdd6 commit cfe47e7
13 files changed
Lines changed: 1510 additions & 67 deletions
File tree
- .github/workflows
- python/ggsql
- scripts
- src
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
15 | 24 | | |
16 | 25 | | |
17 | 26 | | |
18 | 27 | | |
19 | 28 | | |
20 | 29 | | |
21 | | - | |
| 30 | + | |
22 | 31 | | |
23 | 32 | | |
24 | 33 | | |
| |||
68 | 77 | | |
69 | 78 | | |
70 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
73 | 77 | | |
74 | | - | |
| 78 | + | |
75 | 79 | | |
76 | 80 | | |
77 | 81 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
4 | 18 | | |
5 | 19 | | |
6 | 20 | | |
| 21 | + | |
7 | 22 | | |
| 23 | + | |
8 | 24 | | |
9 | 25 | | |
10 | 26 | | |
11 | 27 | | |
12 | 28 | | |
13 | 29 | | |
14 | 30 | | |
15 | | - | |
16 | 31 | | |
17 | 32 | | |
18 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
41 | 51 | | |
42 | 52 | | |
43 | 53 | | |
0 commit comments