Skip to content

Commit 7a85bca

Browse files
committed
update kepler-jupyter to 0.4.0
1 parent cc33b0c commit 7a85bca

32 files changed

Lines changed: 6635 additions & 55 deletions
Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
name: Build KeplerGL Python and NPM Packages
1+
name: Build and Publish KeplerGL Python Package
22

3-
on: push
3+
on:
4+
push:
5+
workflow_dispatch:
6+
inputs:
7+
prerelease:
8+
description: 'Publish as prerelease (uncheck for official release)'
9+
required: false
10+
type: boolean
11+
default: true
412

513
jobs:
614
build_and_publish:
@@ -11,76 +19,81 @@ jobs:
1119
steps:
1220
- uses: actions/checkout@v4
1321

14-
# use Volta to manage yarn/node versions
15-
- uses: volta-cli/action@v4
22+
- name: Install uv
23+
uses: astral-sh/setup-uv@v4
1624

17-
- name: Set up Python 3.9
18-
uses: actions/setup-python@v2
25+
- name: Set up Python 3.11
26+
run: uv python install 3.11
27+
28+
- name: Setup Node.js
29+
uses: actions/setup-node@v4
1930
with:
20-
python-version: 3.9
31+
node-version: '20'
2132

22-
- name: Install dependencies
23-
run: |
24-
python -m pip install --upgrade pip
25-
pip install twine virtualenv
33+
- name: Install Python dependencies
34+
working-directory: bindings/python
35+
run: uv sync --dev
2636

27-
- name: Build KeplerGL
37+
- name: Install npm dependencies
38+
working-directory: bindings/python
39+
run: npm ci
40+
41+
- name: Build TypeScript
42+
working-directory: bindings/python
2843
env:
2944
MapboxAccessTokenJupyter: ${{ secrets.mapbox_jupyter_token }}
30-
NODE_OPTIONS: --openssl-legacy-provider
31-
run: |
32-
python -m virtualenv venv
33-
source venv/bin/activate
34-
pip install jupyter jupyterlab jupyter-packaging
35-
cd bindings/kepler.gl-jupyter
36-
python setup.py sdist
45+
run: npm run build
46+
47+
- name: Type check
48+
working-directory: bindings/python
49+
run: npm run typecheck
50+
51+
- name: Build Python package
52+
working-directory: bindings/python
53+
run: uv build
3754

3855
- name: Test KeplerGL
56+
working-directory: bindings/python
3957
run: |
40-
source venv/bin/activate
41-
pip install bindings/kepler.gl-jupyter/dist/*.tar.gz
42-
if [ ! -f "venv/share/jupyter/nbextensions/keplergl-jupyter/index.js" ]; then
43-
venv/bin/jupyter nbextension install --py --sys-prefix keplergl
44-
venv/bin/jupyter nbextension enable --py --sys-prefix keplergl
45-
fi
46-
venv/bin/jupyter nbconvert --execute bindings/kepler.gl-jupyter/notebooks/DataFrame.ipynb --to python
47-
python bindings/kepler.gl-jupyter/notebooks/DataFrame.py
58+
uv pip install dist/*.whl
59+
uv run pytest
4860
4961
- name: Create artifact
5062
uses: actions/upload-artifact@v4
5163
with:
5264
name: keplergl-pypi
53-
path: bindings/kepler.gl-jupyter/dist/
65+
path: bindings/python/dist/
5466

55-
- name: Check Release Tag
56-
id: check-tag
67+
- name: Check version format
68+
if: github.event_name == 'workflow_dispatch'
69+
working-directory: bindings/python
5770
run: |
58-
if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+([a|b][0-9])?-jupyter$ ]]; then
59-
echo ::set-output name=publish::true
71+
VERSION=$(grep -Po '(?<=^version = ")[^"]+' pyproject.toml)
72+
echo "Package version: $VERSION"
73+
74+
# Check if version contains prerelease indicators (a, b, rc, dev)
75+
if [[ "$VERSION" =~ (a|b|rc|dev)[0-9]+ ]]; then
76+
IS_PRERELEASE_VERSION=true
77+
else
78+
IS_PRERELEASE_VERSION=false
79+
fi
80+
81+
echo "Is prerelease version: $IS_PRERELEASE_VERSION"
82+
echo "Publishing as prerelease: ${{ inputs.prerelease }}"
83+
84+
# Fail if mismatch between version format and publish type
85+
if [[ "${{ inputs.prerelease }}" == "true" && "$IS_PRERELEASE_VERSION" == "false" ]]; then
86+
echo "::error::Publishing as prerelease but version '$VERSION' does not have a prerelease suffix (e.g., 0.4.0a1, 0.4.0b1, 0.4.0rc1)"
87+
exit 1
88+
fi
89+
90+
if [[ "${{ inputs.prerelease }}" == "false" && "$IS_PRERELEASE_VERSION" == "true" ]]; then
91+
echo "::error::Cannot publish official release with prerelease version '$VERSION'. Please update the version in pyproject.toml."
92+
exit 1
6093
fi
6194
62-
- name: Setup Node.js
63-
uses: actions/setup-node@v3
64-
with:
65-
node-version: '18'
66-
registry-url: 'https://registry.npmjs.org'
67-
68-
- name: Publish kepler-jupyter to NPM
69-
if: steps.check-tag.outputs.publish == 'true'
70-
env:
71-
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
72-
MapboxAccessTokenJupyter: ${{ secrets.mapbox_jupyter_token }}
73-
run: |
74-
source venv/bin/activate
75-
cd bindings/kepler.gl-jupyter/js
76-
echo "//registry.npmjs.org/:_authToken=${{ secrets.npm_token }}" > .npmrc
77-
npm config set registry https://registry.npmjs.org/
78-
npm whoami
79-
npm config ls
80-
npm publish --verbose --access public
81-
82-
- name: Publish KeplerGL to Pypi
83-
if: steps.check-tag.outputs.publish == 'true'
95+
- name: Publish to PyPI
96+
if: github.event_name == 'workflow_dispatch'
8497
uses: pypa/gh-action-pypi-publish@release/v1
8598
with:
86-
packages-dir: bindings/kepler.gl-jupyter/dist/
99+
packages-dir: bindings/python/dist/

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ build/
88
umd/
99
*/**/dist/
1010

11+
__pycache__/
12+
.pytest_cache/
13+
.ipynb_checkpoints/
14+
bindings/python/keplergl/static/
1115
typedoc/
1216

1317
examples/**/yarn.lock

bindings/python/DEVELOPMENT.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Development Guide
2+
3+
This guide explains how to set up kepler.gl for Jupyter for local development.
4+
5+
## Prerequisites
6+
7+
- Python >= 3.9
8+
- Node.js (for building the frontend)
9+
- JupyterLab >= 4.0 or Notebook >= 7.0
10+
11+
## Installation
12+
13+
Navigate to the `bindings/python` directory:
14+
15+
```bash
16+
cd bindings/python
17+
```
18+
19+
### 1. Install JavaScript dependencies and build the frontend
20+
21+
```bash
22+
npm install
23+
npm run build
24+
```
25+
26+
### 2. Install Python package in development mode
27+
28+
Using **uv** (recommended):
29+
30+
```bash
31+
uv sync --dev
32+
```
33+
34+
Or using **pip**:
35+
36+
```bash
37+
pip install -e ".[dev]"
38+
```
39+
40+
### 3. Start Jupyter
41+
42+
```bash
43+
# With uv
44+
uv run jupyter lab
45+
46+
# Or with pip
47+
jupyter lab
48+
```
49+
50+
## Development with Hot Reload
51+
52+
For active development with automatic rebuilding of the TypeScript/JavaScript:
53+
54+
```bash
55+
# Terminal 1: Watch for TypeScript changes
56+
npm run dev
57+
58+
# Terminal 2: Run Jupyter
59+
uv run jupyter lab
60+
```
61+
62+
The `npm run dev` command watches for changes in the `src/` directory and automatically rebuilds the widget JavaScript.
63+
64+
## Quick Test
65+
66+
```python
67+
from keplergl import KeplerGl
68+
69+
# Create a map
70+
map = KeplerGl(height=400)
71+
map
72+
```
73+
74+
## Running Tests
75+
76+
```bash
77+
uv run pytest
78+
```
79+
80+
## Available npm Scripts
81+
82+
- `npm run build` - Build TypeScript to `keplergl/static/`
83+
- `npm run dev` - Build with watch mode for development
84+
- `npm run typecheck` - Run TypeScript type checking
85+
- `npm run lint` - Run ESLint on source files
86+
87+
## Publishing to PyPI
88+
89+
Publishing is done manually via GitHub Actions using the "Run workflow" button.
90+
91+
### Version Format
92+
93+
The version in `pyproject.toml` determines what type of release you can publish:
94+
95+
- **Prerelease versions**: Must have a suffix like `a`, `b`, `rc`, or `dev` followed by a number
96+
- Examples: `0.4.0a1` (alpha), `0.4.0b1` (beta), `0.4.0rc1` (release candidate), `0.4.0.dev1` (development)
97+
- **Official versions**: Clean semantic versions without any suffix
98+
- Examples: `0.4.0`, `1.0.0`
99+
100+
### Publishing Steps
101+
102+
1. **Update the version** in both files:
103+
- `pyproject.toml` (line: `version = "x.x.x"`)
104+
- `keplergl/_version.py` (line: `__version__ = "x.x.x"`)
105+
106+
2. **Go to GitHub Actions** → "Build and Publish KeplerGL Python Package" workflow
107+
108+
3. **Click "Run workflow"** and select the appropriate option:
109+
- **Prerelease** (checked by default): Publishes to PyPI as a prerelease. Version must have a prerelease suffix.
110+
- **Official release** (unchecked): Publishes to PyPI as an official release. Version must be a clean version.
111+
112+
4. The workflow will:
113+
- Build and test the package
114+
- Validate that the version format matches the publish type
115+
- Publish to PyPI if validation passes
116+
117+
### Validation Rules
118+
119+
| Checkbox | Version | Result |
120+
|----------|---------|--------|
121+
| ✓ Prerelease | `0.4.0a1` | ✅ Publishes |
122+
| ✓ Prerelease | `0.4.0` | ❌ Fails (version must have prerelease suffix) |
123+
| ☐ Official | `0.4.0` | ✅ Publishes |
124+
| ☐ Official | `0.4.0a1` | ❌ Fails (version must not have prerelease suffix) |

bindings/python/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# kepler.gl for Jupyter
2+
3+
[![PyPI version](https://img.shields.io/pypi/v/keplergl.svg)](https://pypi.org/project/keplergl/)
4+
[![PyPI prerelease](https://img.shields.io/pypi/v/keplergl.svg?include_prereleases&label=prerelease)](https://pypi.org/project/keplergl/#history)
5+
6+
This is the [kepler.gl](http://kepler.gl) Jupyter widget, an advanced geospatial visualization tool for rendering large-scale interactive maps in Jupyter Notebook and JupyterLab.
7+
8+
9+
10+
## Installation
11+
12+
```shell
13+
pip install keplergl
14+
```
15+
16+
### Prerequisites
17+
- Python >= 3.9
18+
- JupyterLab >= 4.0 or Notebook >= 7.0
19+
20+
## Quick Start
21+
22+
```python
23+
from keplergl import KeplerGl
24+
25+
# Create a map
26+
map = KeplerGl(height=400)
27+
28+
# Add data
29+
map.add_data(data=df, name='my_data')
30+
31+
# Display the map
32+
map
33+
```
34+
35+
## Documentation
36+
37+
For full documentation, visit [https://docs.kepler.gl/docs/keplergl-jupyter](https://docs.kepler.gl/docs/keplergl-jupyter).
38+
39+
## License
40+
41+
MIT

bindings/python/esbuild.config.mjs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import * as esbuild from 'esbuild';
2+
import path from 'path';
3+
import {fileURLToPath} from 'url';
4+
import {createRequire} from 'module';
5+
6+
const require = createRequire(import.meta.url);
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
8+
9+
const isWatch = process.argv.includes('--watch');
10+
11+
// Resolve apache-arrow to a single location
12+
const arrowPath = path.dirname(require.resolve('apache-arrow'));
13+
14+
const buildOptions = {
15+
entryPoints: ['src/index.ts'],
16+
bundle: true,
17+
format: 'esm',
18+
outdir: 'keplergl/static',
19+
outExtension: {'.js': '.js'},
20+
loader: {
21+
'.ts': 'ts',
22+
'.tsx': 'tsx',
23+
'.css': 'css'
24+
},
25+
external: [],
26+
minify: !isWatch,
27+
sourcemap: isWatch,
28+
target: ['es2020'],
29+
define: {
30+
'process.env.NODE_ENV': isWatch ? '"development"' : '"production"'
31+
},
32+
// Use alias to ensure single instance of apache-arrow
33+
alias: {
34+
'apache-arrow': arrowPath
35+
}
36+
};
37+
38+
async function build() {
39+
if (isWatch) {
40+
const ctx = await esbuild.context(buildOptions);
41+
await ctx.watch();
42+
console.log('Watching for changes...');
43+
} else {
44+
await esbuild.build(buildOptions);
45+
console.log('Build complete!');
46+
}
47+
}
48+
49+
build().catch(() => process.exit(1));
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""Kepler.gl Jupyter Widget."""
2+
3+
from .widget import KeplerGl
4+
from ._version import __version__
5+
6+
__all__ = ["KeplerGl", "__version__"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""Version information."""
2+
3+
__version__ = "0.4.0"

0 commit comments

Comments
 (0)