jupyverse 0.6.3__tar.gz → 0.7.0__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.
Files changed (303) hide show
  1. {jupyverse-0.6.3 → jupyverse-0.7.0}/.devcontainer/requirements.txt +1 -2
  2. {jupyverse-0.6.3 → jupyverse-0.7.0}/.github/workflows/test.yml +4 -4
  3. {jupyverse-0.6.3 → jupyverse-0.7.0}/.pre-commit-config.yaml +2 -2
  4. {jupyverse-0.6.3 → jupyverse-0.7.0}/CHANGELOG.md +31 -2
  5. {jupyverse-0.6.3 → jupyverse-0.7.0}/PKG-INFO +4 -5
  6. jupyverse-0.7.0/jupyverse/__init__.py +1 -0
  7. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/__init__.py +36 -2
  8. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/app/__init__.py +4 -4
  9. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/auth/__init__.py +2 -2
  10. jupyverse-0.7.0/jupyverse_api/jupyverse_api/cli.py +115 -0
  11. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/contents/__init__.py +13 -5
  12. jupyverse-0.7.0/jupyverse_api/jupyverse_api/main/__init__.py +110 -0
  13. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/terminals/__init__.py +1 -1
  14. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/pyproject.toml +9 -9
  15. jupyverse-0.7.0/jupyverse_api/tests/test_resource_lock.py +57 -0
  16. {jupyverse-0.6.3 → jupyverse-0.7.0}/mkdocs.yml +1 -1
  17. jupyverse-0.7.0/plugins/auth/fps_auth/__init__.py +1 -0
  18. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/backends.py +0 -3
  19. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/db.py +0 -3
  20. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/main.py +13 -22
  21. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/routes.py +2 -5
  22. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/pyproject.toml +3 -3
  23. jupyverse-0.7.0/plugins/auth_fief/fps_auth_fief/__init__.py +1 -0
  24. jupyverse-0.7.0/plugins/auth_fief/fps_auth_fief/main.py +20 -0
  25. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/fps_auth_fief/routes.py +2 -2
  26. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/pyproject.toml +1 -1
  27. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/__init__.py +1 -1
  28. jupyverse-0.7.0/plugins/auth_jupyterhub/fps_auth_jupyterhub/main.py +34 -0
  29. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/routes.py +24 -13
  30. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/pyproject.toml +4 -3
  31. jupyverse-0.7.0/plugins/contents/fps_contents/__init__.py +1 -0
  32. jupyverse-0.7.0/plugins/contents/fps_contents/fileid.py +224 -0
  33. jupyverse-0.7.0/plugins/contents/fps_contents/main.py +16 -0
  34. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/contents/fps_contents/routes.py +111 -97
  35. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/contents/pyproject.toml +5 -5
  36. jupyverse-0.7.0/plugins/frontend/fps_frontend/__init__.py +1 -0
  37. jupyverse-0.7.0/plugins/frontend/fps_frontend/main.py +12 -0
  38. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/frontend/pyproject.toml +3 -3
  39. jupyverse-0.7.0/plugins/jupyterlab/fps_jupyterlab/__init__.py +1 -0
  40. jupyverse-0.7.0/plugins/jupyterlab/fps_jupyterlab/main.py +26 -0
  41. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/jupyterlab/fps_jupyterlab/routes.py +1 -1
  42. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/jupyterlab/pyproject.toml +3 -3
  43. jupyverse-0.7.0/plugins/kernels/fps_kernels/__init__.py +1 -0
  44. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/connect.py +15 -14
  45. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/driver.py +108 -77
  46. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/message.py +1 -1
  47. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_server/server.py +58 -47
  48. jupyverse-0.7.0/plugins/kernels/fps_kernels/main.py +45 -0
  49. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/routes.py +51 -9
  50. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/pyproject.toml +6 -4
  51. jupyverse-0.7.0/plugins/lab/fps_lab/__init__.py +1 -0
  52. jupyverse-0.7.0/plugins/lab/fps_lab/main.py +20 -0
  53. jupyverse-0.7.0/plugins/lab/fps_lab/py.typed +0 -0
  54. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/lab/fps_lab/routes.py +0 -3
  55. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/lab/pyproject.toml +3 -3
  56. jupyverse-0.7.0/plugins/login/fps_login/__init__.py +1 -0
  57. jupyverse-0.7.0/plugins/login/fps_login/main.py +16 -0
  58. jupyverse-0.7.0/plugins/login/fps_login/py.typed +0 -0
  59. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/pyproject.toml +3 -3
  60. jupyverse-0.7.0/plugins/nbconvert/fps_nbconvert/__init__.py +1 -0
  61. jupyverse-0.7.0/plugins/nbconvert/fps_nbconvert/main.py +15 -0
  62. jupyverse-0.7.0/plugins/nbconvert/fps_nbconvert/py.typed +0 -0
  63. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/nbconvert/fps_nbconvert/routes.py +4 -2
  64. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/nbconvert/pyproject.toml +3 -3
  65. jupyverse-0.7.0/plugins/noauth/fps_noauth/__init__.py +1 -0
  66. jupyverse-0.7.0/plugins/noauth/fps_noauth/main.py +12 -0
  67. jupyverse-0.7.0/plugins/noauth/fps_noauth/py.typed +0 -0
  68. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/noauth/pyproject.toml +3 -3
  69. jupyverse-0.7.0/plugins/notebook/fps_notebook/__init__.py +1 -0
  70. jupyverse-0.7.0/plugins/notebook/fps_notebook/main.py +25 -0
  71. jupyverse-0.7.0/plugins/notebook/fps_notebook/py.typed +0 -0
  72. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/notebook/fps_notebook/routes.py +30 -25
  73. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/notebook/pyproject.toml +3 -3
  74. jupyverse-0.7.0/plugins/resource_usage/fps_resource_usage/__init__.py +1 -0
  75. jupyverse-0.7.0/plugins/resource_usage/fps_resource_usage/main.py +20 -0
  76. jupyverse-0.7.0/plugins/resource_usage/fps_resource_usage/py.typed +0 -0
  77. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/resource_usage/pyproject.toml +3 -3
  78. jupyverse-0.7.0/plugins/terminals/fps_terminals/__init__.py +1 -0
  79. jupyverse-0.7.0/plugins/terminals/fps_terminals/main.py +32 -0
  80. jupyverse-0.7.0/plugins/terminals/fps_terminals/py.typed +0 -0
  81. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/terminals/fps_terminals/routes.py +32 -4
  82. jupyverse-0.7.0/plugins/terminals/fps_terminals/server.py +150 -0
  83. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/terminals/fps_terminals/win_server.py +22 -16
  84. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/terminals/pyproject.toml +3 -3
  85. jupyverse-0.7.0/plugins/webdav/fps_webdav/__init__.py +1 -0
  86. jupyverse-0.7.0/plugins/webdav/fps_webdav/main.py +18 -0
  87. jupyverse-0.7.0/plugins/webdav/fps_webdav/py.typed +0 -0
  88. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/webdav/fps_webdav/routes.py +10 -6
  89. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/webdav/pyproject.toml +4 -4
  90. jupyverse-0.7.0/plugins/webdav/tests/conftest.py +15 -0
  91. jupyverse-0.7.0/plugins/webdav/tests/test_webdav.py +54 -0
  92. jupyverse-0.7.0/plugins/yjs/fps_yjs/__init__.py +1 -0
  93. jupyverse-0.7.0/plugins/yjs/fps_yjs/main.py +38 -0
  94. jupyverse-0.7.0/plugins/yjs/fps_yjs/py.typed +0 -0
  95. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/routes.py +145 -108
  96. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/ybasedoc.py +3 -0
  97. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/yblob.py +2 -0
  98. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/ynotebook.py +3 -0
  99. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/__init__.py +0 -1
  100. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/awareness.py +1 -1
  101. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/django_channels_consumer.py +18 -6
  102. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/websocket_provider.py +31 -41
  103. jupyverse-0.7.0/plugins/yjs/fps_yjs/ywebsocket/websocket_server.py +88 -0
  104. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/yroom.py +42 -29
  105. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/ystore.py +97 -103
  106. jupyverse-0.7.0/plugins/yjs/fps_yjs/ywebsocket/yutils.py +29 -0
  107. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywidgets/widgets.py +3 -3
  108. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/pyproject.toml +5 -4
  109. {jupyverse-0.6.3 → jupyverse-0.7.0}/pyproject.toml +2 -6
  110. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/conftest.py +23 -9
  111. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/test_app.py +21 -13
  112. jupyverse-0.7.0/tests/test_auth.py +182 -0
  113. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/test_contents.py +40 -17
  114. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/test_execute.py +70 -38
  115. jupyverse-0.7.0/tests/test_kernels.py +136 -0
  116. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/test_server.py +33 -34
  117. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/test_settings.py +51 -21
  118. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/utils.py +31 -10
  119. jupyverse-0.6.3/MANIFEST.in +0 -2
  120. jupyverse-0.6.3/config.yaml +0 -52
  121. jupyverse-0.6.3/jupyverse/__init__.py +0 -1
  122. jupyverse-0.6.3/jupyverse_api/jupyverse_api/cli.py +0 -110
  123. jupyverse-0.6.3/jupyverse_api/jupyverse_api/main/__init__.py +0 -99
  124. jupyverse-0.6.3/plugins/auth/MANIFEST.in +0 -1
  125. jupyverse-0.6.3/plugins/auth/fps_auth/__init__.py +0 -1
  126. jupyverse-0.6.3/plugins/auth_fief/MANIFEST.in +0 -1
  127. jupyverse-0.6.3/plugins/auth_fief/fps_auth_fief/__init__.py +0 -1
  128. jupyverse-0.6.3/plugins/auth_fief/fps_auth_fief/main.py +0 -23
  129. jupyverse-0.6.3/plugins/auth_jupyterhub/fps_auth_jupyterhub/main.py +0 -50
  130. jupyverse-0.6.3/plugins/contents/MANIFEST.in +0 -1
  131. jupyverse-0.6.3/plugins/contents/fps_contents/__init__.py +0 -1
  132. jupyverse-0.6.3/plugins/contents/fps_contents/fileid.py +0 -212
  133. jupyverse-0.6.3/plugins/contents/fps_contents/main.py +0 -19
  134. jupyverse-0.6.3/plugins/frontend/MANIFEST.in +0 -1
  135. jupyverse-0.6.3/plugins/frontend/fps_frontend/__init__.py +0 -1
  136. jupyverse-0.6.3/plugins/frontend/fps_frontend/main.py +0 -14
  137. jupyverse-0.6.3/plugins/jupyterlab/MANIFEST.in +0 -1
  138. jupyverse-0.6.3/plugins/jupyterlab/fps_jupyterlab/__init__.py +0 -1
  139. jupyverse-0.6.3/plugins/jupyterlab/fps_jupyterlab/main.py +0 -28
  140. jupyverse-0.6.3/plugins/kernels/MANIFEST.in +0 -1
  141. jupyverse-0.6.3/plugins/kernels/fps_kernels/__init__.py +0 -1
  142. jupyverse-0.6.3/plugins/kernels/fps_kernels/main.py +0 -56
  143. jupyverse-0.6.3/plugins/lab/MANIFEST.in +0 -1
  144. jupyverse-0.6.3/plugins/lab/fps_lab/__init__.py +0 -1
  145. jupyverse-0.6.3/plugins/lab/fps_lab/main.py +0 -23
  146. jupyverse-0.6.3/plugins/login/MANIFEST.in +0 -2
  147. jupyverse-0.6.3/plugins/login/fps_login/__init__.py +0 -1
  148. jupyverse-0.6.3/plugins/login/fps_login/main.py +0 -19
  149. jupyverse-0.6.3/plugins/nbconvert/MANIFEST.in +0 -1
  150. jupyverse-0.6.3/plugins/nbconvert/fps_nbconvert/__init__.py +0 -1
  151. jupyverse-0.6.3/plugins/nbconvert/fps_nbconvert/main.py +0 -19
  152. jupyverse-0.6.3/plugins/noauth/MANIFEST.in +0 -1
  153. jupyverse-0.6.3/plugins/noauth/fps_noauth/__init__.py +0 -1
  154. jupyverse-0.6.3/plugins/noauth/fps_noauth/main.py +0 -14
  155. jupyverse-0.6.3/plugins/notebook/MANIFEST.in +0 -1
  156. jupyverse-0.6.3/plugins/notebook/fps_notebook/__init__.py +0 -1
  157. jupyverse-0.6.3/plugins/notebook/fps_notebook/main.py +0 -23
  158. jupyverse-0.6.3/plugins/resource_usage/fps_resource_usage/__init__.py +0 -1
  159. jupyverse-0.6.3/plugins/resource_usage/fps_resource_usage/main.py +0 -22
  160. jupyverse-0.6.3/plugins/terminals/MANIFEST.in +0 -1
  161. jupyverse-0.6.3/plugins/terminals/fps_terminals/__init__.py +0 -1
  162. jupyverse-0.6.3/plugins/terminals/fps_terminals/main.py +0 -28
  163. jupyverse-0.6.3/plugins/terminals/fps_terminals/server.py +0 -82
  164. jupyverse-0.6.3/plugins/webdav/fps_webdav/__init__.py +0 -1
  165. jupyverse-0.6.3/plugins/webdav/fps_webdav/main.py +0 -20
  166. jupyverse-0.6.3/plugins/webdav/tests/test_webdav.py +0 -47
  167. jupyverse-0.6.3/plugins/yjs/MANIFEST.in +0 -1
  168. jupyverse-0.6.3/plugins/yjs/fps_yjs/__init__.py +0 -1
  169. jupyverse-0.6.3/plugins/yjs/fps_yjs/main.py +0 -41
  170. jupyverse-0.6.3/plugins/yjs/fps_yjs/ywebsocket/websocket_server.py +0 -205
  171. jupyverse-0.6.3/plugins/yjs/fps_yjs/ywebsocket/yutils.py +0 -155
  172. jupyverse-0.6.3/tests/test_auth.py +0 -131
  173. jupyverse-0.6.3/tests/test_kernels.py +0 -102
  174. {jupyverse-0.6.3 → jupyverse-0.7.0}/.devcontainer/devcontainer.json +0 -0
  175. {jupyverse-0.6.3 → jupyverse-0.7.0}/.github/workflows/check-release.yml +0 -0
  176. {jupyverse-0.6.3 → jupyverse-0.7.0}/.gitignore +0 -0
  177. {jupyverse-0.6.3 → jupyverse-0.7.0}/CONTRIBUTING.md +0 -0
  178. {jupyverse-0.6.3 → jupyverse-0.7.0}/COPYING.md +0 -0
  179. {jupyverse-0.6.3 → jupyverse-0.7.0}/README.md +0 -0
  180. {jupyverse-0.6.3 → jupyverse-0.7.0}/binder/environment.yml +0 -0
  181. {jupyverse-0.6.3 → jupyverse-0.7.0}/binder/jupyter_notebook_config.py +0 -0
  182. {jupyverse-0.6.3 → jupyverse-0.7.0}/binder/postBuild +0 -0
  183. {jupyverse-0.6.3 → jupyverse-0.7.0}/binder/start +0 -0
  184. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/index.md +0 -0
  185. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/install.md +0 -0
  186. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/jupyter.svg +0 -0
  187. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/auth.md +0 -0
  188. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/contents.md +0 -0
  189. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/frontend.md +0 -0
  190. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/jupyterlab.md +0 -0
  191. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/kernels.md +0 -0
  192. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/lab.md +0 -0
  193. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/login.md +0 -0
  194. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/nbconvert.md +0 -0
  195. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/notebook.md +0 -0
  196. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/resource_usage.md +0 -0
  197. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/terminals.md +0 -0
  198. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/plugins/yjs.md +0 -0
  199. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/tutorials/jupyterhub_jupyverse_deployment.md +0 -0
  200. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/tutorials/standalone_jupyverse_deployment.md +0 -0
  201. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/usage/microservices.md +0 -0
  202. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/usage/multi_user.md +0 -0
  203. {jupyverse-0.6.3 → jupyverse-0.7.0}/docs/usage/single_user.md +0 -0
  204. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse/py.typed +0 -0
  205. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/COPYING.md +0 -0
  206. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/README.md +0 -0
  207. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/auth/models.py +0 -0
  208. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/contents/models.py +0 -0
  209. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/exceptions.py +0 -0
  210. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/frontend/__init__.py +0 -0
  211. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/jupyterlab/__init__.py +0 -0
  212. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/kernels/__init__.py +0 -0
  213. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/kernels/models.py +0 -0
  214. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/lab/__init__.py +0 -0
  215. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/login/__init__.py +0 -0
  216. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/nbconvert/__init__.py +0 -0
  217. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/notebook/__init__.py +0 -0
  218. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/py.typed +0 -0
  219. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/resource_usage/__init__.py +0 -0
  220. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/terminals/models.py +0 -0
  221. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/yjs/__init__.py +0 -0
  222. {jupyverse-0.6.3 → jupyverse-0.7.0}/jupyverse_api/jupyverse_api/yjs/models.py +0 -0
  223. {jupyverse-0.6.3 → jupyverse-0.7.0}/notebooks/admin_users.ipynb +0 -0
  224. {jupyverse-0.6.3 → jupyverse-0.7.0}/notebooks/admin_users.py +0 -0
  225. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/COPYING.md +0 -0
  226. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/README.md +0 -0
  227. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/config.py +0 -0
  228. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/models.py +0 -0
  229. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth/fps_auth/py.typed +0 -0
  230. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/COPYING.md +0 -0
  231. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/README.md +0 -0
  232. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/fps_auth_fief/backend.py +0 -0
  233. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_fief/fps_auth_fief/config.py +0 -0
  234. {jupyverse-0.6.3/plugins/contents/fps_contents → jupyverse-0.7.0/plugins/auth_fief/fps_auth_fief}/py.typed +0 -0
  235. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/COPYING.md +0 -0
  236. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/README.md +0 -0
  237. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/config.py +0 -0
  238. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/db.py +0 -0
  239. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/launch.py +0 -0
  240. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/auth_jupyterhub/fps_auth_jupyterhub/models.py +0 -0
  241. {jupyverse-0.6.3/plugins/frontend/fps_frontend → jupyverse-0.7.0/plugins/auth_jupyterhub/fps_auth_jupyterhub}/py.typed +0 -0
  242. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/contents/COPYING.md +0 -0
  243. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/contents/README.md +0 -0
  244. {jupyverse-0.6.3/plugins/jupyterlab/fps_jupyterlab → jupyverse-0.7.0/plugins/contents/fps_contents}/py.typed +0 -0
  245. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/frontend/COPYING.md +0 -0
  246. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/frontend/README.md +0 -0
  247. {jupyverse-0.6.3/plugins/noauth/fps_noauth → jupyverse-0.7.0/plugins/frontend/fps_frontend}/py.typed +0 -0
  248. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/jupyterlab/COPYING.md +0 -0
  249. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/jupyterlab/README.md +0 -0
  250. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/jupyterlab/fps_jupyterlab/index.py +0 -0
  251. {jupyverse-0.6.3/plugins/webdav/fps_webdav → jupyverse-0.7.0/plugins/jupyterlab/fps_jupyterlab}/py.typed +0 -0
  252. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/COPYING.md +0 -0
  253. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/README.md +0 -0
  254. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/__init__.py +0 -0
  255. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/kernelspec.py +0 -0
  256. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_driver/paths.py +0 -0
  257. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_server/__init__.py +0 -0
  258. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/kernels/fps_kernels/kernel_server/message.py +0 -0
  259. {jupyverse-0.6.3/plugins/yjs/fps_yjs → jupyverse-0.7.0/plugins/kernels/fps_kernels}/py.typed +0 -0
  260. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/lab/COPYING.md +0 -0
  261. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/lab/README.md +0 -0
  262. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/lab/fps_lab/static/favicon.ico +0 -0
  263. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/COPYING.md +0 -0
  264. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/README.md +0 -0
  265. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/routes.py +0 -0
  266. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-busy-1.ico +0 -0
  267. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-busy-2.ico +0 -0
  268. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-busy-3.ico +0 -0
  269. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-file.ico +0 -0
  270. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-notebook.ico +0 -0
  271. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon-terminal.ico +0 -0
  272. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/favicons/favicon.ico +0 -0
  273. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/index.html +0 -0
  274. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/logo/github.svg +0 -0
  275. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/logo/logo.png +0 -0
  276. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/login/fps_login/static/style/index.css +0 -0
  277. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/nbconvert/COPYING.md +0 -0
  278. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/nbconvert/README.md +0 -0
  279. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/noauth/COPYING.md +0 -0
  280. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/noauth/README.md +0 -0
  281. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/noauth/fps_noauth/backends.py +0 -0
  282. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/notebook/COPYING.md +0 -0
  283. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/notebook/README.md +0 -0
  284. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/resource_usage/COPYING.md +0 -0
  285. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/resource_usage/README.md +0 -0
  286. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/resource_usage/fps_resource_usage/routes.py +0 -0
  287. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/terminals/COPYING.md +0 -0
  288. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/terminals/README.md +0 -0
  289. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/webdav/COPYING.md +0 -0
  290. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/webdav/README.md +0 -0
  291. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/webdav/fps_webdav/config.py +0 -0
  292. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/COPYING.md +0 -0
  293. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/README.md +0 -0
  294. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/__init__.py +0 -0
  295. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/utils.py +0 -0
  296. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/yfile.py +0 -0
  297. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ydocs/yunicode.py +0 -0
  298. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/asgi_server.py +0 -0
  299. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywebsocket/websocket.py +0 -0
  300. {jupyverse-0.6.3 → jupyverse-0.7.0}/plugins/yjs/fps_yjs/ywidgets/__init__.py +0 -0
  301. {jupyverse-0.6.3 → jupyverse-0.7.0}/pytest.ini +0 -0
  302. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/data/notebook0.ipynb +0 -0
  303. {jupyverse-0.6.3 → jupyverse-0.7.0}/tests/data/notebook1.ipynb +0 -0
@@ -7,7 +7,6 @@
7
7
  ./plugins/nbconvert
8
8
  ./plugins/terminals
9
9
  ./plugins/yjs
10
- fps[unicorn] >=0.0.10
10
+ fps >=0.1.1
11
11
  mypy
12
12
  pytest
13
- pytest-asyncio
@@ -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.12'
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.8', '3.9', '3.10', '3.11', '3.12' ]
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@v3
50
+ uses: actions/checkout@v4
51
51
 
52
- - uses: actions/setup-python@v4
52
+ - uses: actions/setup-python@v5
53
53
  with:
54
54
  python-version: ${{ matrix.python-version }}
55
55
  cache: 'pip'
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v4.6.0
3
+ rev: v5.0.0
4
4
  hooks:
5
5
  - id: end-of-file-fixer
6
6
  - id: check-case-conflict
@@ -16,7 +16,7 @@ repos:
16
16
  - id: trailing-whitespace
17
17
 
18
18
  - repo: https://github.com/astral-sh/ruff-pre-commit
19
- rev: v0.6.8
19
+ rev: v0.7.1
20
20
  hooks:
21
21
  - id: ruff
22
22
  args: ["--fix"]
@@ -2,6 +2,37 @@
2
2
 
3
3
  <!-- <START NEW CHANGELOG ENTRY> -->
4
4
 
5
+ ## 0.7.0
6
+
7
+ ([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.4...6fe98eab9ef0cef9d77a49bed92829ae3fb3538c))
8
+
9
+ ### Merged PRs
10
+
11
+ - Switch to FPS [#453](https://github.com/jupyter-server/jupyverse/pull/453) ([@davidbrochart](https://github.com/davidbrochart))
12
+ - Fixing typo in the documentation [#452](https://github.com/jupyter-server/jupyverse/pull/452) ([@ThePavolC](https://github.com/ThePavolC))
13
+
14
+ ### Contributors to this release
15
+
16
+ ([GitHub contributors page for this release](https://github.com/jupyter-server/jupyverse/graphs/contributors?from=2024-10-15&to=2025-02-14&type=c))
17
+
18
+ [@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)
19
+
20
+ <!-- <END NEW CHANGELOG ENTRY> -->
21
+
22
+ ## 0.6.4
23
+
24
+ ([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.3...69394c087d0645c784ff14e3cb71557c7a0d5cfa))
25
+
26
+ ### Merged PRs
27
+
28
+ - Fix nbconvert file save mode [#446](https://github.com/jupyter-server/jupyverse/pull/446) ([@davidbrochart](https://github.com/davidbrochart))
29
+
30
+ ### Contributors to this release
31
+
32
+ ([GitHub contributors page for this release](https://github.com/jupyter-server/jupyverse/graphs/contributors?from=2024-10-02&to=2024-10-15&type=c))
33
+
34
+ [@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)
35
+
5
36
  ## 0.6.3
6
37
 
7
38
  ([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.2...aa6854a51665d95216340d7fda1ba111af6aef74))
@@ -16,8 +47,6 @@
16
47
 
17
48
  [@davidbrochart](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Adavidbrochart+updated%3A2024-09-13..2024-10-02&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyverse+involves%3Apre-commit-ci+updated%3A2024-09-13..2024-10-02&type=Issues)
18
49
 
19
- <!-- <END NEW CHANGELOG ENTRY> -->
20
-
21
50
  ## 0.6.2
22
51
 
23
52
  ([Full Changelog](https://github.com/jupyter-server/jupyverse/compare/v0.6.1...b7823731e061936842a3d2bcc6044f5134b50857))
@@ -1,13 +1,13 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: jupyverse
3
- Version: 0.6.3
3
+ Version: 0.7.0
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.8
10
+ Requires-Python: >=3.9
11
11
  Requires-Dist: fps-contents<1,>=0.1.2
12
12
  Requires-Dist: fps-frontend<1,>=0.1.2
13
13
  Requires-Dist: fps-kernels<1,>=0.1.2
@@ -38,14 +38,13 @@ 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
@@ -0,0 +1 @@
1
+ __version__ = "0.7.0"
@@ -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.6.3"
8
+ __version__ = "0.7.0"
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 = logging.getLogger("app")
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("%s added handler for path: %s", _type, path)
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("%s mounted path: %s", _type, path)
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 asyncio
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
- stop_watching_files: asyncio.Event
17
- stopped_watching_files: asyncio.Event
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
@@ -83,5 +83,5 @@ class TerminalServer(ABC):
83
83
  ...
84
84
 
85
85
  @abstractmethod
86
- async def exit(self):
86
+ def quit(self, websocket):
87
87
  ...
@@ -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.8"
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
- "asphalt >=4.11.0,<5",
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."asphalt.components"]
46
- app = "jupyverse_api.main:AppComponent"
47
- jupyverse = "jupyverse_api.main:JupyverseComponent"
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.components"]
50
- app = "jupyverse_api.main:AppComponent"
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"
@@ -0,0 +1,57 @@
1
+ import pytest
2
+ from anyio import create_task_group, sleep
3
+
4
+ from jupyverse_api import ResourceLock
5
+
6
+ pytestmark = pytest.mark.anyio
7
+
8
+
9
+ async def do_op(operation, resource_lock, operations):
10
+ op, path = operation
11
+ async with resource_lock(path):
12
+ operations.append(operation + ["start"])
13
+ await sleep(0.1)
14
+ operations.append(operation + ["done"])
15
+
16
+
17
+ async def test_resource_lock():
18
+ resource_lock = ResourceLock()
19
+
20
+ # test concurrent accesses to the same resource
21
+ idx = "idx"
22
+ operations = []
23
+ async with create_task_group() as tg:
24
+ tg.start_soon(do_op, [0, idx], resource_lock, operations)
25
+ await sleep(0.01)
26
+ tg.start_soon(do_op, [1, idx], resource_lock, operations)
27
+
28
+ assert operations == [
29
+ [0, idx, "start"],
30
+ [0, idx, "done"],
31
+ [1, idx, "start"],
32
+ [1, idx, "done"],
33
+ ]
34
+
35
+ # test concurrent accesses to different files
36
+ idx0 = "idx0"
37
+ idx1 = "idx1"
38
+ operations = []
39
+ async with create_task_group() as tg:
40
+ tg.start_soon(do_op, [0, idx0], resource_lock, operations)
41
+ await sleep(0.01)
42
+ tg.start_soon(do_op, [1, idx1], resource_lock, operations)
43
+ await sleep(0.01)
44
+ tg.start_soon(do_op, [2, idx0], resource_lock, operations)
45
+ await sleep(0.01)
46
+ tg.start_soon(do_op, [3, idx1], resource_lock, operations)
47
+
48
+ assert operations == [
49
+ [0, idx0, "start"],
50
+ [1, idx1, "start"],
51
+ [0, idx0, "done"],
52
+ [2, idx0, "start"],
53
+ [1, idx1, "done"],
54
+ [3, idx1, "start"],
55
+ [2, idx0, "done"],
56
+ [3, idx1, "done"],
57
+ ]
@@ -35,7 +35,7 @@ nav:
35
35
  - usage/single_user.md
36
36
  - usage/multi_user.md
37
37
  - usage/microservices.md
38
- - Turorials:
38
+ - Tutorials:
39
39
  - tutorials/standalone_jupyverse_deployment.md
40
40
  - tutorials/jupyterhub_jupyverse_deployment.md
41
41
  - Plugins:
@@ -0,0 +1 @@
1
+ __version__ = "0.7.0"
@@ -1,4 +1,3 @@
1
- import logging
2
1
  import uuid
3
2
  from dataclasses import dataclass
4
3
  from typing import Any, Dict, Generic, List, Optional, Tuple, cast
@@ -29,8 +28,6 @@ from .config import _AuthConfig
29
28
  from .db import User
30
29
  from .models import UserCreate, UserRead
31
30
 
32
- logger = logging.getLogger("auth")
33
-
34
31
 
35
32
  @dataclass
36
33
  class Res:
@@ -1,4 +1,3 @@
1
- import logging
2
1
  import secrets
3
2
  from dataclasses import dataclass
4
3
  from pathlib import Path
@@ -16,8 +15,6 @@ from sqlalchemy.orm import DeclarativeBase, Mapped, relationship
16
15
 
17
16
  from .config import _AuthConfig
18
17
 
19
- logger = logging.getLogger("auth")
20
-
21
18
 
22
19
  class Base(AsyncAttrs, DeclarativeBase):
23
20
  pass