Repository navigation
chore: remove publish-workflow.sh scaffold #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
f1f6188
feat: add database= parameter to sql engine and editor for managed da…
eddietejeda b1f9d5c
refactor: eliminate flag-based side-effect tracking, fix unregister, …
eddietejeda 1e56b56
fix: pass dropdown label key (not value) to mo.ui.dropdown value= ini…
eddietejeda d78bb80
docs: rewrite README with quickstart and usage examples
eddietejeda 6f3dbde
chore: remove publish-workflow.sh scaffold (workflow already generated)
eddietejeda File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,151 +1,122 @@ | ||
| # hotdata-marimo | ||
|
|
||
| Marimo widgets for [Hotdata](https://hotdata.dev): run SQL, browse catalogs, load managed databases, and display results in notebooks. | ||
|
|
||
| Requires Python 3.10+, [Marimo](https://marimo.io/), and [hotdata-runtime](https://github.com/hotdata-dev/hotdata-runtime) (installed automatically). | ||
|
|
||
| ## Supported widgets | ||
|
|
||
| Importing `hotdata_marimo` registers `mo.ui.hotdata_*` aliases for discoverability. | ||
|
|
||
| | Widget | Function | Notes | | ||
| |--------|----------|-------| | ||
| | SQL editor | `hm.sql_editor(client)` | Returns `.ui` and `.result` | | ||
| | Table browser | `hm.table_browser(client)` | Browse connections, schemas, tables, columns | | ||
| | Managed databases panel | `hm.databases_panel(client)` | Create catalogs and load parquet files | | ||
| | Managed database writer | `hm.managed_database_writer(client)` | Lower-level create/load UI | | ||
| | Workspace selector | `hm.workspace_selector_from_env()` | Pick workspace when `HOTDATA_WORKSPACE` is unset | | ||
| | Connection picker | `hm.connection_picker(client)` | Dropdown of workspace connections | | ||
| | Connection status | `hm.connection_status(client)` | API / workspace health callout | | ||
| | Connections panel | `hm.connections_panel(client)` | Status callout plus connection list | | ||
| | Query result | `hm.query_result(result)` | Render a `QueryResult` as a table | | ||
| | Recent results | `hm.recent_results(client)` | Browse past query results | | ||
| | Run history | `hm.run_history(client)` | Recent query runs | | ||
|
|
||
| Each widget also has a `mo.ui.hotdata_*` alias (e.g. `mo.ui.hotdata_sql_editor`). Native Marimo SQL cells are supported via `hm.register_hotdata_sql_engine()` and `mo.sql(..., engine=client)`. | ||
| [Marimo](https://marimo.io/) widgets for [Hotdata](https://hotdata.dev) — run SQL, browse your schema, and work with managed databases in reactive notebooks. | ||
|
|
||
| ## Install | ||
|
|
||
| ```bash | ||
| pip install hotdata-marimo | ||
| ``` | ||
|
|
||
| Set `HOTDATA_API_KEY`. Optionally set `HOTDATA_WORKSPACE`, `HOTDATA_API_URL`, or `HOTDATA_SANDBOX`. | ||
|
|
||
| ## Connect | ||
|
|
||
| ```python | ||
| import hotdata_marimo as hm | ||
|
|
||
| client = hm.from_env() | ||
| ``` | ||
|
|
||
| If `HOTDATA_WORKSPACE` is unset, pick a workspace interactively: | ||
|
|
||
| ```python | ||
| ws = hm.workspace_selector_from_env() | ||
| client = ws.client | ||
| ``` | ||
| ## Authentication | ||
|
|
||
| ## SQL editor widget | ||
| Set `HOTDATA_API_KEY` in your environment. Optionally set `HOTDATA_WORKSPACE` to pin a specific workspace (the first available workspace is used if unset). | ||
|
|
||
| Run SQL in one cell; show results in the next. Marimo only renders what you **`return`**. | ||
| ## Quickstart | ||
|
|
||
| **Cell 1 — editor** | ||
| Because Marimo reruns cells reactively, construct a widget in one cell and read its `.ui` or `.result` in the next. | ||
|
|
||
| ```python | ||
| import marimo as mo | ||
| # Cell 1 | ||
| import hotdata_marimo as hm | ||
|
|
||
| client = hm.from_env() | ||
| editor = hm.sql_editor(client, default_sql="SELECT 1 AS ok") | ||
| return editor.ui | ||
| ``` | ||
|
|
||
| **Cell 2 — result** | ||
|
|
||
| ```python | ||
| # Cell 2 | ||
| return hm.query_result(editor.result) | ||
| ``` | ||
|
|
||
| Click **Run on Hotdata** after changing SQL. The editor caches the last successful result so downstream cells do not re-query on every refresh. | ||
| Click **Run on Hotdata** after editing SQL. The editor caches the last successful result so downstream cells don't re-query on every refresh. | ||
|
|
||
| ## Native Marimo SQL cells | ||
| ## Workspace selection | ||
|
|
||
| If you have multiple workspaces or `HOTDATA_WORKSPACE` is unset, add an interactive picker. `ws.client` updates when the selection changes: | ||
|
|
||
| ```python | ||
| ws = hm.workspace_selector_from_env() | ||
| client = ws.client | ||
| return ws.ui | ||
| ``` | ||
|
|
||
| Register the Hotdata engine once, then pass `engine=client` to `mo.sql`. Hotdata appears as **Hotdata** in the SQL connection picker. | ||
| ## Native Marimo SQL cells | ||
|
|
||
| **Setup cell** | ||
| Register the Hotdata engine once and Hotdata will appear as a selectable engine in the SQL connection picker: | ||
|
|
||
| ```python | ||
| # Setup cell | ||
| import marimo as mo | ||
| import hotdata_marimo as hm | ||
|
|
||
| hm.register_hotdata_sql_engine() | ||
| client = hm.from_env() | ||
| ``` | ||
|
|
||
| **SQL cell** | ||
|
|
||
| ```python | ||
| _df = mo.sql( | ||
| """ | ||
| SELECT 1 AS example_value | ||
| """, | ||
| engine=client, | ||
| ) | ||
| # Any SQL cell | ||
| _df = mo.sql("SELECT * FROM orders LIMIT 10", engine=client) | ||
| ``` | ||
|
|
||
|  | ||
|
|
||
| ## Browse tables | ||
| ## Browse your schema | ||
|
|
||
| The table browser lets you pick a connection, search for a table, and inspect its columns — with a starter query ready to copy: | ||
|
|
||
| ```python | ||
| browser = hm.table_browser(client) | ||
| return browser.ui | ||
| ``` | ||
|
|
||
| Pick a connection, schema, and table to inspect columns. Use `browser.selected_table` in downstream cells. | ||
| Use `browser.selected_table` in downstream cells to reference the chosen table. | ||
|
|
||
| ## Managed databases | ||
|
|
||
| Create a Hotdata-owned catalog and load a parquet file from the notebook: | ||
| View existing managed databases and load new parquet files from a single tabbed panel: | ||
|
|
||
| ```python | ||
| panel = hm.databases_panel(client) | ||
| return panel | ||
| writer = hm.managed_database_writer(client) | ||
| return writer.tab_ui | ||
| ``` | ||
|
|
||
| Or use the lower-level writer API: | ||
| Or show just the read-only panel: | ||
|
|
||
| ```python | ||
| writer = hm.managed_database_writer(client) | ||
| return writer.ui | ||
| return hm.databases_panel(client) | ||
| ``` | ||
|
|
||
| ## Other helpers | ||
|
|
||
| See [Supported widgets](#supported-widgets) for the full list. Quick examples: | ||
| ## All widgets | ||
|
|
||
| | Widget | Code | What you get | | ||
| |--------|------|-------------| | ||
| | SQL editor | `hm.sql_editor(client)` | `.ui` to show the editor, `.result` to read rows | | ||
| | Query result | `hm.query_result(result)` | Renders a `QueryResult` as a table | | ||
| | Table browser | `hm.table_browser(client)` | Browse connections, tables, and column metadata | | ||
| | Managed databases | `hm.databases_panel(client)` | Read-only list of managed databases | | ||
| | Database writer | `hm.managed_database_writer(client)` | Create databases and load parquet files | | ||
| | Workspace picker | `hm.workspace_selector_from_env()` | Dropdown to switch workspaces | | ||
| | Connection picker | `hm.connection_picker(client)` | Dropdown of connections in the workspace | | ||
| | Connection status | `hm.connection_status(client)` | Health callout for the API and workspace | | ||
| | Connections panel | `hm.connections_panel(client)` | Status + list of connections | | ||
| | Recent results | `hm.recent_results(client)` | Browse past query results | | ||
| | Run history | `hm.run_history(client)` | Recent query runs | | ||
|
|
||
| ```python | ||
| return hm.connection_status(client) | ||
| return hm.connections_panel(client) | ||
| return hm.recent_results(client).ui | ||
| return hm.run_history(client) | ||
| ``` | ||
| All widgets are also available as `mo.ui.hotdata_*` aliases (e.g. `mo.ui.hotdata_sql_editor`) for discovery via Marimo's autocomplete. | ||
|
|
||
| ## Demo notebook | ||
|
|
||
| ```bash | ||
| uv run marimo edit examples/demo.py --no-token | ||
| ``` | ||
|
|
||
| `examples/demo.py` combines workspace selection, catalog browsing, managed databases, query history, and a native `mo.sql` cell. | ||
| The demo combines workspace selection, schema browsing, managed databases, query history, and a native SQL cell in a single tabbed interface. | ||
|
|
||
| ## Development | ||
|
|
||
| ```bash | ||
| uv sync --locked | ||
| uv run pytest | ||
| ``` | ||
|
|
||
| See [hotdata-runtime](https://github.com/hotdata-dev/hotdata-runtime) for the underlying API client. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: (not blocking) Building the options dict directly with
{db.description or db.id: db.id for db in dbs}silently collapses entries when two managed databases share a description. Unlike the oldnamefield,descriptionis free-form user text, so collisions are plausible — and the affected database becomes unreachable from this widget.The repo already has
unique_label_optionsfor exactly this case (seeconnection_optionsin_options.py:47and the workspace picker inworkspace_selector.py:44-48). Consider: