jupyverse 0.1.2__tar.gz → 0.1.4__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.
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.github/workflows/main.yml +5 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.pre-commit-config.yaml +1 -1
- {jupyverse-0.1.2 → jupyverse-0.1.4}/CHANGELOG.md +33 -2
- {jupyverse-0.1.2 → jupyverse-0.1.4}/PKG-INFO +15 -17
- {jupyverse-0.1.2 → jupyverse-0.1.4}/README.md +1 -1
- jupyverse-0.1.4/docs/usage/microservices.md +100 -0
- jupyverse-0.1.4/jupyverse/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/__init__.py +1 -1
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/contents/__init__.py +185 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/contents/models.py +15 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/jupyterlab/__init__.py +90 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/kernels/__init__.py +230 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/lab/__init__.py +193 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/login/__init__.py +23 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/nbconvert/__init__.py +43 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/resource_usage/__init__.py +37 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/retrolab/__init__.py +91 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/terminals/__init__.py +86 -0
- jupyverse-0.1.4/jupyverse_api/jupyverse_api/yjs/__init__.py +72 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/pyproject.toml +8 -1
- {jupyverse-0.1.2 → jupyverse-0.1.4}/mkdocs.yml +1 -0
- jupyverse-0.1.4/plugins/auth/fps_auth/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/config.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/db.py +5 -1
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/auth_fief/fps_auth_fief/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/fps_auth_fief/backend.py +2 -2
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/fps_auth_fief/routes.py +1 -1
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/contents/fps_contents/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/fps_contents/routes.py +108 -123
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/frontend/fps_frontend/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/jupyterlab/fps_jupyterlab/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/fps_jupyterlab/routes.py +58 -59
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/kernels/fps_kernels/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/main.py +5 -1
- jupyverse-0.1.4/plugins/kernels/fps_kernels/routes.py +356 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/lab/fps_lab/__init__.py +1 -0
- jupyverse-0.1.4/plugins/lab/fps_lab/routes.py +205 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/lab/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/login/fps_login/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/routes.py +4 -9
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/nbconvert/fps_nbconvert/__init__.py +1 -0
- jupyverse-0.1.4/plugins/nbconvert/fps_nbconvert/routes.py +41 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/nbconvert/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/noauth/fps_noauth/__init__.py +1 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/resource_usage/fps_resource_usage/__init__.py +1 -0
- jupyverse-0.1.4/plugins/resource_usage/fps_resource_usage/routes.py +73 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/resource_usage/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/retrolab/fps_retrolab/__init__.py +1 -0
- jupyverse-0.1.4/plugins/retrolab/fps_retrolab/routes.py +199 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/retrolab/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/terminals/fps_terminals/__init__.py +1 -0
- jupyverse-0.1.4/plugins/terminals/fps_terminals/routes.py +60 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/pyproject.toml +1 -1
- jupyverse-0.1.4/plugins/yjs/fps_yjs/__init__.py +1 -0
- jupyverse-0.1.4/plugins/yjs/fps_yjs/routes.py +355 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/pyproject.toml +1 -1
- {jupyverse-0.1.2 → jupyverse-0.1.4}/pyproject.toml +38 -39
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/conftest.py +2 -0
- jupyverse-0.1.2/jupyverse/__init__.py +0 -1
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/contents/__init__.py +0 -38
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/jupyterlab/__init__.py +0 -9
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/kernels/__init__.py +0 -16
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/lab/__init__.py +0 -18
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/login/__init__.py +0 -5
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/nbconvert/__init__.py +0 -5
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/resource_usage/__init__.py +0 -13
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/retrolab/__init__.py +0 -5
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/terminals/__init__.py +0 -16
- jupyverse-0.1.2/jupyverse_api/jupyverse_api/yjs/__init__.py +0 -7
- jupyverse-0.1.2/plugins/auth/fps_auth/__init__.py +0 -1
- jupyverse-0.1.2/plugins/auth_fief/fps_auth_fief/__init__.py +0 -1
- jupyverse-0.1.2/plugins/contents/fps_contents/__init__.py +0 -1
- jupyverse-0.1.2/plugins/contents/fps_contents/models.py +0 -18
- jupyverse-0.1.2/plugins/frontend/fps_frontend/__init__.py +0 -1
- jupyverse-0.1.2/plugins/jupyterlab/fps_jupyterlab/__init__.py +0 -1
- jupyverse-0.1.2/plugins/kernels/fps_kernels/__init__.py +0 -1
- jupyverse-0.1.2/plugins/kernels/fps_kernels/routes.py +0 -364
- jupyverse-0.1.2/plugins/lab/fps_lab/__init__.py +0 -1
- jupyverse-0.1.2/plugins/lab/fps_lab/routes.py +0 -253
- jupyverse-0.1.2/plugins/login/fps_login/__init__.py +0 -1
- jupyverse-0.1.2/plugins/nbconvert/fps_nbconvert/__init__.py +0 -1
- jupyverse-0.1.2/plugins/nbconvert/fps_nbconvert/routes.py +0 -47
- jupyverse-0.1.2/plugins/noauth/fps_noauth/__init__.py +0 -1
- jupyverse-0.1.2/plugins/resource_usage/fps_resource_usage/__init__.py +0 -1
- jupyverse-0.1.2/plugins/resource_usage/fps_resource_usage/routes.py +0 -74
- jupyverse-0.1.2/plugins/retrolab/fps_retrolab/__init__.py +0 -1
- jupyverse-0.1.2/plugins/retrolab/fps_retrolab/routes.py +0 -170
- jupyverse-0.1.2/plugins/terminals/fps_terminals/__init__.py +0 -1
- jupyverse-0.1.2/plugins/terminals/fps_terminals/routes.py +0 -66
- jupyverse-0.1.2/plugins/yjs/fps_yjs/__init__.py +0 -1
- jupyverse-0.1.2/plugins/yjs/fps_yjs/routes.py +0 -360
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.devcontainer/devcontainer.json +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.devcontainer/requirements.txt +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.github/workflows/check-release.yml +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/.gitignore +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/CONTRIBUTING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/binder/environment.yml +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/binder/jupyter_notebook_config.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/binder/postBuild +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/binder/start +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/config.yaml +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/index.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/install.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/jupyter.svg +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/auth.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/contents.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/frontend.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/jupyterlab.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/kernels.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/lab.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/login.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/nbconvert.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/resource_usage.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/retrolab.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/terminals.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/plugins/yjs.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/usage/multi_user.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/docs/usage/single_user.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/app/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/auth/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/auth/models.py +0 -0
- {jupyverse-0.1.2/jupyverse → jupyverse-0.1.4/jupyverse_api/jupyverse_api}/cli.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/exceptions.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/frontend/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/kernels/models.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/main/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/jupyverse_api/jupyverse_api/py.typed +0 -0
- {jupyverse-0.1.2/plugins/terminals/fps_terminals → jupyverse-0.1.4/jupyverse_api/jupyverse_api/terminals}/models.py +0 -0
- {jupyverse-0.1.2/plugins/yjs/fps_yjs → jupyverse-0.1.4/jupyverse_api/jupyverse_api/yjs}/models.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/backends.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/models.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth/fps_auth/routes.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/fps_auth_fief/config.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/auth_fief/fps_auth_fief/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/fps_contents/fileid.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/fps_contents/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/contents/fps_contents/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/fps_frontend/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/frontend/fps_frontend/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/fps_jupyterlab/index.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/fps_jupyterlab/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/jupyterlab/fps_jupyterlab/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/connect.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/driver.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/kernelspec.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/message.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_driver/paths.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_server/__init__.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_server/message.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/kernels/fps_kernels/kernel_server/server.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/lab/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/lab/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/lab/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/lab/fps_lab/main.py +0 -0
- {jupyverse-0.1.2/jupyverse → jupyverse-0.1.4/plugins/lab/fps_lab}/static/favicon.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-busy-1.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-busy-2.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-busy-3.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-file.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-notebook.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon-terminal.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/favicons/favicon.ico +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/index.html +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/logo/github.svg +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/logo/logo.png +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/login/fps_login/static/style/index.css +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/nbconvert/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/nbconvert/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/nbconvert/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/nbconvert/fps_nbconvert/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/fps_noauth/backends.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/fps_noauth/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/noauth/fps_noauth/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/resource_usage/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/resource_usage/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/resource_usage/fps_resource_usage/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/retrolab/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/retrolab/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/retrolab/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/retrolab/fps_retrolab/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/fps_terminals/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/fps_terminals/server.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/terminals/fps_terminals/win_server.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/COPYING.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/MANIFEST.in +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/README.md +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/fps_yjs/main.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/plugins/yjs/fps_yjs/py.typed +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/pytest.ini +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/data/notebook0.ipynb +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/test_auth.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/test_contents.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/test_kernels.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/test_server.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/test_settings.py +0 -0
- {jupyverse-0.1.2 → jupyverse-0.1.4}/tests/utils.py +0 -0
@@ -41,7 +41,12 @@ jobs:
|
|
41
41
|
|
42
42
|
- name: Check types
|
43
43
|
run: |
|
44
|
+
hatch run dev.jupyterlab-noauth:typecheck
|
45
|
+
hatch run dev.jupyterlab-noauth:typecheck
|
44
46
|
hatch run dev.jupyterlab-auth:typecheck
|
47
|
+
hatch run dev.retrolab-auth_fief:typecheck
|
48
|
+
hatch run dev.retrolab-auth:typecheck
|
49
|
+
hatch run dev.retrolab-auth_fief:typecheck
|
45
50
|
|
46
51
|
- name: Run tests
|
47
52
|
run: |
|
@@ -2,12 +2,43 @@
|
|
2
2
|
|
3
3
|
<!-- <START NEW CHANGELOG ENTRY> -->
|
4
4
|
|
5
|
-
## 0.1.
|
5
|
+
## 0.1.4
|
6
6
|
|
7
|
-
|
7
|
+
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.1.3...a42f7c4d0e951d620108afb4ca25e57da5bae2a1))
|
8
|
+
|
9
|
+
### Merged PRs
|
10
|
+
|
11
|
+
- Move routes to jupyverse_api [#293](https://github.com/jupyter-server/jupyverse/pull/293) ([@davidbrochart](https://github.com/davidbrochart))
|
12
|
+
- Add microservices doc, move CLI to jupyverse_api [#292](https://github.com/jupyter-server/jupyverse/pull/292) ([@davidbrochart](https://github.com/davidbrochart))
|
13
|
+
- Don't ignore types for fief_client [#290](https://github.com/jupyter-server/jupyverse/pull/290) ([@davidbrochart](https://github.com/davidbrochart))
|
14
|
+
- Update README [#288](https://github.com/jupyter-server/jupyverse/pull/288) ([@davidbrochart](https://github.com/davidbrochart))
|
15
|
+
|
16
|
+
### Contributors to this release
|
17
|
+
|
18
|
+
([GitHub contributors page for this release](https://github.com/jupyter-server/jupyverse/graphs/contributors?from=2023-04-06&to=2023-04-18&type=c))
|
19
|
+
|
20
|
+
[@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2023-04-06..2023-04-18&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Apre-commit-ci+updated%3A2023-04-06..2023-04-18&type=Issues)
|
8
21
|
|
9
22
|
<!-- <END NEW CHANGELOG ENTRY> -->
|
10
23
|
|
24
|
+
## 0.1.3
|
25
|
+
|
26
|
+
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.1.2...b5faf93e3296d855c7ebeda0c25e9861400ad469))
|
27
|
+
|
28
|
+
### Merged PRs
|
29
|
+
|
30
|
+
- Add fps-lab and fps-frontend dependencies to jupyverse [#287](https://github.com/jupyter-server/jupyverse/pull/287) ([@davidbrochart](https://github.com/davidbrochart))
|
31
|
+
|
32
|
+
### Contributors to this release
|
33
|
+
|
34
|
+
([GitHub contributors page for this release](https://github.com/jupyter-server/jupyverse/graphs/contributors?from=2023-04-06&to=2023-04-06&type=c))
|
35
|
+
|
36
|
+
[@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2023-04-06..2023-04-06&type=Issues)
|
37
|
+
|
38
|
+
## 0.1.2
|
39
|
+
|
40
|
+
No merged PRs
|
41
|
+
|
11
42
|
## 0.1.1
|
12
43
|
|
13
44
|
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.0.50...254a3dfd5f6851e2e79406fab934c8361399ffb6))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: jupyverse
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.4
|
4
4
|
Summary: A set of FPS plugins implementing a Jupyter server
|
5
5
|
Project-URL: Homepage, https://jupyter.org
|
6
6
|
Author-email: Jupyter Development Team <jupyter@googlegroups.com>
|
@@ -8,29 +8,27 @@ License: BSD 3-Clause License
|
|
8
8
|
License-File: COPYING.md
|
9
9
|
Keywords: fastapi,jupyter,plugins,server
|
10
10
|
Requires-Python: >=3.8
|
11
|
-
Requires-Dist:
|
12
|
-
Requires-Dist:
|
13
|
-
Requires-Dist:
|
14
|
-
Requires-Dist: fps-
|
15
|
-
Requires-Dist: fps-
|
16
|
-
Requires-Dist: fps-
|
17
|
-
Requires-Dist: fps-
|
18
|
-
Requires-Dist:
|
19
|
-
Requires-Dist: jupyverse-api
|
20
|
-
Requires-Dist: rich-click<2,>=1.6.1
|
11
|
+
Requires-Dist: fps-contents<1,>=0.1.2
|
12
|
+
Requires-Dist: fps-frontend<1,>=0.1.2
|
13
|
+
Requires-Dist: fps-kernels<1,>=0.1.2
|
14
|
+
Requires-Dist: fps-lab<1,>=0.1.2
|
15
|
+
Requires-Dist: fps-nbconvert<1,>=0.1.2
|
16
|
+
Requires-Dist: fps-terminals<1,>=0.1.2
|
17
|
+
Requires-Dist: fps-yjs<1,>=0.1.2
|
18
|
+
Requires-Dist: jupyverse-api<1,>=0.1.2
|
21
19
|
Provides-Extra: auth
|
22
|
-
Requires-Dist: fps-auth; extra == 'auth'
|
20
|
+
Requires-Dist: fps-auth<1,>=0.1.2; extra == 'auth'
|
23
21
|
Provides-Extra: auth-fief
|
24
|
-
Requires-Dist: fps-auth-fief; extra == 'auth-fief'
|
22
|
+
Requires-Dist: fps-auth-fief<1,>=0.1.2; extra == 'auth-fief'
|
25
23
|
Provides-Extra: docs
|
26
24
|
Requires-Dist: mkdocs; extra == 'docs'
|
27
25
|
Requires-Dist: mkdocs-material; extra == 'docs'
|
28
26
|
Provides-Extra: jupyterlab
|
29
|
-
Requires-Dist: fps-jupyterlab; extra == 'jupyterlab'
|
27
|
+
Requires-Dist: fps-jupyterlab<1,>=0.1.2; extra == 'jupyterlab'
|
30
28
|
Provides-Extra: noauth
|
31
|
-
Requires-Dist: fps-noauth; extra == 'noauth'
|
29
|
+
Requires-Dist: fps-noauth<1,>=0.1.2; extra == 'noauth'
|
32
30
|
Provides-Extra: retrolab
|
33
|
-
Requires-Dist: fps-retrolab; extra == 'retrolab'
|
31
|
+
Requires-Dist: fps-retrolab<1,>=0.1.2; extra == 'retrolab'
|
34
32
|
Provides-Extra: test
|
35
33
|
Requires-Dist: httpx; extra == 'test'
|
36
34
|
Requires-Dist: httpx-ws; extra == 'test'
|
@@ -49,7 +47,7 @@ Description-Content-Type: text/markdown
|
|
49
47
|
|
50
48
|
# jupyverse
|
51
49
|
|
52
|
-
A set of [
|
50
|
+
A set of [Asphalt](https://asphalt.readthedocs.io) components implementing a Jupyter server.
|
53
51
|
|
54
52
|
Try it online:
|
55
53
|
- JupyterLab frontend: [](https://mybinder.org/v2/gh/jupyter-server/jupyverse/HEAD?urlpath=jupyverse-jlab)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
# jupyverse
|
5
5
|
|
6
|
-
A set of [
|
6
|
+
A set of [Asphalt](https://asphalt.readthedocs.io) components implementing a Jupyter server.
|
7
7
|
|
8
8
|
Try it online:
|
9
9
|
- JupyterLab frontend: [](https://mybinder.org/v2/gh/jupyter-server/jupyverse/HEAD?urlpath=jupyverse-jlab)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
Jupyverse's modularity allows to run services quite independently from each other, following a microservice architecture. This can be useful when resources are provided by separate systems, or just to have a clear separation of concerns. For instance, you may want to host the contents on AWS and the kernels on Google Cloud, or on different machines in your private network. One way to achieve this is to use a reverse proxy that will forward client requests to the corresponding Jupyverse server. We will show how to do that using [Nginx](https://en.wikipedia.org/wiki/Nginx) on a single computer with local servers. This can serve as a basis for more complicated architectures involving remote servers.
|
2
|
+
|
3
|
+
## Nginx setup
|
4
|
+
|
5
|
+
Nginx is a web server that can also be used as a reverse proxy. We will use it to forward client requests to separate Jupyverse servers, based on the request URL.
|
6
|
+
|
7
|
+
First, install Nginx in its own environment:
|
8
|
+
```bash
|
9
|
+
micromamba create -n nginx
|
10
|
+
micromamba activate nginx
|
11
|
+
micromamba install -c conda-forge nginx
|
12
|
+
```
|
13
|
+
We will just edit the default configuration file at `~/micromamba/envs/nginx/etc/nginx/sites.d/default-site.conf` with the following:
|
14
|
+
```
|
15
|
+
server {
|
16
|
+
listen 8000;
|
17
|
+
server_name localhost;
|
18
|
+
|
19
|
+
location / {
|
20
|
+
proxy_pass http://localhost:8001;
|
21
|
+
}
|
22
|
+
|
23
|
+
location /api/kernelspecs {
|
24
|
+
proxy_pass http://localhost:8002;
|
25
|
+
}
|
26
|
+
location /api/kernels {
|
27
|
+
proxy_pass http://localhost:8002;
|
28
|
+
}
|
29
|
+
location ~ \/api\/kernels\/.+\/channels {
|
30
|
+
proxy_pass http://localhost:8002;
|
31
|
+
proxy_set_header Upgrade $http_upgrade;
|
32
|
+
proxy_set_header Connection "Upgrade";
|
33
|
+
}
|
34
|
+
location /api/sessions {
|
35
|
+
proxy_pass http://localhost:8002;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
```
|
39
|
+
Our Nginx server will listen at `http://localhost:8000`. This is the URL the client will see, i.e. the one we enter in the browser.
|
40
|
+
|
41
|
+
Our Jupyverse servers will run on:
|
42
|
+
|
43
|
+
- `http://localhost:8001` for everything except the kernels API. This means that this server doesn't have the ability to run user code, and thus cannot be used to execute a notebook.
|
44
|
+
- `http://localhost:8002` for the kernels API. This server only deals with executing code in a kernel. It cannot serve JupyterLab's UI, for instance.
|
45
|
+
|
46
|
+
Together, these Jupyverse servers can serve a full JupyterLab API. But because they run on different machines (not exactly in this case, since ports `8001` and `8002` are on the same machine, but let's pretend), we need to make them appear as a unique server. That is the role of the reverse proxy server.
|
47
|
+
|
48
|
+
!!! note
|
49
|
+
WebSocket forwarding requires extra-configuration. Here, we use a `regex` to redirect `/api/kernels/{kernel_id}/channels`, which is the WebSocket endpoint for the kernel protocol. We also set the `Upgrade` and `Connection` headers used to upgrade the connection from HTTP to WebSocket.
|
50
|
+
|
51
|
+
We can now run our reverse proxy server. Just enter:
|
52
|
+
```bash
|
53
|
+
nginx
|
54
|
+
```
|
55
|
+
|
56
|
+
## Jupyverse setup
|
57
|
+
|
58
|
+
### Server 1: everything but kernels
|
59
|
+
|
60
|
+
Let's create a new environment in a new terminal:
|
61
|
+
```bash
|
62
|
+
micromamba create -n jupyverse1
|
63
|
+
micromamba activate jupyverse1
|
64
|
+
micromamba install -c conda-forge python
|
65
|
+
```
|
66
|
+
Since we don't want to install the fully-fledged Jupyverse server, we will install the required plugins individually:
|
67
|
+
```bash
|
68
|
+
pip install fps-auth
|
69
|
+
pip install fps-contents
|
70
|
+
pip install fps-frontend
|
71
|
+
pip install fps-lab
|
72
|
+
pip install fps-jupyterlab
|
73
|
+
pip install fps-login
|
74
|
+
```
|
75
|
+
Now just launch Jupyverse at port `8001`:
|
76
|
+
```bash
|
77
|
+
jupyverse --port=8001
|
78
|
+
```
|
79
|
+
If you open your browser at `http://127.0.0.1:8000` (the URL of the Nginx reverse proxy), you should see the JupyterLab UI you're used to. But if you look closer, you can see that there is no icon for kernels in the launcher tab. And in the terminal where you launched Jupyverse, you will see a bunch of `404` for requests at e.g. `GET /api/kernels`. This is expected, because we didn't install the kernels plugin. You can still use JupyterLab if you don't want to execute a notebook, for instance. But let's close it for now, and install the kernels plugin in another Jupyverse instance.
|
80
|
+
|
81
|
+
### Server 2: the kernels API
|
82
|
+
|
83
|
+
Let's create a new environment in a new terminal:
|
84
|
+
```bash
|
85
|
+
micromamba create -n jupyverse2
|
86
|
+
micromamba activate jupyverse2
|
87
|
+
micromamba install -c conda-forge python
|
88
|
+
```
|
89
|
+
This time, we only want to install the kernels plugin. It also requires an authentication system (for the sake of simplicity we will install `fps-noauth` which gives unrestricted access) and the frontend plugin. Let's not forget to install a kernel, such as `ipykernel`:
|
90
|
+
```bash
|
91
|
+
pip install fps-kernels
|
92
|
+
pip install fps-noauth
|
93
|
+
pip install fps-frontend
|
94
|
+
pip install ipykernel
|
95
|
+
```
|
96
|
+
Launch Juyverse at port `8002`:
|
97
|
+
```bash
|
98
|
+
jupyverse --port=8002
|
99
|
+
```
|
100
|
+
Now if you re-open a browser at `http://127.0.0.1:8000`, you should be able to create or open a notebook, and execute it.
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.4"
|
@@ -0,0 +1,185 @@
|
|
1
|
+
import asyncio
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Dict, List, Optional, Union
|
5
|
+
|
6
|
+
from fastapi import APIRouter, Depends, Request, Response
|
7
|
+
from jupyverse_api import Router
|
8
|
+
|
9
|
+
from .models import Checkpoint, Content, SaveContent
|
10
|
+
from ..auth import Auth, User
|
11
|
+
from ..app import App
|
12
|
+
|
13
|
+
|
14
|
+
class FileIdManager(ABC):
|
15
|
+
stop_watching_files: asyncio.Event
|
16
|
+
stopped_watching_files: asyncio.Event
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
async def get_path(self, file_id: str) -> str:
|
20
|
+
...
|
21
|
+
|
22
|
+
@abstractmethod
|
23
|
+
async def get_id(self, file_path: str) -> str:
|
24
|
+
...
|
25
|
+
|
26
|
+
|
27
|
+
class Contents(Router, ABC):
|
28
|
+
def __init__(self, app: App, auth: Auth):
|
29
|
+
super().__init__(app=app)
|
30
|
+
|
31
|
+
router = APIRouter()
|
32
|
+
|
33
|
+
@router.post(
|
34
|
+
"/api/contents/{path:path}/checkpoints",
|
35
|
+
status_code=201,
|
36
|
+
)
|
37
|
+
async def create_checkpoint(
|
38
|
+
path, user: User = Depends(auth.current_user(permissions={"contents": ["write"]}))
|
39
|
+
) -> Checkpoint:
|
40
|
+
return await self.create_checkpoint(path, user)
|
41
|
+
|
42
|
+
@router.post(
|
43
|
+
"/api/contents{path:path}",
|
44
|
+
status_code=201,
|
45
|
+
)
|
46
|
+
async def create_content(
|
47
|
+
path: Optional[str],
|
48
|
+
request: Request,
|
49
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["write"]})),
|
50
|
+
) -> Content:
|
51
|
+
return await self.create_content(path, request, user)
|
52
|
+
|
53
|
+
@router.get("/api/contents")
|
54
|
+
async def get_root_content(
|
55
|
+
content: int,
|
56
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["read"]})),
|
57
|
+
) -> Content:
|
58
|
+
return await self.get_root_content(content, user)
|
59
|
+
|
60
|
+
@router.get("/api/contents/{path:path}/checkpoints")
|
61
|
+
async def get_checkpoint(
|
62
|
+
path, user: User = Depends(auth.current_user(permissions={"contents": ["read"]}))
|
63
|
+
) -> List[Checkpoint]:
|
64
|
+
return await self.get_checkpoint(path, user)
|
65
|
+
|
66
|
+
@router.get("/api/contents/{path:path}")
|
67
|
+
async def get_content(
|
68
|
+
path: str,
|
69
|
+
content: int = 0,
|
70
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["read"]})),
|
71
|
+
) -> Content:
|
72
|
+
return await self.get_content(path, content, user)
|
73
|
+
|
74
|
+
@router.put("/api/contents/{path:path}")
|
75
|
+
async def save_content(
|
76
|
+
path,
|
77
|
+
request: Request,
|
78
|
+
response: Response,
|
79
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["write"]})),
|
80
|
+
) -> Content:
|
81
|
+
return await self.save_content(path, request, response, user)
|
82
|
+
|
83
|
+
@router.delete(
|
84
|
+
"/api/contents/{path:path}",
|
85
|
+
status_code=204,
|
86
|
+
)
|
87
|
+
async def delete_content(
|
88
|
+
path,
|
89
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["write"]})),
|
90
|
+
):
|
91
|
+
return await self.delete_content(path, user)
|
92
|
+
|
93
|
+
@router.patch("/api/contents/{path:path}")
|
94
|
+
async def rename_content(
|
95
|
+
path,
|
96
|
+
request: Request,
|
97
|
+
user: User = Depends(auth.current_user(permissions={"contents": ["write"]})),
|
98
|
+
) -> Content:
|
99
|
+
return await self.rename_content(path, request, user)
|
100
|
+
|
101
|
+
self.include_router(router)
|
102
|
+
|
103
|
+
@property
|
104
|
+
@abstractmethod
|
105
|
+
def file_id_manager(self) -> FileIdManager:
|
106
|
+
...
|
107
|
+
|
108
|
+
@abstractmethod
|
109
|
+
async def read_content(
|
110
|
+
self, path: Union[str, Path], get_content: bool, as_json: bool = False
|
111
|
+
) -> Content:
|
112
|
+
...
|
113
|
+
|
114
|
+
@abstractmethod
|
115
|
+
async def write_content(self, content: Union[SaveContent, Dict]) -> None:
|
116
|
+
...
|
117
|
+
|
118
|
+
@abstractmethod
|
119
|
+
async def create_checkpoint(
|
120
|
+
self,
|
121
|
+
path,
|
122
|
+
user: User,
|
123
|
+
) -> Checkpoint:
|
124
|
+
...
|
125
|
+
|
126
|
+
@abstractmethod
|
127
|
+
async def create_content(
|
128
|
+
self,
|
129
|
+
path: Optional[str],
|
130
|
+
request: Request,
|
131
|
+
user: User,
|
132
|
+
) -> Content:
|
133
|
+
...
|
134
|
+
|
135
|
+
@abstractmethod
|
136
|
+
async def get_root_content(
|
137
|
+
self,
|
138
|
+
content: int,
|
139
|
+
user: User,
|
140
|
+
) -> Content:
|
141
|
+
return await self.get_root_content(content, user)
|
142
|
+
|
143
|
+
@abstractmethod
|
144
|
+
async def get_checkpoint(
|
145
|
+
self,
|
146
|
+
path,
|
147
|
+
user: User,
|
148
|
+
) -> List[Checkpoint]:
|
149
|
+
...
|
150
|
+
|
151
|
+
@abstractmethod
|
152
|
+
async def get_content(
|
153
|
+
self,
|
154
|
+
path: str,
|
155
|
+
content: int,
|
156
|
+
user: User,
|
157
|
+
) -> Content:
|
158
|
+
...
|
159
|
+
|
160
|
+
@abstractmethod
|
161
|
+
async def save_content(
|
162
|
+
self,
|
163
|
+
path,
|
164
|
+
request: Request,
|
165
|
+
response: Response,
|
166
|
+
user: User,
|
167
|
+
) -> Content:
|
168
|
+
...
|
169
|
+
|
170
|
+
@abstractmethod
|
171
|
+
async def delete_content(
|
172
|
+
self,
|
173
|
+
path,
|
174
|
+
user: User,
|
175
|
+
):
|
176
|
+
...
|
177
|
+
|
178
|
+
@abstractmethod
|
179
|
+
async def rename_content(
|
180
|
+
self,
|
181
|
+
path,
|
182
|
+
request: Request,
|
183
|
+
user: User,
|
184
|
+
) -> Content:
|
185
|
+
...
|
@@ -3,6 +3,11 @@ from typing import Dict, List, Optional, Union
|
|
3
3
|
from pydantic import BaseModel
|
4
4
|
|
5
5
|
|
6
|
+
class Checkpoint(BaseModel):
|
7
|
+
id: str
|
8
|
+
last_modified: str
|
9
|
+
|
10
|
+
|
6
11
|
class Content(BaseModel):
|
7
12
|
name: str
|
8
13
|
path: str
|
@@ -16,8 +21,18 @@ class Content(BaseModel):
|
|
16
21
|
type: str
|
17
22
|
|
18
23
|
|
24
|
+
class CreateContent(BaseModel):
|
25
|
+
ext: Optional[str]
|
26
|
+
path: str
|
27
|
+
type: str
|
28
|
+
|
29
|
+
|
19
30
|
class SaveContent(BaseModel):
|
20
31
|
content: Optional[Union[str, Dict]]
|
21
32
|
format: str
|
22
33
|
path: str
|
23
34
|
type: str
|
35
|
+
|
36
|
+
|
37
|
+
class RenameContent(BaseModel):
|
38
|
+
path: str
|
@@ -0,0 +1,90 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from fastapi import APIRouter, Depends, Request
|
4
|
+
from fastapi.responses import HTMLResponse
|
5
|
+
from jupyverse_api import Config, Router
|
6
|
+
|
7
|
+
from ..auth import Auth, User
|
8
|
+
from ..app import App
|
9
|
+
|
10
|
+
|
11
|
+
class JupyterLab(Router, ABC):
|
12
|
+
def __init__(self, app: App, auth: Auth):
|
13
|
+
super().__init__(app)
|
14
|
+
|
15
|
+
router = APIRouter()
|
16
|
+
|
17
|
+
@router.get("/lab")
|
18
|
+
async def get_lab(
|
19
|
+
user: User = Depends(auth.current_user()),
|
20
|
+
):
|
21
|
+
return await self.get_lab(user)
|
22
|
+
|
23
|
+
@router.get("/lab/tree/{path:path}")
|
24
|
+
async def load_workspace(
|
25
|
+
path,
|
26
|
+
):
|
27
|
+
return await self.load_workspace(path)
|
28
|
+
|
29
|
+
@router.get("/lab/api/workspaces/{name}")
|
30
|
+
async def get_workspace_data(user: User = Depends(auth.current_user())):
|
31
|
+
return await self.get_workspace_data(user)
|
32
|
+
|
33
|
+
@router.put(
|
34
|
+
"/lab/api/workspaces/{name}",
|
35
|
+
status_code=204,
|
36
|
+
)
|
37
|
+
async def set_workspace(
|
38
|
+
request: Request,
|
39
|
+
user: User = Depends(auth.current_user()),
|
40
|
+
user_update=Depends(auth.update_user),
|
41
|
+
):
|
42
|
+
return await self.set_workspace(request, user, user_update)
|
43
|
+
|
44
|
+
@router.get("/lab/workspaces/{name}", response_class=HTMLResponse)
|
45
|
+
async def get_workspace(
|
46
|
+
name,
|
47
|
+
user: User = Depends(auth.current_user()),
|
48
|
+
):
|
49
|
+
return await self.get_workspace(name, user)
|
50
|
+
|
51
|
+
self.include_router(router)
|
52
|
+
|
53
|
+
@abstractmethod
|
54
|
+
async def get_lab(
|
55
|
+
self,
|
56
|
+
user: User,
|
57
|
+
):
|
58
|
+
...
|
59
|
+
|
60
|
+
@abstractmethod
|
61
|
+
async def load_workspace(
|
62
|
+
self,
|
63
|
+
path,
|
64
|
+
):
|
65
|
+
...
|
66
|
+
|
67
|
+
@abstractmethod
|
68
|
+
async def get_workspace_data(self, user: User):
|
69
|
+
...
|
70
|
+
|
71
|
+
@abstractmethod
|
72
|
+
async def set_workspace(
|
73
|
+
self,
|
74
|
+
request: Request,
|
75
|
+
user: User,
|
76
|
+
user_update,
|
77
|
+
):
|
78
|
+
...
|
79
|
+
|
80
|
+
@abstractmethod
|
81
|
+
async def get_workspace(
|
82
|
+
self,
|
83
|
+
name,
|
84
|
+
user: User,
|
85
|
+
):
|
86
|
+
...
|
87
|
+
|
88
|
+
|
89
|
+
class JupyterLabConfig(Config):
|
90
|
+
dev_mode: bool = False
|