@@ -751,159 +751,6 @@ When running in Positron IDE, the extension provides enhanced functionality:
751751
752752---
753753
754- ### 8. Python Bindings (` ggsql-python/ ` )
755-
756- ** Responsibility** : Python bindings for ggsql, enabling Python users to create visualizations using ggsql's VISUALISE syntax.
757-
758- ** Features** :
759-
760- - PyO3-based Rust bindings compiled to a native Python extension
761- - Two-stage API mirroring the Rust API: ` reader.execute() ` → ` render() `
762- - DuckDB reader with DataFrame registration
763- - Custom Python reader support: any object with ` execute_sql(sql) -> DataFrame ` method
764- - Works with any narwhals-compatible DataFrame (polars, pandas, etc.)
765- - LazyFrames are collected automatically
766- - Returns native ` altair.Chart ` objects via ` render_altair() ` convenience function
767- - Query validation and introspection (SQL, layer queries, stat queries)
768-
769- ** Installation** :
770-
771- ``` bash
772- # From source (requires Rust toolchain and maturin)
773- cd ggsql-python
774- pip install maturin
775- maturin develop
776- ```
777-
778- ** API** :
779-
780- ``` python
781- import ggsql
782- import polars as pl
783-
784- # Create reader and register data
785- reader = ggsql.DuckDBReader(" duckdb://memory" )
786- df = pl.DataFrame({" x" : [1 , 2 , 3 ], " y" : [10 , 20 , 30 ]})
787- reader.register(" data" , df)
788-
789- # Execute visualization
790- spec = reader.execute(
791- " SELECT * FROM data VISUALISE x, y DRAW point"
792- )
793-
794- # Inspect metadata
795- print (f " Rows: { spec.metadata()[' rows' ]} " )
796- print (f " Columns: { spec.metadata()[' columns' ]} " )
797- print (f " SQL: { spec.sql()} " )
798-
799- # Render to Vega-Lite JSON
800- writer = ggsql.VegaLiteWriter()
801- json_output = writer.render(spec)
802- ```
803-
804- ** Convenience Function** (` render_altair ` ):
805-
806- For quick visualizations without explicit reader setup:
807-
808- ``` python
809- import ggsql
810- import polars as pl
811-
812- df = pl.DataFrame({" x" : [1 , 2 , 3 ], " y" : [10 , 20 , 30 ]})
813-
814- # Render DataFrame to Altair chart in one call
815- chart = ggsql.render_altair(df, " VISUALISE x, y DRAW point" )
816- chart.display() # In Jupyter
817- ```
818-
819- ** Query Validation** :
820-
821- ``` python
822- # Validate syntax without execution
823- validated = ggsql.validate(
824- " SELECT x, y FROM data VISUALISE x, y DRAW point"
825- )
826- print (f " Valid: { validated.valid()} " )
827- print (f " Has VISUALISE: { validated.has_visual()} " )
828- print (f " SQL portion: { validated.sql()} " )
829- print (f " Errors: { validated.errors()} " )
830- ```
831-
832- ** Classes** :
833-
834- | Class | Description |
835- | -------------------------- | ------------------------------------------------- |
836- | ` DuckDBReader(connection) ` | Database reader with DataFrame registration |
837- | ` VegaLiteWriter() ` | Vega-Lite JSON output writer |
838- | ` Validated ` | Result of ` validate() ` with query inspection |
839- | ` Spec ` | Result of ` reader.execute() ` , ready for rendering |
840-
841- ** Functions** :
842-
843- | Function | Description |
844- | ------------------------ | ------------------------------------------------ |
845- | ` validate(query) ` | Syntax/semantic validation with query inspection |
846- | ` reader.execute(query) ` | Execute ggsql query, return Spec |
847- | ` execute(query, reader) ` | Execute with custom reader (bridge path) |
848- | ` render_altair(df, viz) ` | Convenience: render DataFrame to Altair chart |
849-
850- ** Spec Methods** :
851-
852- | Method | Description |
853- | ---------------- | -------------------------------------------- |
854- | ` render(writer) ` | Generate Vega-Lite JSON |
855- | ` metadata() ` | Get rows, columns, layer_count |
856- | ` sql() ` | Get the SQL portion |
857- | ` visual() ` | Get the VISUALISE portion |
858- | ` layer_count() ` | Number of DRAW layers |
859- | ` data() ` | Get the main DataFrame |
860- | ` layer_data(i) ` | Get layer-specific DataFrame (if filtered) |
861- | ` stat_data(i) ` | Get stat transform DataFrame (if applicable) |
862- | ` layer_sql(i) ` | Get layer filter SQL (if applicable) |
863- | ` stat_sql(i) ` | Get stat transform SQL (if applicable) |
864- | ` warnings() ` | Get validation warnings |
865-
866- ** Custom Python Readers** :
867-
868- Any Python object with an ` execute_sql(sql: str) -> polars.DataFrame ` method can be used as a reader:
869-
870- ``` python
871- import ggsql
872- import polars as pl
873-
874- class MyReader :
875- """ Custom reader that returns static data."""
876-
877- def execute_sql (self , sql : str ) -> pl.DataFrame:
878- return pl.DataFrame({" x" : [1 , 2 , 3 ], " y" : [10 , 20 , 30 ]})
879-
880- # Use custom reader with ggsql.execute()
881- reader = MyReader()
882- spec = ggsql.execute(
883- " SELECT * FROM data VISUALISE x, y DRAW point" ,
884- reader
885- )
886- ```
887-
888- Required methods for custom readers (in addition to ` execute_sql ` ):
889-
890- - ` register(name: str, df: polars.DataFrame, replace: bool = False) -> None ` - Register a DataFrame as a table
891-
892- Optional methods for custom readers:
893-
894- - ` unregister(name: str) -> None ` - Unregister a previously registered table
895-
896- Native readers (e.g., ` DuckDBReader ` ) use an optimized fast path, while custom Python readers are automatically bridged via IPC serialization.
897-
898- ** Dependencies** :
899-
900- - Python >= 3.10
901- - altair >= 5.0
902- - narwhals >= 2.15
903- - polars >= 1.0
904-
905- ---
906-
907754## Feature Flags and Build Configuration
908755
909756ggsql uses Cargo feature flags to enable optional functionality and reduce binary size.
@@ -930,10 +777,6 @@ ggsql uses Cargo feature flags to enable optional functionality and reduce binar
930777- ` plotters ` - Enable plotters-based rendering (planned, not implemented)
931778- ` all-writers ` - Enable all writer implementations
932779
933- ** Python bindings** :
934-
935- - ` ggsql-python ` - Python bindings via PyO3 (separate crate, not a feature flag)
936-
937780### Building with Custom Features
938781
939782``` bash
@@ -954,7 +797,6 @@ cargo build --all-features
954797- ` duckdb ` → ` duckdb ` crate
955798- ` postgres ` → ` postgres ` crate (future)
956799- ` sqlite ` → ` rusqlite ` crate (future)
957- - ` ggsql-python ` → ` pyo3 ` , ` narwhals ` , ` altair ` (separate workspace crate)
958800
959801---
960802
@@ -1033,7 +875,6 @@ gh workflow run release-installers.yml
1033875- Scoop (Windows)
1034876- apt repository (Debian/Ubuntu)
1035877- crates.io (Rust library)
1036- - PyPI (Python bindings)
1037878
1038879---
1039880
0 commit comments