hotdata-jupyter 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hotdata_jupyter-0.2.1/.github/dependabot.yml +9 -0
- hotdata_jupyter-0.2.1/.github/workflows/check-release.yml +26 -0
- hotdata_jupyter-0.2.1/.github/workflows/ci.yml +33 -0
- hotdata_jupyter-0.2.1/.github/workflows/dependabot-automerge.yml +17 -0
- hotdata_jupyter-0.2.1/.github/workflows/publish.yml +69 -0
- hotdata_jupyter-0.2.1/.github/workflows/release.yml +54 -0
- hotdata_jupyter-0.2.1/.gitignore +23 -0
- hotdata_jupyter-0.2.1/.vscode/settings.json +5 -0
- hotdata_jupyter-0.2.1/CHANGELOG.md +43 -0
- hotdata_jupyter-0.2.1/PKG-INFO +113 -0
- hotdata_jupyter-0.2.1/README.md +101 -0
- hotdata_jupyter-0.2.1/RELEASING.md +43 -0
- hotdata_jupyter-0.2.1/examples/demo.ipynb +232 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/__init__.py +62 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/databases.py +237 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/display.py +35 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/env.py +40 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/magics.py +38 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/metadata.py +13 -0
- hotdata_jupyter-0.2.1/hotdata_jupyter/workspace.py +99 -0
- hotdata_jupyter-0.2.1/pyproject.toml +72 -0
- hotdata_jupyter-0.2.1/scripts/check-release.py +68 -0
- hotdata_jupyter-0.2.1/scripts/extract-changelog.py +36 -0
- hotdata_jupyter-0.2.1/scripts/release.sh +187 -0
- hotdata_jupyter-0.2.1/scripts/update_changelog.py +62 -0
- hotdata_jupyter-0.2.1/tests/conftest.py +31 -0
- hotdata_jupyter-0.2.1/tests/test_databases_jupyter.py +217 -0
- hotdata_jupyter-0.2.1/tests/test_demo_notebook.py +46 -0
- hotdata_jupyter-0.2.1/tests/test_hotdata_jupyter.py +205 -0
- hotdata_jupyter-0.2.1/tests/test_package.py +58 -0
- hotdata_jupyter-0.2.1/tests/test_update_changelog.py +48 -0
- hotdata_jupyter-0.2.1/uv.lock +1268 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Check release metadata
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- 'pyproject.toml'
|
|
7
|
+
- 'CHANGELOG.md'
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
check:
|
|
14
|
+
name: Verify changelog matches version bump
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
|
|
25
|
+
- name: Check release metadata
|
|
26
|
+
run: python scripts/check-release.py
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main", "master"]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: Test (Python 3.12)
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
21
|
+
|
|
22
|
+
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v6
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
run: uv python install 3.12
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --locked
|
|
31
|
+
|
|
32
|
+
- name: Test
|
|
33
|
+
run: uv run pytest -v
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Dependabot auto-merge
|
|
2
|
+
|
|
3
|
+
on: pull_request
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
contents: write
|
|
7
|
+
pull-requests: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
auto-merge:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
if: github.actor == 'dependabot[bot]'
|
|
13
|
+
steps:
|
|
14
|
+
- name: Enable auto-merge
|
|
15
|
+
run: gh pr merge --squash --auto "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}"
|
|
16
|
+
env:
|
|
17
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v[0-9]*'
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: pypi-publish-${{ github.ref_name }}
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
name: Build distribution
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: '3.12'
|
|
25
|
+
|
|
26
|
+
- name: Install build tooling
|
|
27
|
+
run: python -m pip install --upgrade build twine
|
|
28
|
+
|
|
29
|
+
- name: Verify tag matches pyproject version
|
|
30
|
+
run: |
|
|
31
|
+
if [[ ! "$GITHUB_REF_NAME" =~ ^v[0-9] ]]; then
|
|
32
|
+
echo "Release tag '$GITHUB_REF_NAME' must start with 'v' followed by a digit (e.g. v1.0.0)" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
36
|
+
pkg_version=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
|
|
37
|
+
if [ "$tag" != "$pkg_version" ]; then
|
|
38
|
+
echo "Release tag ($tag) does not match pyproject.toml version ($pkg_version)" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
- name: Build sdist and wheel
|
|
43
|
+
run: python -m build
|
|
44
|
+
|
|
45
|
+
- name: Check distribution metadata
|
|
46
|
+
run: python -m twine check --strict dist/*
|
|
47
|
+
|
|
48
|
+
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
|
|
53
|
+
publish:
|
|
54
|
+
name: Publish to PyPI
|
|
55
|
+
needs: build
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
environment:
|
|
58
|
+
name: pypi
|
|
59
|
+
url: https://pypi.org/p/hotdata-jupyter
|
|
60
|
+
permissions:
|
|
61
|
+
id-token: write
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
64
|
+
with:
|
|
65
|
+
name: dist
|
|
66
|
+
path: dist/
|
|
67
|
+
|
|
68
|
+
- name: Publish via Trusted Publishing
|
|
69
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: GitHub Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v[0-9]*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
name: Create GitHub Release
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
|
|
22
|
+
- name: Read package metadata
|
|
23
|
+
id: meta
|
|
24
|
+
run: |
|
|
25
|
+
pkg_name=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['name'])")
|
|
26
|
+
pkg_version="${GITHUB_REF_NAME#v}"
|
|
27
|
+
echo "name=${pkg_name}" >> "$GITHUB_OUTPUT"
|
|
28
|
+
echo "version=${pkg_version}" >> "$GITHUB_OUTPUT"
|
|
29
|
+
|
|
30
|
+
- name: Extract changelog notes
|
|
31
|
+
id: notes
|
|
32
|
+
run: |
|
|
33
|
+
set -euo pipefail
|
|
34
|
+
version="${GITHUB_REF_NAME#v}"
|
|
35
|
+
if [[ -f CHANGELOG.md ]]; then
|
|
36
|
+
body="$(python scripts/extract-changelog.py "$version")"
|
|
37
|
+
else
|
|
38
|
+
body="Release ${version}."
|
|
39
|
+
fi
|
|
40
|
+
delimiter="EOF_${RANDOM}_${RANDOM}"
|
|
41
|
+
{
|
|
42
|
+
echo "body<<${delimiter}"
|
|
43
|
+
echo "$body"
|
|
44
|
+
echo "${delimiter}"
|
|
45
|
+
} >> "$GITHUB_OUTPUT"
|
|
46
|
+
|
|
47
|
+
- name: Create GitHub Release
|
|
48
|
+
uses: softprops/action-gh-release@1e812e8210a4a8a0b23075e5795f2a4e2b2a0b7 # v2.2.2
|
|
49
|
+
with:
|
|
50
|
+
tag_name: ${{ github.ref_name }}
|
|
51
|
+
name: ${{ steps.meta.outputs.name }} ${{ steps.meta.outputs.version }}
|
|
52
|
+
body: ${{ steps.notes.outputs.body }}
|
|
53
|
+
generate_release_notes: false
|
|
54
|
+
make_latest: true
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Virtual environments
|
|
8
|
+
.env
|
|
9
|
+
.venv
|
|
10
|
+
env/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Testing
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
htmlcov/
|
|
17
|
+
|
|
18
|
+
# Packaging
|
|
19
|
+
*.egg-info/
|
|
20
|
+
dist/
|
|
21
|
+
build/
|
|
22
|
+
|
|
23
|
+
.DS_Store
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## [0.2.1] - 2026-06-22
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Pin `hotdata-runtime>=0.3.0` to pick up its typed-error API.
|
|
16
|
+
- Adopt typed error handling in the managed-database widgets: the create and
|
|
17
|
+
load-table handlers now catch `HotdataError` to surface a clean message and
|
|
18
|
+
run raw SDK exceptions through `classify_sdk_error`, adding a retry hint for
|
|
19
|
+
transient (retryable) failures.
|
|
20
|
+
|
|
21
|
+
## [0.2.0] - 2026-06-22
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Upgrade `hotdata` SDK pin to `>=0.4.1` and `hotdata-runtime` to `>=0.2.4`.
|
|
26
|
+
- Raise core dependency floors to `ipython>=8.18` and `ipywidgets>=8.1`.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Add Ruff lint/format and strict mypy configuration, plus `ruff` and `mypy`
|
|
31
|
+
dev dependencies.
|
|
32
|
+
|
|
33
|
+
## [0.1.1] - 2026-06-01
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Release 0.1.1
|
|
38
|
+
|
|
39
|
+
## [0.1.0] - 2026-05-19
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- Initial release with managed database widgets for Jupyter.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hotdata-jupyter
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Jupyter integration for Hotdata runtime
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: hotdata-runtime>=0.3.0
|
|
8
|
+
Requires-Dist: hotdata>=0.4.1
|
|
9
|
+
Requires-Dist: ipython>=8.18
|
|
10
|
+
Requires-Dist: ipywidgets>=8.1
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# hotdata-jupyter
|
|
14
|
+
|
|
15
|
+
[Jupyter](https://jupyter.org/) helpers for [Hotdata](https://hotdata.dev) — rich query display, workspace selection, managed databases, and a `%%hotdata` cell magic for running SQL directly in cells.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install hotdata-jupyter
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Authentication
|
|
24
|
+
|
|
25
|
+
Set `HOTDATA_API_KEY` in your environment. Optionally set `HOTDATA_WORKSPACE` to pin a specific workspace (the first available workspace is used if unset).
|
|
26
|
+
|
|
27
|
+
## Quickstart
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import hotdata_jupyter as hj
|
|
31
|
+
|
|
32
|
+
client = hj.from_env()
|
|
33
|
+
result = client.execute_sql("SELECT 1 AS ok")
|
|
34
|
+
hj.display_query_result(result)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Workspace selection
|
|
38
|
+
|
|
39
|
+
When `HOTDATA_WORKSPACE` is set, the client connects to that workspace directly. If you have multiple workspaces, use the interactive picker — it renders a dropdown and updates `ws.client` when the selection changes:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
ws = hj.workspace_selector_from_env()
|
|
43
|
+
display(ws.ui)
|
|
44
|
+
client = ws.client
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Running SQL
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
result = client.execute_sql("SELECT * FROM orders LIMIT 10")
|
|
51
|
+
hj.display_query_result(result)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`display_query_result` renders the row count, column names, and a pandas DataFrame inline in the notebook.
|
|
55
|
+
|
|
56
|
+
## Cell magic
|
|
57
|
+
|
|
58
|
+
Load the extension once per session, then use `%%hotdata` cells to write SQL without wrapping it in Python strings. The last active client is picked up automatically:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
%load_ext hotdata_jupyter
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
%%hotdata
|
|
66
|
+
SELECT
|
|
67
|
+
product,
|
|
68
|
+
SUM(amount) AS total
|
|
69
|
+
FROM orders
|
|
70
|
+
GROUP BY product
|
|
71
|
+
ORDER BY total DESC
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Managed databases
|
|
75
|
+
|
|
76
|
+
List the managed databases in your workspace:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
hj.display_managed_databases_panel(client)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Create a database and load parquet files programmatically:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
db = hj.create_managed_database(client, name="sales", tables=["orders"])
|
|
86
|
+
|
|
87
|
+
with open("orders.parquet", "rb") as f:
|
|
88
|
+
loaded = hj.load_managed_table_from_bytes(client, "sales", "orders", f.read())
|
|
89
|
+
|
|
90
|
+
print(f"Loaded {loaded.row_count} rows into {loaded.full_name}")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or use the interactive ipywidgets form:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
writer = hj.managed_database_writer(client)
|
|
97
|
+
writer.display()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Open the demo notebook
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
jupyter lab examples/demo.ipynb
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The demo covers workspace selection, connection listing, schema browsing, query history, and cell magics.
|
|
107
|
+
|
|
108
|
+
## Development
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
uv sync --locked
|
|
112
|
+
uv run pytest
|
|
113
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# hotdata-jupyter
|
|
2
|
+
|
|
3
|
+
[Jupyter](https://jupyter.org/) helpers for [Hotdata](https://hotdata.dev) — rich query display, workspace selection, managed databases, and a `%%hotdata` cell magic for running SQL directly in cells.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install hotdata-jupyter
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Authentication
|
|
12
|
+
|
|
13
|
+
Set `HOTDATA_API_KEY` in your environment. Optionally set `HOTDATA_WORKSPACE` to pin a specific workspace (the first available workspace is used if unset).
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import hotdata_jupyter as hj
|
|
19
|
+
|
|
20
|
+
client = hj.from_env()
|
|
21
|
+
result = client.execute_sql("SELECT 1 AS ok")
|
|
22
|
+
hj.display_query_result(result)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Workspace selection
|
|
26
|
+
|
|
27
|
+
When `HOTDATA_WORKSPACE` is set, the client connects to that workspace directly. If you have multiple workspaces, use the interactive picker — it renders a dropdown and updates `ws.client` when the selection changes:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
ws = hj.workspace_selector_from_env()
|
|
31
|
+
display(ws.ui)
|
|
32
|
+
client = ws.client
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Running SQL
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
result = client.execute_sql("SELECT * FROM orders LIMIT 10")
|
|
39
|
+
hj.display_query_result(result)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`display_query_result` renders the row count, column names, and a pandas DataFrame inline in the notebook.
|
|
43
|
+
|
|
44
|
+
## Cell magic
|
|
45
|
+
|
|
46
|
+
Load the extension once per session, then use `%%hotdata` cells to write SQL without wrapping it in Python strings. The last active client is picked up automatically:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
%load_ext hotdata_jupyter
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
%%hotdata
|
|
54
|
+
SELECT
|
|
55
|
+
product,
|
|
56
|
+
SUM(amount) AS total
|
|
57
|
+
FROM orders
|
|
58
|
+
GROUP BY product
|
|
59
|
+
ORDER BY total DESC
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Managed databases
|
|
63
|
+
|
|
64
|
+
List the managed databases in your workspace:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
hj.display_managed_databases_panel(client)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Create a database and load parquet files programmatically:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
db = hj.create_managed_database(client, name="sales", tables=["orders"])
|
|
74
|
+
|
|
75
|
+
with open("orders.parquet", "rb") as f:
|
|
76
|
+
loaded = hj.load_managed_table_from_bytes(client, "sales", "orders", f.read())
|
|
77
|
+
|
|
78
|
+
print(f"Loaded {loaded.row_count} rows into {loaded.full_name}")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Or use the interactive ipywidgets form:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
writer = hj.managed_database_writer(client)
|
|
85
|
+
writer.display()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Open the demo notebook
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
jupyter lab examples/demo.ipynb
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The demo covers workspace selection, connection listing, schema browsing, query history, and cell magics.
|
|
95
|
+
|
|
96
|
+
## Development
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uv sync --locked
|
|
100
|
+
uv run pytest
|
|
101
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Every release uses `./scripts/release.sh`. Do not bump versions, tag, or create GitHub Releases manually.
|
|
4
|
+
|
|
5
|
+
## One-time setup
|
|
6
|
+
|
|
7
|
+
- Install [GitHub CLI](https://cli.github.com/) (`gh`) and authenticate.
|
|
8
|
+
- Ensure PyPI [trusted publishing](https://docs.pypi.org/trusted-publishers/) is configured for this repo (`publish.yml` uses the `pypi` GitHub environment).
|
|
9
|
+
|
|
10
|
+
## Release steps
|
|
11
|
+
|
|
12
|
+
1. Add user-facing notes under `## [Unreleased]` in `CHANGELOG.md`.
|
|
13
|
+
2. Prepare the release PR:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
./scripts/release.sh prepare patch # or minor | major | 1.2.3
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
3. Merge the PR after CI passes (including the changelog check).
|
|
20
|
+
4. Publish from a clean default branch checkout:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git checkout main # or master for hotdata-marimo
|
|
24
|
+
git pull
|
|
25
|
+
./scripts/release.sh publish
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What happens automatically
|
|
29
|
+
|
|
30
|
+
Pushing a `vX.Y.Z` tag triggers two workflows:
|
|
31
|
+
|
|
32
|
+
| Workflow | Purpose |
|
|
33
|
+
|----------|---------|
|
|
34
|
+
| `publish.yml` | Build wheel/sdist and publish to PyPI |
|
|
35
|
+
| `release.yml` | Create the GitHub Release with notes from `CHANGELOG.md` |
|
|
36
|
+
|
|
37
|
+
## Enforcement
|
|
38
|
+
|
|
39
|
+
- **PR check** (`check-release.yml`): if `pyproject.toml` version changes, `CHANGELOG.md` must contain a matching `## [X.Y.Z]` section.
|
|
40
|
+
- **Tag check** (`publish.yml`): the tag (without `v`) must match `[project].version` in `pyproject.toml`.
|
|
41
|
+
- **Publish guard** (`release.sh publish`): refuses to tag if the changelog section is missing.
|
|
42
|
+
|
|
43
|
+
Together, these make it hard to ship a version without changelog notes or a GitHub Release.
|