jupyverse 0.6.4__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.devcontainer/requirements.txt +1 -2
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.github/workflows/test.yml +4 -4
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.pre-commit-config.yaml +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/CHANGELOG.md +34 -2
- {jupyverse-0.6.4 → jupyverse-0.7.1}/PKG-INFO +20 -21
- {jupyverse-0.6.4 → jupyverse-0.7.1}/README.md +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/binder/environment.yml +1 -1
- jupyverse-0.7.1/jupyverse/__init__.py +1 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/__init__.py +36 -2
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/app/__init__.py +4 -4
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/auth/__init__.py +2 -2
- jupyverse-0.7.1/jupyverse_api/jupyverse_api/cli.py +115 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/contents/__init__.py +13 -5
- jupyverse-0.7.1/jupyverse_api/jupyverse_api/main/__init__.py +110 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/terminals/__init__.py +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/pyproject.toml +9 -9
- jupyverse-0.7.1/jupyverse_api/tests/test_resource_lock.py +57 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/mkdocs.yml +1 -1
- jupyverse-0.7.1/plugins/auth/fps_auth/__init__.py +1 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/backends.py +0 -3
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/db.py +0 -3
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/main.py +13 -22
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/routes.py +2 -5
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/auth_fief/fps_auth_fief/__init__.py +1 -0
- jupyverse-0.7.1/plugins/auth_fief/fps_auth_fief/main.py +20 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/fps_auth_fief/routes.py +2 -2
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/pyproject.toml +2 -2
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/__init__.py +1 -1
- jupyverse-0.7.1/plugins/auth_jupyterhub/fps_auth_jupyterhub/main.py +34 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/routes.py +24 -13
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/pyproject.toml +5 -4
- jupyverse-0.7.1/plugins/contents/fps_contents/__init__.py +1 -0
- jupyverse-0.7.1/plugins/contents/fps_contents/fileid.py +224 -0
- jupyverse-0.7.1/plugins/contents/fps_contents/main.py +16 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/contents/fps_contents/routes.py +111 -97
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/contents/pyproject.toml +6 -6
- jupyverse-0.7.1/plugins/frontend/fps_frontend/__init__.py +1 -0
- jupyverse-0.7.1/plugins/frontend/fps_frontend/main.py +12 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/frontend/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/jupyterlab/fps_jupyterlab/__init__.py +1 -0
- jupyverse-0.7.1/plugins/jupyterlab/fps_jupyterlab/main.py +26 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/jupyterlab/fps_jupyterlab/routes.py +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/jupyterlab/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/kernels/fps_kernels/__init__.py +1 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/connect.py +15 -14
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/driver.py +108 -77
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/message.py +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_server/server.py +58 -47
- jupyverse-0.7.1/plugins/kernels/fps_kernels/main.py +45 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/routes.py +51 -9
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/pyproject.toml +7 -5
- jupyverse-0.7.1/plugins/lab/fps_lab/__init__.py +1 -0
- jupyverse-0.7.1/plugins/lab/fps_lab/main.py +20 -0
- jupyverse-0.7.1/plugins/lab/fps_lab/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/lab/fps_lab/routes.py +0 -3
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/lab/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/login/fps_login/__init__.py +1 -0
- jupyverse-0.7.1/plugins/login/fps_login/main.py +16 -0
- jupyverse-0.7.1/plugins/login/fps_login/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/nbconvert/fps_nbconvert/__init__.py +1 -0
- jupyverse-0.7.1/plugins/nbconvert/fps_nbconvert/main.py +15 -0
- jupyverse-0.7.1/plugins/nbconvert/fps_nbconvert/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/nbconvert/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/noauth/fps_noauth/__init__.py +1 -0
- jupyverse-0.7.1/plugins/noauth/fps_noauth/main.py +12 -0
- jupyverse-0.7.1/plugins/noauth/fps_noauth/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/noauth/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/notebook/fps_notebook/__init__.py +1 -0
- jupyverse-0.7.1/plugins/notebook/fps_notebook/main.py +25 -0
- jupyverse-0.7.1/plugins/notebook/fps_notebook/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/notebook/fps_notebook/routes.py +32 -25
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/notebook/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/resource_usage/fps_resource_usage/__init__.py +1 -0
- jupyverse-0.7.1/plugins/resource_usage/fps_resource_usage/main.py +20 -0
- jupyverse-0.7.1/plugins/resource_usage/fps_resource_usage/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/resource_usage/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/terminals/fps_terminals/__init__.py +1 -0
- jupyverse-0.7.1/plugins/terminals/fps_terminals/main.py +32 -0
- jupyverse-0.7.1/plugins/terminals/fps_terminals/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/terminals/fps_terminals/routes.py +32 -4
- jupyverse-0.7.1/plugins/terminals/fps_terminals/server.py +150 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/terminals/fps_terminals/win_server.py +22 -16
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/terminals/pyproject.toml +4 -4
- jupyverse-0.7.1/plugins/webdav/fps_webdav/__init__.py +1 -0
- jupyverse-0.7.1/plugins/webdav/fps_webdav/main.py +18 -0
- jupyverse-0.7.1/plugins/webdav/fps_webdav/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/webdav/fps_webdav/routes.py +10 -6
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/webdav/pyproject.toml +5 -5
- jupyverse-0.7.1/plugins/webdav/tests/conftest.py +15 -0
- jupyverse-0.7.1/plugins/webdav/tests/test_webdav.py +54 -0
- jupyverse-0.7.1/plugins/yjs/fps_yjs/__init__.py +1 -0
- jupyverse-0.7.1/plugins/yjs/fps_yjs/main.py +38 -0
- jupyverse-0.7.1/plugins/yjs/fps_yjs/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/routes.py +145 -108
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/ybasedoc.py +3 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/yblob.py +2 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/ynotebook.py +3 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/__init__.py +0 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/awareness.py +1 -1
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/django_channels_consumer.py +18 -6
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/websocket_provider.py +31 -41
- jupyverse-0.7.1/plugins/yjs/fps_yjs/ywebsocket/websocket_server.py +88 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/yroom.py +42 -29
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/ystore.py +97 -103
- jupyverse-0.7.1/plugins/yjs/fps_yjs/ywebsocket/yutils.py +29 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywidgets/widgets.py +3 -3
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/pyproject.toml +6 -5
- {jupyverse-0.6.4 → jupyverse-0.7.1}/pyproject.toml +16 -20
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/conftest.py +23 -9
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/test_app.py +21 -13
- jupyverse-0.7.1/tests/test_auth.py +182 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/test_contents.py +40 -17
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/test_execute.py +70 -38
- jupyverse-0.7.1/tests/test_kernels.py +136 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/test_server.py +33 -34
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/test_settings.py +51 -21
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/utils.py +31 -10
- jupyverse-0.6.4/MANIFEST.in +0 -2
- jupyverse-0.6.4/config.yaml +0 -52
- jupyverse-0.6.4/jupyverse/__init__.py +0 -1
- jupyverse-0.6.4/jupyverse_api/jupyverse_api/cli.py +0 -110
- jupyverse-0.6.4/jupyverse_api/jupyverse_api/main/__init__.py +0 -99
- jupyverse-0.6.4/plugins/auth/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/auth/fps_auth/__init__.py +0 -1
- jupyverse-0.6.4/plugins/auth_fief/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/auth_fief/fps_auth_fief/__init__.py +0 -1
- jupyverse-0.6.4/plugins/auth_fief/fps_auth_fief/main.py +0 -23
- jupyverse-0.6.4/plugins/auth_jupyterhub/fps_auth_jupyterhub/main.py +0 -50
- jupyverse-0.6.4/plugins/contents/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/contents/fps_contents/__init__.py +0 -1
- jupyverse-0.6.4/plugins/contents/fps_contents/fileid.py +0 -212
- jupyverse-0.6.4/plugins/contents/fps_contents/main.py +0 -19
- jupyverse-0.6.4/plugins/frontend/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/frontend/fps_frontend/__init__.py +0 -1
- jupyverse-0.6.4/plugins/frontend/fps_frontend/main.py +0 -14
- jupyverse-0.6.4/plugins/jupyterlab/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/jupyterlab/fps_jupyterlab/__init__.py +0 -1
- jupyverse-0.6.4/plugins/jupyterlab/fps_jupyterlab/main.py +0 -28
- jupyverse-0.6.4/plugins/kernels/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/kernels/fps_kernels/__init__.py +0 -1
- jupyverse-0.6.4/plugins/kernels/fps_kernels/main.py +0 -56
- jupyverse-0.6.4/plugins/lab/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/lab/fps_lab/__init__.py +0 -1
- jupyverse-0.6.4/plugins/lab/fps_lab/main.py +0 -23
- jupyverse-0.6.4/plugins/login/MANIFEST.in +0 -2
- jupyverse-0.6.4/plugins/login/fps_login/__init__.py +0 -1
- jupyverse-0.6.4/plugins/login/fps_login/main.py +0 -19
- jupyverse-0.6.4/plugins/nbconvert/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/nbconvert/fps_nbconvert/__init__.py +0 -1
- jupyverse-0.6.4/plugins/nbconvert/fps_nbconvert/main.py +0 -19
- jupyverse-0.6.4/plugins/noauth/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/noauth/fps_noauth/__init__.py +0 -1
- jupyverse-0.6.4/plugins/noauth/fps_noauth/main.py +0 -14
- jupyverse-0.6.4/plugins/notebook/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/notebook/fps_notebook/__init__.py +0 -1
- jupyverse-0.6.4/plugins/notebook/fps_notebook/main.py +0 -23
- jupyverse-0.6.4/plugins/resource_usage/fps_resource_usage/__init__.py +0 -1
- jupyverse-0.6.4/plugins/resource_usage/fps_resource_usage/main.py +0 -22
- jupyverse-0.6.4/plugins/terminals/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/terminals/fps_terminals/__init__.py +0 -1
- jupyverse-0.6.4/plugins/terminals/fps_terminals/main.py +0 -28
- jupyverse-0.6.4/plugins/terminals/fps_terminals/server.py +0 -82
- jupyverse-0.6.4/plugins/webdav/fps_webdav/__init__.py +0 -1
- jupyverse-0.6.4/plugins/webdav/fps_webdav/main.py +0 -20
- jupyverse-0.6.4/plugins/webdav/tests/test_webdav.py +0 -47
- jupyverse-0.6.4/plugins/yjs/MANIFEST.in +0 -1
- jupyverse-0.6.4/plugins/yjs/fps_yjs/__init__.py +0 -1
- jupyverse-0.6.4/plugins/yjs/fps_yjs/main.py +0 -41
- jupyverse-0.6.4/plugins/yjs/fps_yjs/ywebsocket/websocket_server.py +0 -205
- jupyverse-0.6.4/plugins/yjs/fps_yjs/ywebsocket/yutils.py +0 -155
- jupyverse-0.6.4/tests/test_auth.py +0 -131
- jupyverse-0.6.4/tests/test_kernels.py +0 -102
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.devcontainer/devcontainer.json +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.github/workflows/check-release.yml +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/.gitignore +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/CONTRIBUTING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/binder/jupyter_notebook_config.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/binder/postBuild +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/binder/start +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/index.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/install.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/jupyter.svg +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/auth.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/contents.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/frontend.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/jupyterlab.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/kernels.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/lab.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/login.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/nbconvert.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/notebook.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/resource_usage.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/terminals.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/plugins/yjs.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/tutorials/jupyterhub_jupyverse_deployment.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/tutorials/standalone_jupyverse_deployment.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/usage/microservices.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/usage/multi_user.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/docs/usage/single_user.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/auth/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/contents/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/exceptions.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/frontend/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/jupyterlab/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/kernels/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/kernels/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/lab/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/login/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/nbconvert/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/notebook/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/resource_usage/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/terminals/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/yjs/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/jupyverse_api/jupyverse_api/yjs/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/notebooks/admin_users.ipynb +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/notebooks/admin_users.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/config.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/models.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth/fps_auth/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/fps_auth_fief/backend.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_fief/fps_auth_fief/config.py +0 -0
- {jupyverse-0.6.4/plugins/contents/fps_contents → jupyverse-0.7.1/plugins/auth_fief/fps_auth_fief}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/config.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/db.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/launch.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/auth_jupyterhub/fps_auth_jupyterhub/models.py +0 -0
- {jupyverse-0.6.4/plugins/frontend/fps_frontend → jupyverse-0.7.1/plugins/auth_jupyterhub/fps_auth_jupyterhub}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/contents/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/contents/README.md +0 -0
- {jupyverse-0.6.4/plugins/jupyterlab/fps_jupyterlab → jupyverse-0.7.1/plugins/contents/fps_contents}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/frontend/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/frontend/README.md +0 -0
- {jupyverse-0.6.4/plugins/noauth/fps_noauth → jupyverse-0.7.1/plugins/frontend/fps_frontend}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/jupyterlab/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/jupyterlab/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/jupyterlab/fps_jupyterlab/index.py +0 -0
- {jupyverse-0.6.4/plugins/webdav/fps_webdav → jupyverse-0.7.1/plugins/jupyterlab/fps_jupyterlab}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/kernelspec.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_driver/paths.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_server/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/kernels/fps_kernels/kernel_server/message.py +0 -0
- {jupyverse-0.6.4/plugins/yjs/fps_yjs → jupyverse-0.7.1/plugins/kernels/fps_kernels}/py.typed +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/lab/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/lab/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/lab/fps_lab/static/favicon.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/routes.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-busy-1.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-busy-2.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-busy-3.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-file.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-notebook.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon-terminal.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/favicons/favicon.ico +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/index.html +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/logo/github.svg +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/logo/logo.png +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/login/fps_login/static/style/index.css +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/nbconvert/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/nbconvert/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/nbconvert/fps_nbconvert/routes.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/noauth/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/noauth/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/noauth/fps_noauth/backends.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/notebook/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/notebook/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/resource_usage/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/resource_usage/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/resource_usage/fps_resource_usage/routes.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/terminals/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/terminals/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/webdav/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/webdav/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/webdav/fps_webdav/config.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/COPYING.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/README.md +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/utils.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/yfile.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ydocs/yunicode.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/asgi_server.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywebsocket/websocket.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/plugins/yjs/fps_yjs/ywidgets/__init__.py +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/pytest.ini +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/data/notebook0.ipynb +0 -0
- {jupyverse-0.6.4 → jupyverse-0.7.1}/tests/data/notebook1.ipynb +0 -0
@@ -21,7 +21,7 @@ jobs:
|
|
21
21
|
uses: actions/checkout@v3
|
22
22
|
- uses: actions/setup-python@v4
|
23
23
|
with:
|
24
|
-
python-version: '3.
|
24
|
+
python-version: '3.13'
|
25
25
|
cache: 'pip'
|
26
26
|
- name: Install hatch
|
27
27
|
run: |
|
@@ -43,13 +43,13 @@ jobs:
|
|
43
43
|
fail-fast: false
|
44
44
|
matrix:
|
45
45
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
46
|
-
python-version: [ '3.
|
46
|
+
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
|
47
47
|
|
48
48
|
steps:
|
49
49
|
- name: Checkout
|
50
|
-
uses: actions/checkout@
|
50
|
+
uses: actions/checkout@v4
|
51
51
|
|
52
|
-
- uses: actions/setup-python@
|
52
|
+
- uses: actions/setup-python@v5
|
53
53
|
with:
|
54
54
|
python-version: ${{ matrix.python-version }}
|
55
55
|
cache: 'pip'
|
@@ -2,6 +2,40 @@
|
|
2
2
|
|
3
3
|
<!-- <START NEW CHANGELOG ENTRY> -->
|
4
4
|
|
5
|
+
## 0.7.1
|
6
|
+
|
7
|
+
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.7.0...96cb8831e330527089ebbf41d649cbe9c8b32053))
|
8
|
+
|
9
|
+
### Merged PRs
|
10
|
+
|
11
|
+
- Require versions >=0.7.0 [#457](https://github.com/jupyter-server/jupyverse/pull/457) ([@davidbrochart](https://github.com/davidbrochart))
|
12
|
+
- Unpin Python version in Binder [#456](https://github.com/jupyter-server/jupyverse/pull/456) ([@davidbrochart](https://github.com/davidbrochart))
|
13
|
+
- Fix fps-notebook base URL [#455](https://github.com/jupyter-server/jupyverse/pull/455) ([@davidbrochart](https://github.com/davidbrochart))
|
14
|
+
- Update README [#454](https://github.com/jupyter-server/jupyverse/pull/454) ([@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=2025-02-14&to=2025-02-14&type=c))
|
19
|
+
|
20
|
+
[@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2025-02-14..2025-02-14&type=Issues)
|
21
|
+
|
22
|
+
<!-- <END NEW CHANGELOG ENTRY> -->
|
23
|
+
|
24
|
+
## 0.7.0
|
25
|
+
|
26
|
+
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.4...6fe98eab9ef0cef9d77a49bed92829ae3fb3538c))
|
27
|
+
|
28
|
+
### Merged PRs
|
29
|
+
|
30
|
+
- Switch to FPS [#453](https://github.com/jupyter-server/jupyverse/pull/453) ([@davidbrochart](https://github.com/davidbrochart))
|
31
|
+
- Fixing typo in the documentation [#452](https://github.com/jupyter-server/jupyverse/pull/452) ([@ThePavolC](https://github.com/ThePavolC))
|
32
|
+
|
33
|
+
### Contributors to this release
|
34
|
+
|
35
|
+
([GitHub contributors page for this release](https://github.com/jupyter-server/jupyverse/graphs/contributors?from=2024-10-15&to=2025-02-14&type=c))
|
36
|
+
|
37
|
+
[@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2024-10-15..2025-02-14&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Apre-commit-ci+updated%3A2024-10-15..2025-02-14&type=Issues) | [@ThePavolC](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3AThePavolC+updated%3A2024-10-15..2025-02-14&type=Issues)
|
38
|
+
|
5
39
|
## 0.6.4
|
6
40
|
|
7
41
|
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.3...69394c087d0645c784ff14e3cb71557c7a0d5cfa))
|
@@ -16,8 +50,6 @@
|
|
16
50
|
|
17
51
|
[@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2024-10-02..2024-10-15&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Apre-commit-ci+updated%3A2024-10-02..2024-10-15&type=Issues)
|
18
52
|
|
19
|
-
<!-- <END NEW CHANGELOG ENTRY> -->
|
20
|
-
|
21
53
|
## 0.6.3
|
22
54
|
|
23
55
|
([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.2...aa6854a51665d95216340d7fda1ba111af6aef74))
|
@@ -1,51 +1,50 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: jupyverse
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.1
|
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>
|
7
7
|
License: BSD 3-Clause License
|
8
8
|
License-File: COPYING.md
|
9
9
|
Keywords: fastapi,jupyter,plugins,server
|
10
|
-
Requires-Python: >=3.
|
11
|
-
Requires-Dist: fps-contents<1,>=0.
|
12
|
-
Requires-Dist: fps-frontend<1,>=0.
|
13
|
-
Requires-Dist: fps-kernels<1,>=0.
|
14
|
-
Requires-Dist: fps-lab<1,>=0.
|
15
|
-
Requires-Dist: fps-nbconvert<1,>=0.
|
16
|
-
Requires-Dist: fps-terminals<1,>=0.
|
17
|
-
Requires-Dist: fps-yjs<1,>=0.
|
18
|
-
Requires-Dist: jupyverse-api<1,>=0.
|
10
|
+
Requires-Python: >=3.9
|
11
|
+
Requires-Dist: fps-contents<1,>=0.7.0
|
12
|
+
Requires-Dist: fps-frontend<1,>=0.7.0
|
13
|
+
Requires-Dist: fps-kernels<1,>=0.7.0
|
14
|
+
Requires-Dist: fps-lab<1,>=0.7.0
|
15
|
+
Requires-Dist: fps-nbconvert<1,>=0.7.0
|
16
|
+
Requires-Dist: fps-terminals<1,>=0.7.0
|
17
|
+
Requires-Dist: fps-yjs<1,>=0.7.0
|
18
|
+
Requires-Dist: jupyverse-api<1,>=0.7.0
|
19
19
|
Provides-Extra: auth
|
20
|
-
Requires-Dist: fps-auth<1,>=0.
|
21
|
-
Requires-Dist: fps-login<1,>=0.
|
20
|
+
Requires-Dist: fps-auth<1,>=0.7.0; extra == 'auth'
|
21
|
+
Requires-Dist: fps-login<1,>=0.7.0; extra == 'auth'
|
22
22
|
Provides-Extra: auth-fief
|
23
|
-
Requires-Dist: fps-auth-fief<1,>=0.
|
23
|
+
Requires-Dist: fps-auth-fief<1,>=0.7.0; extra == 'auth-fief'
|
24
24
|
Provides-Extra: auth-jupyterhub
|
25
|
-
Requires-Dist: fps-auth-jupyterhub<1,>=0.
|
25
|
+
Requires-Dist: fps-auth-jupyterhub<1,>=0.7.0; extra == 'auth-jupyterhub'
|
26
26
|
Provides-Extra: docs
|
27
27
|
Requires-Dist: mkdocs; extra == 'docs'
|
28
28
|
Requires-Dist: mkdocs-material; extra == 'docs'
|
29
29
|
Provides-Extra: jupyterlab
|
30
|
-
Requires-Dist: fps-jupyterlab<1,>=0.
|
30
|
+
Requires-Dist: fps-jupyterlab<1,>=0.7.0; extra == 'jupyterlab'
|
31
31
|
Provides-Extra: noauth
|
32
|
-
Requires-Dist: fps-noauth<1,>=0.
|
32
|
+
Requires-Dist: fps-noauth<1,>=0.7.0; extra == 'noauth'
|
33
33
|
Provides-Extra: notebook
|
34
|
-
Requires-Dist: fps-notebook<1,>=0.
|
34
|
+
Requires-Dist: fps-notebook<1,>=0.7.0; extra == 'notebook'
|
35
35
|
Provides-Extra: test
|
36
36
|
Requires-Dist: httpx; extra == 'test'
|
37
37
|
Requires-Dist: httpx-ws>=0.4.1; extra == 'test'
|
38
38
|
Requires-Dist: ipykernel; extra == 'test'
|
39
39
|
Requires-Dist: mypy; extra == 'test'
|
40
40
|
Requires-Dist: pytest; extra == 'test'
|
41
|
-
Requires-Dist: pytest-asyncio; extra == 'test'
|
42
41
|
Requires-Dist: pytest-env; extra == 'test'
|
43
42
|
Requires-Dist: pytest-rerunfailures; extra == 'test'
|
44
43
|
Requires-Dist: pytest-timeout; extra == 'test'
|
45
44
|
Requires-Dist: requests; extra == 'test'
|
46
45
|
Requires-Dist: ruff>=0.1.2; extra == 'test'
|
46
|
+
Requires-Dist: trio; extra == 'test'
|
47
47
|
Requires-Dist: types-setuptools; extra == 'test'
|
48
|
-
Requires-Dist: websockets; extra == 'test'
|
49
48
|
Requires-Dist: ypywidgets-textual<0.6.0,>=0.5.0; extra == 'test'
|
50
49
|
Requires-Dist: ypywidgets<0.10.0,>=0.9.3; extra == 'test'
|
51
50
|
Description-Content-Type: text/markdown
|
@@ -54,7 +53,7 @@ Description-Content-Type: text/markdown
|
|
54
53
|
|
55
54
|
# jupyverse
|
56
55
|
|
57
|
-
A set of [
|
56
|
+
A set of [FPS](https://github.com/jupyter-server/fps) modules implementing a Jupyter server.
|
58
57
|
|
59
58
|
Try it online:
|
60
59
|
- JupyterLab frontend: [](https://mybinder.org/v2/gh/jupyter-server/jupyverse/HEAD?urlpath=jupyverse-jupyterlab)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# jupyverse
|
4
4
|
|
5
|
-
A set of [
|
5
|
+
A set of [FPS](https://github.com/jupyter-server/fps) modules implementing a Jupyter server.
|
6
6
|
|
7
7
|
Try it online:
|
8
8
|
- JupyterLab frontend: [](https://mybinder.org/v2/gh/jupyter-server/jupyverse/HEAD?urlpath=jupyverse-jupyterlab)
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.7.1"
|
@@ -1,10 +1,11 @@
|
|
1
|
-
from typing import Dict
|
1
|
+
from typing import Any, Dict
|
2
2
|
|
3
|
+
from anyio import Event
|
3
4
|
from pydantic import BaseModel
|
4
5
|
|
5
6
|
from .app import App
|
6
7
|
|
7
|
-
__version__ = "0.
|
8
|
+
__version__ = "0.7.1"
|
8
9
|
|
9
10
|
|
10
11
|
class Singleton(type):
|
@@ -41,3 +42,36 @@ class Router:
|
|
41
42
|
|
42
43
|
def add_middleware(self, middleware, *args, **kwargs) -> None:
|
43
44
|
self._app.add_middleware(middleware, *args, **kwargs)
|
45
|
+
|
46
|
+
|
47
|
+
class ResourceLock:
|
48
|
+
"""ResourceLock ensures that accesses cannot be done concurrently on the same resource.
|
49
|
+
"""
|
50
|
+
_locks: Dict[Any, Event]
|
51
|
+
|
52
|
+
def __init__(self):
|
53
|
+
self._locks = {}
|
54
|
+
|
55
|
+
def __call__(self, idx: Any):
|
56
|
+
return _ResourceLock(idx, self._locks)
|
57
|
+
|
58
|
+
|
59
|
+
class _ResourceLock:
|
60
|
+
_idx: Any
|
61
|
+
_locks: Dict[Any, Event]
|
62
|
+
_lock: Event
|
63
|
+
|
64
|
+
def __init__(self, idx: Any, locks: Dict[Any, Event]):
|
65
|
+
self._idx = idx
|
66
|
+
self._locks = locks
|
67
|
+
|
68
|
+
async def __aenter__(self):
|
69
|
+
while True:
|
70
|
+
if self._idx not in self._locks:
|
71
|
+
break
|
72
|
+
await self._locks[self._idx].wait()
|
73
|
+
self._locks[self._idx] = self._lock = Event()
|
74
|
+
|
75
|
+
async def __aexit__(self, exc_type, exc_value, exc_tb):
|
76
|
+
self._lock.set()
|
77
|
+
del self._locks[self._idx]
|
@@ -1,15 +1,15 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import logging
|
4
3
|
from collections import defaultdict
|
5
4
|
from datetime import datetime, timezone
|
6
5
|
from typing import Dict, List
|
7
6
|
|
7
|
+
import structlog
|
8
8
|
from fastapi import FastAPI, Request
|
9
9
|
|
10
10
|
from ..exceptions import RedirectException, _redirect_exception_handler
|
11
11
|
|
12
|
-
logger =
|
12
|
+
logger = structlog.get_logger()
|
13
13
|
|
14
14
|
|
15
15
|
class App:
|
@@ -57,7 +57,7 @@ class App:
|
|
57
57
|
f"{_type} adds a handler for a path that is already defined in "
|
58
58
|
f"{_router}: {path}"
|
59
59
|
)
|
60
|
-
logger.debug("
|
60
|
+
logger.debug("Handler added", type=_type, path=path)
|
61
61
|
new_paths.append(path)
|
62
62
|
self._router_paths[_type].extend(new_paths)
|
63
63
|
self._app.include_router(router, **kwargs)
|
@@ -69,7 +69,7 @@ class App:
|
|
69
69
|
f"{_type } mounts a path that is already defined in {_router}: {path}"
|
70
70
|
)
|
71
71
|
self._router_paths[_type].append(path)
|
72
|
-
logger.debug("
|
72
|
+
logger.debug("Path mounted", type=_type, path=path)
|
73
73
|
self._app.mount(path, *args, **kwargs)
|
74
74
|
|
75
75
|
def add_middleware(self, middleware, *args, **kwargs) -> None:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
|
-
from typing import Any, Callable, Dict, List, Optional, Tuple
|
2
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple
|
3
3
|
|
4
4
|
from jupyverse_api import Config
|
5
5
|
|
@@ -19,7 +19,7 @@ class Auth(ABC):
|
|
19
19
|
def websocket_auth(
|
20
20
|
self,
|
21
21
|
permissions: Optional[Dict[str, List[str]]] = None,
|
22
|
-
) -> Callable[[], Tuple[Any, Dict[str, List[str]]]]:
|
22
|
+
) -> Callable[[Any], Awaitable[Optional[Tuple[Any, Optional[Dict[str, List[str]]]]]]]:
|
23
23
|
...
|
24
24
|
|
25
25
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
import io
|
2
|
+
import json
|
3
|
+
import sys
|
4
|
+
from typing import Any, List, Tuple
|
5
|
+
|
6
|
+
import rich_click as click
|
7
|
+
from fps import main as fps_main
|
8
|
+
|
9
|
+
if sys.version_info < (3, 10):
|
10
|
+
from importlib_metadata import entry_points
|
11
|
+
else:
|
12
|
+
from importlib.metadata import entry_points
|
13
|
+
|
14
|
+
|
15
|
+
@click.command() # type: ignore
|
16
|
+
@click.option(
|
17
|
+
"--debug",
|
18
|
+
is_flag=True,
|
19
|
+
show_default=True,
|
20
|
+
default=False,
|
21
|
+
help="Enable debug mode.",
|
22
|
+
)
|
23
|
+
@click.option(
|
24
|
+
"--open-browser",
|
25
|
+
is_flag=True,
|
26
|
+
show_default=True,
|
27
|
+
default=False,
|
28
|
+
help="Open a browser window.",
|
29
|
+
)
|
30
|
+
@click.option(
|
31
|
+
"--host",
|
32
|
+
type=str,
|
33
|
+
default="127.0.0.1",
|
34
|
+
help="The host URL.",
|
35
|
+
)
|
36
|
+
@click.option(
|
37
|
+
"--port",
|
38
|
+
type=int,
|
39
|
+
default=8000,
|
40
|
+
help="The host port.",
|
41
|
+
)
|
42
|
+
@click.option(
|
43
|
+
"--query-param",
|
44
|
+
multiple=True,
|
45
|
+
type=str,
|
46
|
+
help='The query parameter key and value, separated by "=".',
|
47
|
+
)
|
48
|
+
@click.option(
|
49
|
+
"--allow-origin",
|
50
|
+
multiple=True,
|
51
|
+
type=str,
|
52
|
+
help="The origin to allow.",
|
53
|
+
)
|
54
|
+
@click.option(
|
55
|
+
"--set",
|
56
|
+
"set_",
|
57
|
+
multiple=True,
|
58
|
+
type=str,
|
59
|
+
help="Set configuration.",
|
60
|
+
)
|
61
|
+
@click.option(
|
62
|
+
"--disable",
|
63
|
+
multiple=True,
|
64
|
+
type=str,
|
65
|
+
help="Disable plugin.",
|
66
|
+
)
|
67
|
+
def main(
|
68
|
+
debug: bool = False,
|
69
|
+
open_browser: bool = False,
|
70
|
+
host: str = "127.0.0.1",
|
71
|
+
port: int = 8000,
|
72
|
+
set_: Tuple[str, ...] = (),
|
73
|
+
disable: Tuple[str, ...] = (),
|
74
|
+
allow_origin: Tuple[str, ...] = (),
|
75
|
+
query_param: Tuple[str, ...] = (),
|
76
|
+
) -> None:
|
77
|
+
query_params_dict = {}
|
78
|
+
for qp in query_param:
|
79
|
+
key, _, value = qp.partition("=")
|
80
|
+
query_params_dict[key] = value
|
81
|
+
query_params_str = json.dumps(query_params_dict)
|
82
|
+
allow_origins_str = json.dumps(allow_origin)
|
83
|
+
set_list: List[str] = list(set_)
|
84
|
+
set_list.append(f"debug={debug}")
|
85
|
+
set_list.append(f"open_browser={open_browser}")
|
86
|
+
set_list.append(f"host={host}")
|
87
|
+
set_list.append(f"port={port}")
|
88
|
+
set_list.append(f"allow_origins={allow_origins_str}")
|
89
|
+
set_list.append(f"query_params={query_params_str}")
|
90
|
+
pluggin_config = io.StringIO(json.dumps(get_pluggin_config(disable)))
|
91
|
+
fps_main.callback(
|
92
|
+
"",
|
93
|
+
set_=set_list,
|
94
|
+
config=pluggin_config,
|
95
|
+
) # type: ignore
|
96
|
+
|
97
|
+
|
98
|
+
def get_pluggin_config(disable: Tuple[str, ...]) -> dict[str, Any]:
|
99
|
+
jupyverse_modules = [
|
100
|
+
ep.name
|
101
|
+
for ep in entry_points(group="jupyverse.modules")
|
102
|
+
if ep.name not in disable
|
103
|
+
]
|
104
|
+
config = {
|
105
|
+
"jupyverse": {
|
106
|
+
"type":"jupyverse_api.main:JupyverseModule",
|
107
|
+
"modules": {
|
108
|
+
module: {
|
109
|
+
"type": module
|
110
|
+
}
|
111
|
+
for module in jupyverse_modules
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
return config
|
@@ -1,11 +1,12 @@
|
|
1
|
-
import
|
1
|
+
from __future__ import annotations
|
2
|
+
|
2
3
|
from abc import ABC, abstractmethod
|
3
4
|
from pathlib import Path
|
4
5
|
from typing import Dict, List, Optional, Union
|
5
6
|
|
6
7
|
from fastapi import APIRouter, Depends, Request, Response
|
7
8
|
|
8
|
-
from jupyverse_api import Router
|
9
|
+
from jupyverse_api import ResourceLock, Router
|
9
10
|
|
10
11
|
from ..app import App
|
11
12
|
from ..auth import Auth, User
|
@@ -13,8 +14,13 @@ from .models import Checkpoint, Content, SaveContent
|
|
13
14
|
|
14
15
|
|
15
16
|
class FileIdManager(ABC):
|
16
|
-
|
17
|
-
|
17
|
+
@abstractmethod
|
18
|
+
async def start(self) -> None:
|
19
|
+
...
|
20
|
+
|
21
|
+
@abstractmethod
|
22
|
+
async def stop(self) -> None:
|
23
|
+
...
|
18
24
|
|
19
25
|
@abstractmethod
|
20
26
|
async def get_path(self, file_id: str) -> str:
|
@@ -32,9 +38,11 @@ class FileIdManager(ABC):
|
|
32
38
|
|
33
39
|
|
34
40
|
class Contents(Router, ABC):
|
41
|
+
file_lock: ResourceLock
|
42
|
+
|
35
43
|
def __init__(self, app: App, auth: Auth):
|
36
44
|
super().__init__(app=app)
|
37
|
-
|
45
|
+
self.file_lock = ResourceLock()
|
38
46
|
router = APIRouter()
|
39
47
|
|
40
48
|
@router.post(
|
@@ -0,0 +1,110 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import logging
|
4
|
+
import webbrowser
|
5
|
+
from typing import Dict, List
|
6
|
+
|
7
|
+
import structlog
|
8
|
+
from anyio import Event, create_task_group
|
9
|
+
from fastapi import FastAPI
|
10
|
+
from fastapi.middleware.cors import CORSMiddleware
|
11
|
+
from fps import Module
|
12
|
+
from fps.web.fastapi import FastAPIModule
|
13
|
+
from pydantic import BaseModel, Json
|
14
|
+
|
15
|
+
from jupyverse_api import Config
|
16
|
+
|
17
|
+
from ..app import App
|
18
|
+
|
19
|
+
logger = structlog.get_logger()
|
20
|
+
|
21
|
+
|
22
|
+
class AppModule(Module):
|
23
|
+
def __init__(
|
24
|
+
self,
|
25
|
+
name: str,
|
26
|
+
*,
|
27
|
+
mount_path: str | None = None,
|
28
|
+
) -> None:
|
29
|
+
super().__init__(name)
|
30
|
+
self.mount_path = mount_path
|
31
|
+
|
32
|
+
async def prepare(self) -> None:
|
33
|
+
app = await self.get(FastAPI)
|
34
|
+
_app = App(app, mount_path=self.mount_path)
|
35
|
+
self.put(_app)
|
36
|
+
|
37
|
+
|
38
|
+
class JupyverseModule(FastAPIModule):
|
39
|
+
def __init__(self, name: str, **kwargs) -> None:
|
40
|
+
self.jupyverse_config = JupyverseConfig(**kwargs)
|
41
|
+
if self.jupyverse_config.debug:
|
42
|
+
structlog.stdlib.recreate_defaults(log_level=logging.DEBUG)
|
43
|
+
super().__init__(
|
44
|
+
name,
|
45
|
+
host=self.jupyverse_config.host,
|
46
|
+
port=self.jupyverse_config.port,
|
47
|
+
debug=self.jupyverse_config.debug,
|
48
|
+
)
|
49
|
+
self.lifespan = Lifespan()
|
50
|
+
|
51
|
+
async def prepare(self) -> None:
|
52
|
+
await super().prepare()
|
53
|
+
app = await self.get(App)
|
54
|
+
if self.jupyverse_config.allow_origins:
|
55
|
+
app.add_middleware(
|
56
|
+
CORSMiddleware,
|
57
|
+
allow_origins=self.jupyverse_config.allow_origins,
|
58
|
+
allow_credentials=True,
|
59
|
+
allow_methods=["*"],
|
60
|
+
allow_headers=["*"],
|
61
|
+
)
|
62
|
+
self._query_params = QueryParams(d={})
|
63
|
+
self._host = self.jupyverse_config.host
|
64
|
+
if not self._host.startswith("http"):
|
65
|
+
self._host = f"http://{self._host}"
|
66
|
+
self._port = self.jupyverse_config.port
|
67
|
+
host_url = Host(url=f"{self._host}:{self._port}/")
|
68
|
+
self.put(self._query_params)
|
69
|
+
self.put(host_url)
|
70
|
+
self.put(self.lifespan)
|
71
|
+
|
72
|
+
async def start(self) -> None:
|
73
|
+
async with create_task_group() as tg:
|
74
|
+
tg.start_soon(super().start)
|
75
|
+
await self.started.wait()
|
76
|
+
|
77
|
+
# at this point, the server has started
|
78
|
+
qp = self._query_params.d
|
79
|
+
if self.jupyverse_config.query_params:
|
80
|
+
qp.update(**self.jupyverse_config.query_params)
|
81
|
+
query_params_str = "?" + "&".join([f"{k}={v}" for k, v in qp.items()]) if qp else ""
|
82
|
+
url = f"{self._host}:{self._port}{query_params_str}"
|
83
|
+
logger.info("Server running", url=url)
|
84
|
+
if self.jupyverse_config.open_browser:
|
85
|
+
webbrowser.open_new_tab(url)
|
86
|
+
|
87
|
+
async def stop(self) -> None:
|
88
|
+
self.lifespan.shutdown_request.set()
|
89
|
+
|
90
|
+
|
91
|
+
class QueryParams(BaseModel):
|
92
|
+
d: Dict[str, str]
|
93
|
+
|
94
|
+
|
95
|
+
class Host(BaseModel):
|
96
|
+
url: str
|
97
|
+
|
98
|
+
|
99
|
+
class Lifespan:
|
100
|
+
def __init__(self):
|
101
|
+
self.shutdown_request = Event()
|
102
|
+
|
103
|
+
|
104
|
+
class JupyverseConfig(Config):
|
105
|
+
host: str = "127.0.0.1"
|
106
|
+
port: int = 8000
|
107
|
+
allow_origins: Json[List[str]] = []
|
108
|
+
open_browser: bool = False
|
109
|
+
query_params: Json[Dict[str, str]] = {}
|
110
|
+
debug: bool = False
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
6
6
|
name = "jupyverse_api"
|
7
7
|
description = "The public API for Jupyverse"
|
8
8
|
readme = "README.md"
|
9
|
-
requires-python = ">=3.
|
9
|
+
requires-python = ">=3.9"
|
10
10
|
keywords = [
|
11
11
|
"jupyverse", "api",
|
12
12
|
]
|
@@ -16,10 +16,11 @@ authors = [
|
|
16
16
|
classifiers = [
|
17
17
|
"Development Status :: 4 - Beta",
|
18
18
|
"Programming Language :: Python",
|
19
|
-
"Programming Language :: Python :: 3.8",
|
20
19
|
"Programming Language :: Python :: 3.9",
|
21
20
|
"Programming Language :: Python :: 3.10",
|
22
21
|
"Programming Language :: Python :: 3.11",
|
22
|
+
"Programming Language :: Python :: 3.12",
|
23
|
+
"Programming Language :: Python :: 3.13",
|
23
24
|
"Programming Language :: Python :: Implementation :: CPython",
|
24
25
|
"Programming Language :: Python :: Implementation :: PyPy",
|
25
26
|
]
|
@@ -28,8 +29,7 @@ dependencies = [
|
|
28
29
|
"pydantic >=2,<3",
|
29
30
|
"fastapi >=0.95.0,<1",
|
30
31
|
"rich-click >=1.6.1,<2",
|
31
|
-
"
|
32
|
-
"asphalt-web[fastapi] >=1.1.0,<2",
|
32
|
+
"fps[web] >=0.1.1,<0.2.0",
|
33
33
|
]
|
34
34
|
dynamic = ["version"]
|
35
35
|
|
@@ -42,12 +42,12 @@ Source = "https://github.com/jupyter-server/jupyverse/jupyverse_api"
|
|
42
42
|
[project.scripts]
|
43
43
|
jupyverse = "jupyverse_api.cli:main"
|
44
44
|
|
45
|
-
[project.entry-points."
|
46
|
-
app = "jupyverse_api.main:
|
47
|
-
jupyverse = "jupyverse_api.main:
|
45
|
+
[project.entry-points."fps.modules"]
|
46
|
+
app = "jupyverse_api.main:AppModule"
|
47
|
+
jupyverse = "jupyverse_api.main:JupyverseModule"
|
48
48
|
|
49
|
-
[project.entry-points."jupyverse.
|
50
|
-
app = "jupyverse_api.main:
|
49
|
+
[project.entry-points."jupyverse.modules"]
|
50
|
+
app = "jupyverse_api.main:AppModule"
|
51
51
|
|
52
52
|
[tool.hatch.version]
|
53
53
|
path = "jupyverse_api/__init__.py"
|