From cf58ed7fe7f654d7f58be1ab5b38ef962787d634 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Mon, 3 Feb 2025 14:53:34 +0100 Subject: [PATCH 01/21] Don't change paths to absolute backend paths --- .../jupytergis_lab/notebook/gis_document.py | 3 +-- python/jupytergis_lab/jupytergis_lab/notebook/utils.py | 8 -------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py b/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py index 3d0bf9b27..bfa503ffd 100644 --- a/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py +++ b/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py @@ -29,7 +29,6 @@ LayerType, SourceType, ) -from .utils import normalize_path logger = logging.getLogger(__file__) @@ -708,7 +707,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() diff --git a/python/jupytergis_lab/jupytergis_lab/notebook/utils.py b/python/jupytergis_lab/jupytergis_lab/notebook/utils.py index 36ca3a583..064d09c97 100644 --- a/python/jupytergis_lab/jupytergis_lab/notebook/utils.py +++ b/python/jupytergis_lab/jupytergis_lab/notebook/utils.py @@ -1,4 +1,3 @@ -import os from enum import Enum from urllib.parse import urljoin import requests @@ -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)) From d1ce4544062a9143963baa4eadc5246b70ca948f Mon Sep 17 00:00:00 2001 From: David Brochart Date: Thu, 30 Jan 2025 12:23:35 +0100 Subject: [PATCH 02/21] Enable jupytergis_lab in WASM platform --- python/jupytergis_lab/jupytergis_lab/__init__.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/python/jupytergis_lab/jupytergis_lab/__init__.py b/python/jupytergis_lab/jupytergis_lab/__init__.py index 47c21a2fc..0d4f3c58f 100644 --- a/python/jupytergis_lab/jupytergis_lab/__init__.py +++ b/python/jupytergis_lab/jupytergis_lab/__init__.py @@ -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 From 2054511dd42cc1ecd3fa408a85964ba9206744f1 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Thu, 30 Jan 2025 17:00:22 +0100 Subject: [PATCH 03/21] Make the model collaborative in JupyterLite --- python/jupytergis_core/src/jgisplugin/modelfactory.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/jupytergis_core/src/jgisplugin/modelfactory.ts b/python/jupytergis_core/src/jgisplugin/modelfactory.ts index f4eeaad3c..38c1967c4 100644 --- a/python/jupytergis_core/src/jgisplugin/modelfactory.ts +++ b/python/jupytergis_core/src/jgisplugin/modelfactory.ts @@ -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. From 882e055869bcf51ade5c8b436c1dd71a337ceaca Mon Sep 17 00:00:00 2001 From: David Brochart Date: Tue, 4 Feb 2025 21:54:53 +0100 Subject: [PATCH 04/21] Deploy JupyterLite with collaborative drive --- .github/workflows/build.yml | 4 ++-- .readthedocs.yaml | 18 ++++-------------- docs/conf.py | 7 +------ docs/environment-docs.yml | 6 +++--- docs/environment.yml | 16 +++++++++++++++- docs/jupyter-lite.json | 6 +----- 6 files changed, 26 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a88eca8eb..2f28d0acb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -266,10 +266,10 @@ jobs: micromamba-version: '1.5.5-0' environment-name: build-env create-args: >- - python=3.10 + python=3.13 pip jupyterlite-core>=0.4.0,<0.6.0 - jupyterlite-xeus>=2,<3 + jupyterlite-xeus>=3.1.3,<4 jupyterlite-sphinx sphinx sphinx-tabs diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1b6be8391..51cd3723e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -23,8 +23,8 @@ build: # 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: @@ -33,18 +33,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: diff --git a/docs/conf.py b/docs/conf.py index 54459086c..9eb83daa8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -34,12 +34,7 @@ language = "en" jupyterlite_contents = [ - "../examples/*.jGIS", - "../examples/*.json", - "../examples/*.zip", - "../examples/*.gif", - "../examples/*.geojson", - "../examples/*.tif", + "../examples/*", ] jupyterlite_dir = "." jupyterlite_config = "jupyter_lite_config.json" diff --git a/docs/environment-docs.yml b/docs/environment-docs.yml index 3f1d8319d..4fad85258 100644 --- a/docs/environment-docs.yml +++ b/docs/environment-docs.yml @@ -3,12 +3,12 @@ channels: - conda-forge - nodefaults dependencies: - - python=3.12 + - python=3.13 - 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 diff --git a/docs/environment.yml b/docs/environment.yml index cf391c4ef..ca5fc33c1 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -1,6 +1,20 @@ 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 + - emscripten-abi=3.1.73 + - requests + - jupyter_ydoc=2.1.5 + - ypywidgets>=0.9.6,<0.10.0 + - yjs-widgets>=0.3.5,<0.4 + - comm>=0.1.2,<0.2.0 + - pydantic>=2,<3 + - pip: + - my-jupyter-shared-drive==0.1.13 + - jupyterlab==4.3 + - python/jupytergis_lab + - python/jupytergis_core diff --git a/docs/jupyter-lite.json b/docs/jupyter-lite.json index b865b7086..dcb590d80 100644 --- a/docs/jupyter-lite.json +++ b/docs/jupyter-lite.json @@ -1,10 +1,6 @@ { "jupyter-lite-schema-version": 0, "jupyter-config-data": { - "appName": "JupyterGIS App", - "disabledExtensions": [ - "@jupyter/collaboration-extension", - "@jupyter/docprovider-extension" - ] + "appName": "JupyterGIS App" } } From 65c89eda44de3ef83083d1d675b8a395dd26ebd4 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 09:21:47 +0100 Subject: [PATCH 05/21] Review --- docs/conf.py | 8 +++++++- docs/environment.yml | 2 -- docs/jupyter-lite.json | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9eb83daa8..344cb8eab 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -34,7 +34,13 @@ language = "en" jupyterlite_contents = [ - "../examples/*", + "../examples/*.jGIS", + "../examples/*.json", + "../examples/*.zip", + "../examples/*.gif", + "../examples/*.geojson", + "../examples/*.tif", + "../examples/*.ipynb", ] jupyterlite_dir = "." jupyterlite_config = "jupyter_lite_config.json" diff --git a/docs/environment.yml b/docs/environment.yml index ca5fc33c1..ec95e76da 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -6,7 +6,6 @@ dependencies: - python=3.13 - pip - xeus-python - - emscripten-abi=3.1.73 - requests - jupyter_ydoc=2.1.5 - ypywidgets>=0.9.6,<0.10.0 @@ -15,6 +14,5 @@ dependencies: - pydantic>=2,<3 - pip: - my-jupyter-shared-drive==0.1.13 - - jupyterlab==4.3 - python/jupytergis_lab - python/jupytergis_core diff --git a/docs/jupyter-lite.json b/docs/jupyter-lite.json index dcb590d80..40da604e0 100644 --- a/docs/jupyter-lite.json +++ b/docs/jupyter-lite.json @@ -1,6 +1,5 @@ { "jupyter-lite-schema-version": 0, "jupyter-config-data": { - "appName": "JupyterGIS App" } } From 3e08df72041d565a472e06d09665b09fe4b0f64d Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 09:42:16 +0100 Subject: [PATCH 06/21] Pin python=3.12 Co-authored-by: martinRenou --- docs/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/environment-docs.yml b/docs/environment-docs.yml index 4fad85258..028907d27 100644 --- a/docs/environment-docs.yml +++ b/docs/environment-docs.yml @@ -3,7 +3,7 @@ channels: - conda-forge - nodefaults dependencies: - - python=3.13 + - python=3.12 - pip # Needed to install jupytergis wheels in RTD build # Build docs & JupyterLite From 8ce4b5739cc4e89cb6a9b37302be8cb2b9ee7038 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 15:46:37 +0100 Subject: [PATCH 07/21] Pin micromamba v2.0.5 --- .readthedocs.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 51cd3723e..b7dcc9afa 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,6 +20,8 @@ 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 From c190b82ec836db19882e31cb4a41b37da40e0ddd Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 15:55:06 +0100 Subject: [PATCH 08/21] Install myst-parser from conda --- docs/environment-docs.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/environment-docs.yml b/docs/environment-docs.yml index 028907d27..28feb5133 100644 --- a/docs/environment-docs.yml +++ b/docs/environment-docs.yml @@ -16,9 +16,5 @@ dependencies: - 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 From d4ad3d13f6bdc4594d047124269d4cd7bb47fc40 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 15:59:51 +0100 Subject: [PATCH 09/21] Fix typo --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index b7dcc9afa..84b970360 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -26,7 +26,7 @@ build: - /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 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'" + - /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: From 4c00edca2f17b05b4c489003813957100dec3007 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Wed, 5 Feb 2025 16:09:25 +0100 Subject: [PATCH 10/21] Fix paths --- docs/environment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/environment.yml b/docs/environment.yml index ec95e76da..5cc16df76 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -14,5 +14,5 @@ dependencies: - pydantic>=2,<3 - pip: - my-jupyter-shared-drive==0.1.13 - - python/jupytergis_lab - - python/jupytergis_core + - ../python/jupytergis_lab + - ../python/jupytergis_core From 27456b96760f02419a3094fb5e2e5baee7b20af8 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Thu, 6 Feb 2025 16:22:01 +0100 Subject: [PATCH 11/21] Show error message in the front-end when there is no collaborative drive --- python/jupytergis_lab/src/notebookrenderer.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/python/jupytergis_lab/src/notebookrenderer.ts b/python/jupytergis_lab/src/notebookrenderer.ts index af15ae3b6..1954a5e54 100644 --- a/python/jupytergis_lab/src/notebookrenderer.ts +++ b/python/jupytergis_lab/src/notebookrenderer.ts @@ -16,6 +16,7 @@ import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; +import { showErrorMessage } from '@jupyterlab/apputils'; import { ConsolePanel } from '@jupyterlab/console'; import { PathExt } from '@jupyterlab/coreutils'; import { NotebookPanel } from '@jupyterlab/notebook'; @@ -132,16 +133,20 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { console.error('Missing IJupyterYWidgetManager token!'); return; } - if (!drive) { - console.error( - 'Cannot setup JupyterGIS Python API without a collaborative drive' - ); - return; - } + class YJupyterGISModelFactory extends YJupyterGISModel { ydocFactory(commMetadata: ICommMetadata): Y.Doc { const { path, format, contentType } = commMetadata; const fileFormat = format as Contents.FileFormat; + + if (!drive) { + showErrorMessage( + 'Error using the JupyterGIS Python API', + 'You cannot use the JupyterGIS Python API without a collaborative drive. You need to install a package providing collaboration features (e.g. jupyter-collaboration).' + ); + throw new Error('Failed to create the YDoc without a collaborative drive'); + } + const sharedModel = drive!.sharedModelFactory.createNew({ path, format: fileFormat, From 0a37f8c426ab3f0edc7ca0beead50450cd02b9b0 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Thu, 6 Feb 2025 16:22:30 +0100 Subject: [PATCH 12/21] Linter --- docs/environment.yml | 6 +++--- docs/jupyter-lite.json | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/environment.yml b/docs/environment.yml index 5cc16df76..1655ab0d2 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -13,6 +13,6 @@ dependencies: - comm>=0.1.2,<0.2.0 - pydantic>=2,<3 - pip: - - my-jupyter-shared-drive==0.1.13 - - ../python/jupytergis_lab - - ../python/jupytergis_core + - my-jupyter-shared-drive==0.1.13 + - ../python/jupytergis_lab + - ../python/jupytergis_core diff --git a/docs/jupyter-lite.json b/docs/jupyter-lite.json index 40da604e0..1907b9a8e 100644 --- a/docs/jupyter-lite.json +++ b/docs/jupyter-lite.json @@ -1,5 +1,4 @@ { "jupyter-lite-schema-version": 0, - "jupyter-config-data": { - } + "jupyter-config-data": {} } From 7dd2bf99dc760d6bd2bb7133420e4d4db3d1f320 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Thu, 6 Feb 2025 18:26:04 +0100 Subject: [PATCH 13/21] Handle file operations in the front-end --- .../jupytergis_lab/notebook/gis_document.py | 5 -- python/jupytergis_lab/src/notebookrenderer.ts | 63 ++++++++++++------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py b/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py index bfa503ffd..a19b2f22e 100644 --- a/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py +++ b/python/jupytergis_lab/jupytergis_lab/notebook/gis_document.py @@ -63,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__( diff --git a/python/jupytergis_lab/src/notebookrenderer.ts b/python/jupytergis_lab/src/notebookrenderer.ts index 1954a5e54..6ea5fe065 100644 --- a/python/jupytergis_lab/src/notebookrenderer.ts +++ b/python/jupytergis_lab/src/notebookrenderer.ts @@ -29,6 +29,7 @@ import * as Y from 'yjs'; import { IJupyterYWidget, IJupyterYWidgetManager, + // JupyterYDoc, JupyterYModel } from 'yjs-widgets'; @@ -135,7 +136,7 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { } class YJupyterGISModelFactory extends YJupyterGISModel { - ydocFactory(commMetadata: ICommMetadata): Y.Doc { + async ydocFactory(commMetadata: ICommMetadata): Promise { const { path, format, contentType } = commMetadata; const fileFormat = format as Contents.FileFormat; @@ -144,11 +145,46 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { 'Error using the JupyterGIS Python API', 'You cannot use the JupyterGIS Python API without a collaborative drive. You need to install a package providing collaboration features (e.g. jupyter-collaboration).' ); - throw new Error('Failed to create the YDoc without a collaborative drive'); + throw new Error( + 'Failed to create the YDoc without a collaborative drive' + ); + } + + // The path of the project is relative to the path of the notebook + let currentWidgetPath: string = ''; + const currentWidget = app.shell.currentWidget; + if ( + currentWidget instanceof NotebookPanel || + currentWidget instanceof ConsolePanel + ) { + currentWidgetPath = currentWidget.sessionContext.path; + } + + let localPath = ''; + let fileless = false; + if (path) { + localPath = PathExt.join(PathExt.dirname(currentWidgetPath), path); + + // If the file does not exist yet, create it + try { + await app.serviceManager.contents.get(localPath); + } catch (e) { + await app.serviceManager.contents.save(localPath, { + content: btoa('{}'), + format: 'base64' + }); + } + } else { + // If the user did not provide a path, do not create + localPath = PathExt.join( + PathExt.dirname(currentWidgetPath), + 'unsaved_project' + ); + fileless = true; } const sharedModel = drive!.sharedModelFactory.createNew({ - path, + path: localPath, format: fileFormat, contentType, collaborative: true @@ -159,25 +195,10 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { this.jupyterGISModel.contentsManager = app.serviceManager.contents; - if (!sharedModel) { - // The path of the project is set to the path of the notebook, to be able to - // add local geoJSON/shape file in a "file-less" project. - let currentWidgetPath: string | undefined = undefined; - const currentWidget = app.shell.currentWidget; - if ( - currentWidget instanceof NotebookPanel || - currentWidget instanceof ConsolePanel - ) { - currentWidgetPath = currentWidget.sessionContext.path; - } - - if (currentWidgetPath) { - this.jupyterGISModel.filePath = PathExt.join( - PathExt.dirname(currentWidgetPath), - 'unsaved_project' - ); - } + if (fileless) { + this.jupyterGISModel.filePath = localPath; } + return this.jupyterGISModel.sharedModel.ydoc; } } From a63bb36d4a21007c19928e14226c9e6c2f58ce63 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 09:22:56 +0100 Subject: [PATCH 14/21] Up --- python/jupytergis_lab/src/notebookrenderer.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/python/jupytergis_lab/src/notebookrenderer.ts b/python/jupytergis_lab/src/notebookrenderer.ts index 6ea5fe065..56780c63b 100644 --- a/python/jupytergis_lab/src/notebookrenderer.ts +++ b/python/jupytergis_lab/src/notebookrenderer.ts @@ -25,10 +25,10 @@ import { Toolbar } from '@jupyterlab/ui-components'; import { CommandRegistry } from '@lumino/commands'; import { MessageLoop } from '@lumino/messaging'; import { Panel, Widget } from '@lumino/widgets'; -import * as Y from 'yjs'; import { IJupyterYWidget, IJupyterYWidgetManager, + JupyterYDoc, // JupyterYDoc, JupyterYModel } from 'yjs-widgets'; @@ -136,7 +136,9 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { } class YJupyterGISModelFactory extends YJupyterGISModel { - async ydocFactory(commMetadata: ICommMetadata): Promise { + protected async initialize(commMetadata: { + [key: string]: any; + }): Promise { const { path, format, contentType } = commMetadata; const fileFormat = format as Contents.FileFormat; @@ -151,7 +153,7 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { } // The path of the project is relative to the path of the notebook - let currentWidgetPath: string = ''; + let currentWidgetPath = ''; const currentWidget = app.shell.currentWidget; if ( currentWidget instanceof NotebookPanel || @@ -199,7 +201,8 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { this.jupyterGISModel.filePath = localPath; } - return this.jupyterGISModel.sharedModel.ydoc; + this.ydoc = this.jupyterGISModel.sharedModel.ydoc; + this.sharedModel = new JupyterYDoc(commMetadata, this.ydoc); } } From 3818b3dda5975005c16290699c0ce2bfeff3320b Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 09:39:04 +0100 Subject: [PATCH 15/21] Update yjs widgets --- docs/environment.yml | 2 +- python/jupytergis_lab/package.json | 2 +- python/jupytergis_lab/pyproject.toml | 2 +- yarn.lock | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/environment.yml b/docs/environment.yml index 1655ab0d2..ab420a9ef 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -9,10 +9,10 @@ dependencies: - requests - jupyter_ydoc=2.1.5 - ypywidgets>=0.9.6,<0.10.0 - - yjs-widgets>=0.3.5,<0.4 - comm>=0.1.2,<0.2.0 - pydantic>=2,<3 - pip: + - yjs-widgets>=0.4,<0.5 - my-jupyter-shared-drive==0.1.13 - ../python/jupytergis_lab - ../python/jupytergis_core diff --git a/python/jupytergis_lab/package.json b/python/jupytergis_lab/package.json index 8745166bc..40b345908 100644 --- a/python/jupytergis_lab/package.json +++ b/python/jupytergis_lab/package.json @@ -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", diff --git a/python/jupytergis_lab/pyproject.toml b/python/jupytergis_lab/pyproject.toml index 974618b1d..713d5cf6f 100644 --- a/python/jupytergis_lab/pyproject.toml +++ b/python/jupytergis_lab/pyproject.toml @@ -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", diff --git a/yarn.lock b/yarn.lock index 02bf94bf7..3740c67e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -849,7 +849,7 @@ __metadata: rimraf: ^3.0.2 typescript: ^5 yjs: ^13.5.0 - yjs-widgets: ^0.3.9 + yjs-widgets: ^0.4 languageName: unknown linkType: soft @@ -11471,9 +11471,9 @@ __metadata: languageName: node linkType: hard -"yjs-widgets@npm:^0.3.9": - version: 0.3.9 - resolution: "yjs-widgets@npm:0.3.9" +"yjs-widgets@npm:^0.4": + version: 0.4.0 + resolution: "yjs-widgets@npm:0.4.0" dependencies: "@jupyter/ydoc": ^2.0.0 || ^3.0.0-a3 "@jupyterlab/application": ^4.0.0 @@ -11489,7 +11489,7 @@ __metadata: uuid: ^9.0.0 webpack: ^5.77.0 webpack-cli: ^5.0.1 - checksum: 463d0d2e18cfbe9c8eb769fe25390a03a3ee3c50741763de0eb3c15806d55ab5c0b6a7ace8eef8367275fd15100a4b4f4cab21a0dd9f49a18538d2c952ecdd04 + checksum: 147fc7ae1c3d13fd591d434af33d439bc20d23494ded601dd8da5986426c6c896d7ff2a6296e24bda8d5ee17921c5c390c3b095f14fd5195506c0f891747e2fd languageName: node linkType: hard From 28daa39c2b1e6e3b547cef0509c3b1b7608c8296 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:08:40 +0100 Subject: [PATCH 16/21] Remove unwanted test --- .../jupytergis_lab/notebook/tests/test_api.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/python/jupytergis_lab/jupytergis_lab/notebook/tests/test_api.py b/python/jupytergis_lab/jupytergis_lab/notebook/tests/test_api.py index 45a1ee15c..8f723100a 100644 --- a/python/jupytergis_lab/jupytergis_lab/notebook/tests/test_api.py +++ b/python/jupytergis_lab/jupytergis_lab/notebook/tests/test_api.py @@ -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() From e9f218f296dcd056430e92505152ca789c355f5b Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:13:56 +0100 Subject: [PATCH 17/21] Cleanup --- python/jupytergis_lab/src/notebookrenderer.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/python/jupytergis_lab/src/notebookrenderer.ts b/python/jupytergis_lab/src/notebookrenderer.ts index 56780c63b..c262c5d3c 100644 --- a/python/jupytergis_lab/src/notebookrenderer.ts +++ b/python/jupytergis_lab/src/notebookrenderer.ts @@ -82,10 +82,6 @@ export class YJupyterGISLuminoWidget extends Panel { */ private _buildWidget = (options: IOptions) => { const { commands, model, externalCommands, tracker } = options; - // Ensure the model filePath is relevant with the shared model path. - if (model.sharedModel.getState('path')) { - model.filePath = model.sharedModel.getState('path') as string; - } const content = new JupyterGISPanel({ model }); let toolbar: Toolbar | undefined = undefined; if (model.filePath) { @@ -163,7 +159,6 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { } let localPath = ''; - let fileless = false; if (path) { localPath = PathExt.join(PathExt.dirname(currentWidgetPath), path); @@ -182,7 +177,6 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { PathExt.dirname(currentWidgetPath), 'unsaved_project' ); - fileless = true; } const sharedModel = drive!.sharedModelFactory.createNew({ @@ -196,10 +190,7 @@ export const notebookRendererPlugin: JupyterFrontEndPlugin = { }); this.jupyterGISModel.contentsManager = app.serviceManager.contents; - - if (fileless) { - this.jupyterGISModel.filePath = localPath; - } + this.jupyterGISModel.filePath = localPath; this.ydoc = this.jupyterGISModel.sharedModel.ydoc; this.sharedModel = new JupyterYDoc(commMetadata, this.ydoc); From 0e2a371b272dbfd45dc68df00b30601f27cb264c Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:27:25 +0100 Subject: [PATCH 18/21] Remove Github pages build --- .github/workflows/build.yml | 17 ----------------- README.md | 6 +++--- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f28d0acb..a30910b14 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -304,20 +304,3 @@ jobs: 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 diff --git a/README.md b/README.md index 856b50116..8ed6ea086 100644 --- a/README.md +++ b/README.md @@ -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. ⚠️ @@ -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! 🤯 From d392fd227c3682d8ca4af8847766e61e91fc539e Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:30:50 +0100 Subject: [PATCH 19/21] Show console as early as possible --- packages/base/src/widget.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/base/src/widget.ts b/packages/base/src/widget.ts index cb657f98c..b21e34b2b 100644 --- a/packages/base/src/widget.ts +++ b/packages/base/src/widget.ts @@ -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(); From 4a5654443458b1554b3802959d77ed758a487c04 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:37:52 +0100 Subject: [PATCH 20/21] More docs building removal --- .github/workflows/build.yml | 54 ------------------------------------- 1 file changed, 54 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a30910b14..47d40b45e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -250,57 +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.13 - pip - jupyterlite-core>=0.4.0,<0.6.0 - jupyterlite-xeus>=3.1.3,<4 - 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 From 98c6783d919966560491ae16df586724ff942954 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 10:48:48 +0100 Subject: [PATCH 21/21] Unpin my-jupyter-shared-drive --- docs/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/environment.yml b/docs/environment.yml index ab420a9ef..46243e9b9 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -13,6 +13,6 @@ dependencies: - pydantic>=2,<3 - pip: - yjs-widgets>=0.4,<0.5 - - my-jupyter-shared-drive==0.1.13 + - my-jupyter-shared-drive - ../python/jupytergis_lab - ../python/jupytergis_core