Skip to content

Commit

Permalink
Enable Python API in the JupyterLite deployment (#412)
Browse files Browse the repository at this point in the history
* Don't change paths to absolute backend paths

* Enable jupytergis_lab in WASM platform

* Make the model collaborative in JupyterLite

* Deploy JupyterLite with collaborative drive

* Review

* Pin python=3.12

Co-authored-by: martinRenou <martin.renou@gmail.com>

* Pin micromamba v2.0.5

* Install myst-parser from conda

* Fix typo

* Fix paths

* Show error message in the front-end when there is no collaborative drive

* Linter

* Handle file operations in the front-end

* Up

* Update yjs widgets

* Remove unwanted test

* Cleanup

* Remove Github pages build

* Show console as early as possible

* More docs building removal

* Unpin my-jupyter-shared-drive

---------

Co-authored-by: martinRenou <martin.renou@gmail.com>
  • Loading branch information
davidbrochart and martinRenou authored Feb 7, 2025
1 parent aa2ef32 commit 89e4de9
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 187 deletions.
71 changes: 0 additions & 71 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,74 +250,3 @@ jobs:
- uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1
with:
ignore_links: 'lite/'

build-docs-and-lite:
name: Build docs with JupyterLite deployment
needs: build
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Conda environment with Micromamba
uses: mamba-org/setup-micromamba@v2
with:
micromamba-version: '1.5.5-0'
environment-name: build-env
create-args: >-
python=3.10
pip
jupyterlite-core>=0.4.0,<0.6.0
jupyterlite-xeus>=2,<3
jupyterlite-sphinx
sphinx
sphinx-tabs
pydata-sphinx-theme
sphinx-autodoc-typehints
sphinx-exercise
sphinx-togglebutton
myst-parser<4.0.0
- name: Download extension package
uses: actions/download-artifact@v4
with:
name: extension-artifacts

- name: Install the extension
shell: bash -l {0}
run: |
set -eux
cp ./jupytergis_core/dist/jupytergis*.whl ./jupytergis_lab/dist/jupytergis*.whl ./jupytergis_qgis/dist/jupytergis*.whl .
python -m pip install jupytergis*.whl
- name: Build the docs site
shell: bash -l {0}
working-directory: docs
run: |
set -eux
sphinx-build . dist
- name: Upload artifact
id: upload-docs-artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./docs/dist
retention-days: 30

deploy:
needs: build-docs-and-lite
if: github.ref == 'refs/heads/main'
permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
20 changes: 6 additions & 14 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ build:
# Override the create_environment step (undocumented feature) to create
# multiple environments.
create_environment:
# Pin micromamba
- /bin/bash --login -c "micromamba self-update --version 2.0.5"
# Create the env for building the docs
- /bin/bash --login -c "micromamba env create -n jupytergis-docs -f docs/environment-docs.yml"
# Create the isolated env for building JupyterGIS
- /bin/bash --login -c "micromamba create -n jupytergis-build -c conda-forge yarn=3 hatch pip python=3.12"
- /bin/bash --login -c "micromamba run -n jupytergis-build pip install -r requirements-build.txt"
- /bin/bash --login -c "micromamba create -n jupytergis-build -c conda-forge nodejs hatch pip python=3.13"
- /bin/bash --login -c "micromamba run -n jupytergis-build pip install 'jupyterlab==4.3' 'datamodel-code-generator>=0.23.0'"

# Override the install step to do nothing - we already created the envs
install:
Expand All @@ -33,18 +35,8 @@ build:
# Before building the docs, build JupyterGIS in its isolated environment,
# then install the wheels into the docs environment.
pre_build:
- /bin/bash --login -c "micromamba run -n jupytergis-build yarn install"
- /bin/bash --login -c "micromamba run -n jupytergis-build yarn dev"
- /bin/bash --login -c "micromamba run -n jupytergis-build jupyter labextension list 2>&1 | grep -ie 'jupytergis-core.*OK'"
- /bin/bash --login -c "micromamba run -n jupytergis-build jupyter labextension list 2>&1 | grep -ie 'jupytergis-lab.*OK'"
- /bin/bash --login -c "micromamba run -n jupytergis-build yarn build:packages"

- |-
/bin/bash --login -c "micromamba run -n jupytergis-docs \
python -m pip install \
$(ls ./python/jupytergis_core/dist/jupytergis*.whl) \
$(ls ./python/jupytergis_lab/dist/jupytergis*.whl) \
$(ls ./python/jupytergis_qgis/dist/jupytergis*.whl)"
- /bin/bash --login -c "micromamba run -n jupytergis-build jlpm install"
- /bin/bash --login -c "micromamba run -n jupytergis-build jlpm build"

build:
html:
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[![lite-badge]][lite] [![docs-badge]][docs]

[lite-badge]: https://jupyterlite.rtfd.io/en/latest/_static/badge.svg
[lite]: https://geojupyter.github.io/jupytergis/lite/lab/index.html?path=france_hiking.jGIS/
[lite]: https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html?path=france_hiking.jGIS/
[docs-badge]: https://readthedocs.org/projects/jupytergis/badge/?version=latest
[docs]: https://geojupyter.github.io/jupytergis
[docs]: https://jupytergis.readthedocs.io

⚠️ This extension is work in progress. Features and APIs are subject to change quickly. ⚠️

Expand All @@ -18,7 +18,7 @@
- **QGIS File Support**: Load, visualize, and manipulate QGIS project files (`.qgs`, `.qgz`), and other GIS data formats.
- **Interactive Maps**: Render interactive maps and geospatial visualizations within Jupyter notebooks using the JupyterGIS Python API.

## [🪄 Try JupyterGIS now! ✨](https://geojupyter.github.io/jupytergis/lite/lab/index.html?path=france_hiking.jGIS)
## [🪄 Try JupyterGIS now! ✨](https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html?path=france_hiking.jGIS)

This demo runs a JupyterLab instance entirely in your browser with WebAssembly! 🤯

Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"../examples/*.gif",
"../examples/*.geojson",
"../examples/*.tif",
"../examples/*.ipynb",
]
jupyterlite_dir = "."
jupyterlite_config = "jupyter_lite_config.json"
Expand Down
10 changes: 3 additions & 7 deletions docs/environment-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@ dependencies:
- pip # Needed to install jupytergis wheels in RTD build

# Build docs & JupyterLite
- jupyterlite-core>=0.4.0,<0.6.0
- jupyterlite-xeus>=2,<3
- jupyterlite-core
- jupyterlite-xeus>=3.1.3,<4
- jupyterlite-sphinx
- sphinx
- sphinx-tabs
- pydata-sphinx-theme
- sphinx-autodoc-typehints
- sphinx-exercise
- sphinx-togglebutton

- myst-parser
- xeus-python # TODO: Do we need this?

# Install myst-parser via pip
- pip:
- myst-parser<4.0.0
14 changes: 13 additions & 1 deletion docs/environment.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
name: xeus-python-kernel
channels:
- https://repo.mamba.pm/emscripten-forge
- https://prefix.dev/emscripten-forge-dev
- conda-forge
dependencies:
- python=3.13
- pip
- xeus-python
- requests
- jupyter_ydoc=2.1.5
- ypywidgets>=0.9.6,<0.10.0
- comm>=0.1.2,<0.2.0
- pydantic>=2,<3
- pip:
- yjs-widgets>=0.4,<0.5
- my-jupyter-shared-drive
- ../python/jupytergis_lab
- ../python/jupytergis_core
8 changes: 1 addition & 7 deletions docs/jupyter-lite.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
{
"jupyter-lite-schema-version": 0,
"jupyter-config-data": {
"appName": "JupyterGIS App",
"disabledExtensions": [
"@jupyter/collaboration-extension",
"@jupyter/docprovider-extension"
]
}
"jupyter-config-data": {}
}
6 changes: 3 additions & 3 deletions packages/base/src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ export class JupyterGISPanel extends SplitPanel {

(this._consoleTracker.widgetAdded as any).emit(consolePanel);
await consolePanel.sessionContext.ready;
await consolePanel.console.inject(
`from jupytergis_lab import GISDocument\ndoc = GISDocument("${jgisPath}")`
);
this.addWidget(this._consoleView);
this.setRelativeSizes([2, 1]);
this._consoleOpened = true;
await consolePanel.console.inject(
`from jupytergis_lab import GISDocument\ndoc = GISDocument("${jgisPath}")`
);
consolePanel.console.sessionContext.kernelChanged.connect((_, arg) => {
if (!arg.newValue) {
this.removeConsole();
Expand Down
3 changes: 1 addition & 2 deletions python/jupytergis_core/src/jgisplugin/modelfactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ export class JupyterGISModelFactory
/**
* Whether the model is collaborative or not.
*/
readonly collaborative =
document.querySelectorAll('[data-jupyter-lite-root]')[0] === undefined;
readonly collaborative = true;

/**
* The name of the model.
Expand Down
7 changes: 0 additions & 7 deletions python/jupytergis_lab/jupytergis_lab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@

__version__ = "dev"

import sys

if sys.platform == "emscripten":
raise ImportError(
"Cannot use the JupyterGIS Python API in a JupyterLite kernel yet"
)

from .notebook import GISDocument # noqa


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
LayerType,
SourceType,
)
from .utils import normalize_path

logger = logging.getLogger(__file__)

Expand Down Expand Up @@ -64,11 +63,6 @@ def __init__(

comm_metadata = GISDocument._path_to_comm(path)

# Create an empty project file if it does not exist
if comm_metadata["path"] and not os.path.isfile(comm_metadata["path"]):
with open(comm_metadata["path"], "w") as fd:
fd.write("{}")

ydoc = Doc()

super().__init__(
Expand Down Expand Up @@ -708,7 +702,7 @@ def _path_to_comm(cls, filePath: Optional[str]) -> Dict:
contentType = None

if filePath is not None:
path = normalize_path(filePath)
path = filePath
file_name = Path(path).name
try:
ext = file_name.split(".")[1].lower()
Expand Down
17 changes: 0 additions & 17 deletions python/jupytergis_lab/jupytergis_lab/notebook/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@
from jupytergis_lab import GISDocument


class ProjectCreation(unittest.TestCase):
filename = "test.jgis"

def setUp(self):
if os.path.isfile(self.filename):
os.remove(self.filename)

def tearDown(self):
if os.path.isfile(self.filename):
os.remove(self.filename)

def test_creation(self):
self.doc = GISDocument(self.filename)

assert os.path.isfile(self.filename)


class VectorTileTests(unittest.TestCase):
def setUp(self):
self.doc = GISDocument()
Expand Down
8 changes: 0 additions & 8 deletions python/jupytergis_lab/jupytergis_lab/notebook/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
from enum import Enum
from urllib.parse import urljoin
import requests
Expand All @@ -16,10 +15,3 @@ def multi_urljoin(*parts) -> str:
parts[0],
"/".join(part for part in parts[1:]),
)


def normalize_path(path: str) -> str:
if os.path.isabs(path):
return path
else:
return os.path.abspath(os.path.join(os.getcwd(), path))
2 changes: 1 addition & 1 deletion python/jupytergis_lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"@lumino/messaging": "^2.0.0",
"@lumino/widgets": "^2.0.0",
"react": "^18.0.1",
"yjs-widgets": "^0.3.9"
"yjs-widgets": "^0.4"
},
"devDependencies": {
"@jupyterlab/builder": "^4.3.0",
Expand Down
2 changes: 1 addition & 1 deletion python/jupytergis_lab/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies = [
"requests",
"jupyter-ydoc>=2,<4",
"ypywidgets>=0.9.0,<0.10.0",
"yjs-widgets>=0.3.9,<0.4",
"yjs-widgets>=0.4,<0.5",
"comm>=0.1.2,<0.2.0",
"pydantic>=2,<3",
"jupytergis_core>=0.1.0,<1",
Expand Down
Loading

0 comments on commit 89e4de9

Please sign in to comment.