solara-ui 1.45.0__py3-none-any.whl

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 (464) hide show
  1. prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
  2. prefix/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
  3. solara/__init__.py +124 -0
  4. solara/__main__.py +765 -0
  5. solara/_stores.py +297 -0
  6. solara/alias.py +6 -0
  7. solara/autorouting.py +555 -0
  8. solara/cache.py +305 -0
  9. solara/checks.html +71 -0
  10. solara/checks.py +227 -0
  11. solara/comm.py +28 -0
  12. solara/components/__init__.py +77 -0
  13. solara/components/alert.py +155 -0
  14. solara/components/applayout.py +397 -0
  15. solara/components/button.py +85 -0
  16. solara/components/card.py +87 -0
  17. solara/components/checkbox.py +50 -0
  18. solara/components/code_highlight_css.py +11 -0
  19. solara/components/code_highlight_css.vue +63 -0
  20. solara/components/columns.py +159 -0
  21. solara/components/component_vue.py +134 -0
  22. solara/components/cross_filter.py +335 -0
  23. solara/components/dataframe.py +546 -0
  24. solara/components/datatable.py +214 -0
  25. solara/components/datatable.vue +175 -0
  26. solara/components/details.py +56 -0
  27. solara/components/download.vue +35 -0
  28. solara/components/echarts.py +86 -0
  29. solara/components/echarts.vue +139 -0
  30. solara/components/figure_altair.py +39 -0
  31. solara/components/file_browser.py +181 -0
  32. solara/components/file_download.py +199 -0
  33. solara/components/file_drop.py +159 -0
  34. solara/components/file_drop.vue +83 -0
  35. solara/components/file_list_widget.vue +78 -0
  36. solara/components/head.py +27 -0
  37. solara/components/head_tag.py +49 -0
  38. solara/components/head_tag.vue +60 -0
  39. solara/components/image.py +173 -0
  40. solara/components/input.py +456 -0
  41. solara/components/input_text_area.py +86 -0
  42. solara/components/link.py +55 -0
  43. solara/components/markdown.py +441 -0
  44. solara/components/markdown_editor.py +33 -0
  45. solara/components/markdown_editor.vue +359 -0
  46. solara/components/matplotlib.py +74 -0
  47. solara/components/meta.py +47 -0
  48. solara/components/misc.py +333 -0
  49. solara/components/pivot_table.py +258 -0
  50. solara/components/pivot_table.vue +158 -0
  51. solara/components/progress.py +47 -0
  52. solara/components/select.py +182 -0
  53. solara/components/select.vue +27 -0
  54. solara/components/slider.py +442 -0
  55. solara/components/slider_date.vue +56 -0
  56. solara/components/spinner-solara.vue +105 -0
  57. solara/components/spinner.py +45 -0
  58. solara/components/sql_code.py +41 -0
  59. solara/components/sql_code.vue +125 -0
  60. solara/components/style.py +105 -0
  61. solara/components/switch.py +71 -0
  62. solara/components/tab_navigation.py +37 -0
  63. solara/components/title.py +90 -0
  64. solara/components/title.vue +38 -0
  65. solara/components/togglebuttons.py +200 -0
  66. solara/components/tooltip.py +61 -0
  67. solara/core.py +42 -0
  68. solara/datatypes.py +143 -0
  69. solara/express.py +241 -0
  70. solara/hooks/__init__.py +4 -0
  71. solara/hooks/dataframe.py +99 -0
  72. solara/hooks/misc.py +263 -0
  73. solara/hooks/use_reactive.py +151 -0
  74. solara/hooks/use_thread.py +129 -0
  75. solara/kitchensink.py +8 -0
  76. solara/lab/__init__.py +34 -0
  77. solara/lab/components/__init__.py +7 -0
  78. solara/lab/components/chat.py +215 -0
  79. solara/lab/components/confirmation_dialog.py +163 -0
  80. solara/lab/components/cross_filter.py +7 -0
  81. solara/lab/components/input_date.py +339 -0
  82. solara/lab/components/input_time.py +133 -0
  83. solara/lab/components/menu.py +181 -0
  84. solara/lab/components/menu.vue +38 -0
  85. solara/lab/components/tabs.py +274 -0
  86. solara/lab/components/theming.py +98 -0
  87. solara/lab/components/theming.vue +72 -0
  88. solara/lab/hooks/__init__.py +0 -0
  89. solara/lab/hooks/dataframe.py +2 -0
  90. solara/lab/toestand.py +3 -0
  91. solara/lab/utils/__init__.py +2 -0
  92. solara/lab/utils/cookies.py +5 -0
  93. solara/lab/utils/dataframe.py +165 -0
  94. solara/lab/utils/headers.py +5 -0
  95. solara/layout.py +44 -0
  96. solara/lifecycle.py +46 -0
  97. solara/minisettings.py +141 -0
  98. solara/py.typed +0 -0
  99. solara/reactive.py +99 -0
  100. solara/routing.py +268 -0
  101. solara/scope/__init__.py +88 -0
  102. solara/scope/types.py +55 -0
  103. solara/server/__init__.py +0 -0
  104. solara/server/app.py +527 -0
  105. solara/server/assets/custom.css +1 -0
  106. solara/server/assets/custom.js +1 -0
  107. solara/server/assets/favicon.png +0 -0
  108. solara/server/assets/favicon.svg +5 -0
  109. solara/server/assets/style.css +1681 -0
  110. solara/server/assets/theme-dark.css +437 -0
  111. solara/server/assets/theme-light.css +420 -0
  112. solara/server/assets/theme.js +3 -0
  113. solara/server/cdn_helper.py +91 -0
  114. solara/server/esm.py +71 -0
  115. solara/server/fastapi.py +5 -0
  116. solara/server/flask.py +297 -0
  117. solara/server/jupyter/__init__.py +2 -0
  118. solara/server/jupyter/cdn_handler.py +28 -0
  119. solara/server/jupyter/server_extension.py +40 -0
  120. solara/server/jupyter/solara.py +91 -0
  121. solara/server/jupytertools.py +46 -0
  122. solara/server/kernel.py +388 -0
  123. solara/server/kernel_context.py +467 -0
  124. solara/server/patch.py +564 -0
  125. solara/server/pyinstaller/__init__.py +9 -0
  126. solara/server/pyinstaller/hook-ipyreact.py +5 -0
  127. solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
  128. solara/server/pyinstaller/hook-solara.py +9 -0
  129. solara/server/qt.py +113 -0
  130. solara/server/reload.py +251 -0
  131. solara/server/server.py +484 -0
  132. solara/server/settings.py +249 -0
  133. solara/server/shell.py +269 -0
  134. solara/server/starlette.py +770 -0
  135. solara/server/static/ansi.js +270 -0
  136. solara/server/static/highlight-dark.css +82 -0
  137. solara/server/static/highlight.css +43 -0
  138. solara/server/static/main-vuetify.js +272 -0
  139. solara/server/static/main.js +163 -0
  140. solara/server/static/solara_bootstrap.py +129 -0
  141. solara/server/static/sun.svg +23 -0
  142. solara/server/static/webworker.js +42 -0
  143. solara/server/telemetry.py +212 -0
  144. solara/server/templates/index.html.j2 +1 -0
  145. solara/server/templates/loader-plain.css +11 -0
  146. solara/server/templates/loader-plain.html +20 -0
  147. solara/server/templates/loader-solara.css +111 -0
  148. solara/server/templates/loader-solara.html +40 -0
  149. solara/server/templates/plain.html +82 -0
  150. solara/server/templates/solara.html.j2 +486 -0
  151. solara/server/threaded.py +84 -0
  152. solara/server/utils.py +44 -0
  153. solara/server/websocket.py +45 -0
  154. solara/settings.py +86 -0
  155. solara/tasks.py +893 -0
  156. solara/template/button.py +16 -0
  157. solara/template/markdown.py +42 -0
  158. solara/template/portal/.flake8 +6 -0
  159. solara/template/portal/.pre-commit-config.yaml +28 -0
  160. solara/template/portal/LICENSE +21 -0
  161. solara/template/portal/Procfile +7 -0
  162. solara/template/portal/mypy.ini +3 -0
  163. solara/template/portal/pyproject.toml +26 -0
  164. solara/template/portal/solara_portal/__init__.py +4 -0
  165. solara/template/portal/solara_portal/components/__init__.py +2 -0
  166. solara/template/portal/solara_portal/components/article.py +28 -0
  167. solara/template/portal/solara_portal/components/data.py +28 -0
  168. solara/template/portal/solara_portal/components/header.py +6 -0
  169. solara/template/portal/solara_portal/components/layout.py +6 -0
  170. solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +85 -0
  171. solara/template/portal/solara_portal/content/articles/substiterat-vati.md +70 -0
  172. solara/template/portal/solara_portal/data.py +60 -0
  173. solara/template/portal/solara_portal/pages/__init__.py +67 -0
  174. solara/template/portal/solara_portal/pages/article/__init__.py +26 -0
  175. solara/template/portal/solara_portal/pages/tabular.py +29 -0
  176. solara/template/portal/solara_portal/pages/viz/__init__.py +70 -0
  177. solara/template/portal/solara_portal/pages/viz/overview.py +14 -0
  178. solara/test/__init__.py +0 -0
  179. solara/test/pytest_plugin.py +783 -0
  180. solara/toestand.py +998 -0
  181. solara/util.py +348 -0
  182. solara/validate_hooks.py +258 -0
  183. solara/website/__init__.py +0 -0
  184. solara/website/assets/custom.css +444 -0
  185. solara/website/assets/images/logo-small.png +0 -0
  186. solara/website/assets/images/logo.svg +17 -0
  187. solara/website/assets/images/logo_white.svg +50 -0
  188. solara/website/assets/theme.js +8 -0
  189. solara/website/components/__init__.py +5 -0
  190. solara/website/components/algolia.py +6 -0
  191. solara/website/components/algolia.vue +24 -0
  192. solara/website/components/algolia_api.vue +202 -0
  193. solara/website/components/breadcrumbs.py +28 -0
  194. solara/website/components/contact.py +144 -0
  195. solara/website/components/docs.py +143 -0
  196. solara/website/components/header.py +75 -0
  197. solara/website/components/mailchimp.py +12 -0
  198. solara/website/components/mailchimp.vue +47 -0
  199. solara/website/components/markdown.py +99 -0
  200. solara/website/components/markdown_nav.vue +34 -0
  201. solara/website/components/notebook.py +171 -0
  202. solara/website/components/sidebar.py +105 -0
  203. solara/website/pages/__init__.py +370 -0
  204. solara/website/pages/about/__init__.py +9 -0
  205. solara/website/pages/about/about.md +3 -0
  206. solara/website/pages/apps/__init__.py +16 -0
  207. solara/website/pages/apps/authorization/__init__.py +119 -0
  208. solara/website/pages/apps/authorization/admin.py +12 -0
  209. solara/website/pages/apps/authorization/users.py +12 -0
  210. solara/website/pages/apps/jupyter-dashboard-1.py +116 -0
  211. solara/website/pages/apps/layout-demo.py +40 -0
  212. solara/website/pages/apps/multipage/__init__.py +38 -0
  213. solara/website/pages/apps/multipage/page1.py +26 -0
  214. solara/website/pages/apps/multipage/page2.py +34 -0
  215. solara/website/pages/apps/scatter.py +136 -0
  216. solara/website/pages/apps/scrolling.py +63 -0
  217. solara/website/pages/apps/tutorial-streamlit.py +18 -0
  218. solara/website/pages/careers/__init__.py +27 -0
  219. solara/website/pages/changelog/__init__.py +10 -0
  220. solara/website/pages/changelog/changelog.md +372 -0
  221. solara/website/pages/contact/__init__.py +34 -0
  222. solara/website/pages/doc_use_download.py +85 -0
  223. solara/website/pages/documentation/__init__.py +90 -0
  224. solara/website/pages/documentation/advanced/__init__.py +9 -0
  225. solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
  226. solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +6 -0
  227. solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +196 -0
  228. solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +125 -0
  229. solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +417 -0
  230. solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +69 -0
  231. solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +50 -0
  232. solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +124 -0
  233. solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +3 -0
  234. solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +31 -0
  235. solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +72 -0
  236. solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +59 -0
  237. solara/website/pages/documentation/advanced/content/15-reference/70-search.md +34 -0
  238. solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +34 -0
  239. solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +7 -0
  240. solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +148 -0
  241. solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +10 -0
  242. solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +35 -0
  243. solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +42 -0
  244. solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +28 -0
  245. solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +108 -0
  246. solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +23 -0
  247. solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +192 -0
  248. solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +166 -0
  249. solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +18 -0
  250. solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +256 -0
  251. solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +108 -0
  252. solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +12 -0
  253. solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +7 -0
  254. solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +187 -0
  255. solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
  256. solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +45 -0
  257. solara/website/pages/documentation/advanced/content/40-development/10-setup.md +76 -0
  258. solara/website/pages/documentation/api/__init__.py +19 -0
  259. solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
  260. solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +22 -0
  261. solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +20 -0
  262. solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +20 -0
  263. solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +20 -0
  264. solara/website/pages/documentation/api/hooks/__init__.py +9 -0
  265. solara/website/pages/documentation/api/hooks/use_cross_filter.py +23 -0
  266. solara/website/pages/documentation/api/hooks/use_dark_effective.py +12 -0
  267. solara/website/pages/documentation/api/hooks/use_effect.md +43 -0
  268. solara/website/pages/documentation/api/hooks/use_effect.py +9 -0
  269. solara/website/pages/documentation/api/hooks/use_exception.py +31 -0
  270. solara/website/pages/documentation/api/hooks/use_memo.md +16 -0
  271. solara/website/pages/documentation/api/hooks/use_memo.py +9 -0
  272. solara/website/pages/documentation/api/hooks/use_previous.py +30 -0
  273. solara/website/pages/documentation/api/hooks/use_reactive.py +16 -0
  274. solara/website/pages/documentation/api/hooks/use_state.py +10 -0
  275. solara/website/pages/documentation/api/hooks/use_state_or_update.py +66 -0
  276. solara/website/pages/documentation/api/hooks/use_thread.md +64 -0
  277. solara/website/pages/documentation/api/hooks/use_thread.py +42 -0
  278. solara/website/pages/documentation/api/hooks/use_trait_observe.py +12 -0
  279. solara/website/pages/documentation/api/routing/__init__.py +9 -0
  280. solara/website/pages/documentation/api/routing/generate_routes.py +10 -0
  281. solara/website/pages/documentation/api/routing/generate_routes_directory.py +10 -0
  282. solara/website/pages/documentation/api/routing/resolve_path.py +35 -0
  283. solara/website/pages/documentation/api/routing/route.py +29 -0
  284. solara/website/pages/documentation/api/routing/use_route.py +76 -0
  285. solara/website/pages/documentation/api/routing/use_router.py +16 -0
  286. solara/website/pages/documentation/api/utilities/__init__.py +9 -0
  287. solara/website/pages/documentation/api/utilities/component_vue.py +10 -0
  288. solara/website/pages/documentation/api/utilities/computed.py +16 -0
  289. solara/website/pages/documentation/api/utilities/display.py +16 -0
  290. solara/website/pages/documentation/api/utilities/get_kernel_id.py +16 -0
  291. solara/website/pages/documentation/api/utilities/get_session_id.py +16 -0
  292. solara/website/pages/documentation/api/utilities/memoize.py +35 -0
  293. solara/website/pages/documentation/api/utilities/on_kernel_start.py +44 -0
  294. solara/website/pages/documentation/api/utilities/reactive.py +16 -0
  295. solara/website/pages/documentation/api/utilities/widget.py +104 -0
  296. solara/website/pages/documentation/components/__init__.py +12 -0
  297. solara/website/pages/documentation/components/advanced/__init__.py +9 -0
  298. solara/website/pages/documentation/components/advanced/link.py +25 -0
  299. solara/website/pages/documentation/components/advanced/meta.py +17 -0
  300. solara/website/pages/documentation/components/advanced/style.py +43 -0
  301. solara/website/pages/documentation/components/common.py +9 -0
  302. solara/website/pages/documentation/components/data/__init__.py +9 -0
  303. solara/website/pages/documentation/components/data/dataframe.py +44 -0
  304. solara/website/pages/documentation/components/data/pivot_table.py +81 -0
  305. solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
  306. solara/website/pages/documentation/components/enterprise/avatar.py +24 -0
  307. solara/website/pages/documentation/components/enterprise/avatar_menu.py +25 -0
  308. solara/website/pages/documentation/components/input/__init__.py +9 -0
  309. solara/website/pages/documentation/components/input/button.py +23 -0
  310. solara/website/pages/documentation/components/input/checkbox.py +10 -0
  311. solara/website/pages/documentation/components/input/file_browser.py +30 -0
  312. solara/website/pages/documentation/components/input/file_drop.py +76 -0
  313. solara/website/pages/documentation/components/input/input.py +43 -0
  314. solara/website/pages/documentation/components/input/select.py +22 -0
  315. solara/website/pages/documentation/components/input/slider.py +29 -0
  316. solara/website/pages/documentation/components/input/switch.py +10 -0
  317. solara/website/pages/documentation/components/input/togglebuttons.py +21 -0
  318. solara/website/pages/documentation/components/lab/__init__.py +9 -0
  319. solara/website/pages/documentation/components/lab/chat.py +109 -0
  320. solara/website/pages/documentation/components/lab/confirmation_dialog.py +55 -0
  321. solara/website/pages/documentation/components/lab/cookies_headers.py +48 -0
  322. solara/website/pages/documentation/components/lab/input_date.py +20 -0
  323. solara/website/pages/documentation/components/lab/input_time.py +15 -0
  324. solara/website/pages/documentation/components/lab/menu.py +22 -0
  325. solara/website/pages/documentation/components/lab/tab.py +25 -0
  326. solara/website/pages/documentation/components/lab/tabs.py +45 -0
  327. solara/website/pages/documentation/components/lab/task.py +11 -0
  328. solara/website/pages/documentation/components/lab/theming.py +74 -0
  329. solara/website/pages/documentation/components/lab/use_task.py +11 -0
  330. solara/website/pages/documentation/components/layout/__init__.py +9 -0
  331. solara/website/pages/documentation/components/layout/app_bar.py +16 -0
  332. solara/website/pages/documentation/components/layout/app_bar_title.py +16 -0
  333. solara/website/pages/documentation/components/layout/app_layout.py +24 -0
  334. solara/website/pages/documentation/components/layout/card.py +15 -0
  335. solara/website/pages/documentation/components/layout/card_actions.py +16 -0
  336. solara/website/pages/documentation/components/layout/column.py +30 -0
  337. solara/website/pages/documentation/components/layout/columns.py +27 -0
  338. solara/website/pages/documentation/components/layout/columns_responsive.py +66 -0
  339. solara/website/pages/documentation/components/layout/details.py +13 -0
  340. solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
  341. solara/website/pages/documentation/components/layout/gridfixed.py +19 -0
  342. solara/website/pages/documentation/components/layout/hbox.py +18 -0
  343. solara/website/pages/documentation/components/layout/row.py +30 -0
  344. solara/website/pages/documentation/components/layout/sidebar.py +24 -0
  345. solara/website/pages/documentation/components/layout/vbox.py +19 -0
  346. solara/website/pages/documentation/components/output/__init__.py +9 -0
  347. solara/website/pages/documentation/components/output/file_download.py +11 -0
  348. solara/website/pages/documentation/components/output/html.py +19 -0
  349. solara/website/pages/documentation/components/output/image.py +11 -0
  350. solara/website/pages/documentation/components/output/markdown.py +57 -0
  351. solara/website/pages/documentation/components/output/markdown_editor.py +51 -0
  352. solara/website/pages/documentation/components/output/sql_code.py +83 -0
  353. solara/website/pages/documentation/components/output/tooltip.py +11 -0
  354. solara/website/pages/documentation/components/page/__init__.py +9 -0
  355. solara/website/pages/documentation/components/page/head.py +15 -0
  356. solara/website/pages/documentation/components/page/title.py +25 -0
  357. solara/website/pages/documentation/components/status/__init__.py +9 -0
  358. solara/website/pages/documentation/components/status/error.py +39 -0
  359. solara/website/pages/documentation/components/status/info.py +39 -0
  360. solara/website/pages/documentation/components/status/progress.py +10 -0
  361. solara/website/pages/documentation/components/status/spinner.py +11 -0
  362. solara/website/pages/documentation/components/status/success.py +40 -0
  363. solara/website/pages/documentation/components/status/warning.py +47 -0
  364. solara/website/pages/documentation/components/viz/__init__.py +9 -0
  365. solara/website/pages/documentation/components/viz/altair.py +42 -0
  366. solara/website/pages/documentation/components/viz/echarts.py +77 -0
  367. solara/website/pages/documentation/components/viz/matplotlib.py +30 -0
  368. solara/website/pages/documentation/components/viz/plotly.py +63 -0
  369. solara/website/pages/documentation/components/viz/plotly_express.py +41 -0
  370. solara/website/pages/documentation/examples/__init__.py +54 -0
  371. solara/website/pages/documentation/examples/ai/__init__.py +11 -0
  372. solara/website/pages/documentation/examples/ai/chatbot.py +113 -0
  373. solara/website/pages/documentation/examples/ai/tokenizer.py +107 -0
  374. solara/website/pages/documentation/examples/basics/__init__.py +10 -0
  375. solara/website/pages/documentation/examples/basics/sine.py +28 -0
  376. solara/website/pages/documentation/examples/fullscreen/__init__.py +10 -0
  377. solara/website/pages/documentation/examples/fullscreen/authorization.py +3 -0
  378. solara/website/pages/documentation/examples/fullscreen/layout_demo.py +3 -0
  379. solara/website/pages/documentation/examples/fullscreen/multipage.py +3 -0
  380. solara/website/pages/documentation/examples/fullscreen/scatter.py +3 -0
  381. solara/website/pages/documentation/examples/fullscreen/scrolling.py +3 -0
  382. solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +3 -0
  383. solara/website/pages/documentation/examples/general/__init__.py +10 -0
  384. solara/website/pages/documentation/examples/general/custom_storage.py +70 -0
  385. solara/website/pages/documentation/examples/general/deploy_model.py +115 -0
  386. solara/website/pages/documentation/examples/general/live_update.py +32 -0
  387. solara/website/pages/documentation/examples/general/login_oauth.py +81 -0
  388. solara/website/pages/documentation/examples/general/mycard.vue +58 -0
  389. solara/website/pages/documentation/examples/general/pokemon_search.py +51 -0
  390. solara/website/pages/documentation/examples/general/vue_component.py +50 -0
  391. solara/website/pages/documentation/examples/ipycanvas.py +49 -0
  392. solara/website/pages/documentation/examples/libraries/__init__.py +10 -0
  393. solara/website/pages/documentation/examples/libraries/altair.py +65 -0
  394. solara/website/pages/documentation/examples/libraries/bqplot.py +39 -0
  395. solara/website/pages/documentation/examples/libraries/ipyleaflet.py +33 -0
  396. solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +66 -0
  397. solara/website/pages/documentation/examples/utilities/__init__.py +10 -0
  398. solara/website/pages/documentation/examples/utilities/calculator.py +157 -0
  399. solara/website/pages/documentation/examples/utilities/countdown_timer.py +62 -0
  400. solara/website/pages/documentation/examples/utilities/todo.py +196 -0
  401. solara/website/pages/documentation/examples/visualization/__init__.py +6 -0
  402. solara/website/pages/documentation/examples/visualization/annotator.py +67 -0
  403. solara/website/pages/documentation/examples/visualization/linked_views.py +81 -0
  404. solara/website/pages/documentation/examples/visualization/plotly.py +44 -0
  405. solara/website/pages/documentation/faq/__init__.py +12 -0
  406. solara/website/pages/documentation/faq/content/99-faq.md +112 -0
  407. solara/website/pages/documentation/getting_started/__init__.py +9 -0
  408. solara/website/pages/documentation/getting_started/content/00-quickstart.md +107 -0
  409. solara/website/pages/documentation/getting_started/content/01-introduction.md +125 -0
  410. solara/website/pages/documentation/getting_started/content/02-installing.md +134 -0
  411. solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +14 -0
  412. solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +13 -0
  413. solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +89 -0
  414. solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +124 -0
  415. solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +146 -0
  416. solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +144 -0
  417. solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +65 -0
  418. solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
  419. solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +445 -0
  420. solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +1021 -0
  421. solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +11 -0
  422. solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +228 -0
  423. solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +278 -0
  424. solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +7 -0
  425. solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +305 -0
  426. solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +80 -0
  427. solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +7 -0
  428. solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +26 -0
  429. solara/website/pages/docutils.py +38 -0
  430. solara/website/pages/home.vue +1199 -0
  431. solara/website/pages/our_team/__init__.py +83 -0
  432. solara/website/pages/pricing/__init__.py +31 -0
  433. solara/website/pages/roadmap/__init__.py +11 -0
  434. solara/website/pages/roadmap/roadmap.md +47 -0
  435. solara/website/pages/scale_ipywidgets.py +45 -0
  436. solara/website/pages/showcase/__init__.py +105 -0
  437. solara/website/pages/showcase/domino_code_assist.py +60 -0
  438. solara/website/pages/showcase/planeto_tessa.py +19 -0
  439. solara/website/pages/showcase/solara_dev.py +54 -0
  440. solara/website/pages/showcase/solarathon_2023_team_2.py +22 -0
  441. solara/website/pages/showcase/solarathon_2023_team_4.py +22 -0
  442. solara/website/pages/showcase/solarathon_2023_team_5.py +23 -0
  443. solara/website/pages/showcase/solarathon_2023_team_6.py +34 -0
  444. solara/website/pages/showcase/wanderlust.py +27 -0
  445. solara/website/public/beach.jpeg +0 -0
  446. solara/website/public/logo.svg +6 -0
  447. solara/website/public/social/discord.svg +1 -0
  448. solara/website/public/social/github.svg +1 -0
  449. solara/website/public/social/twitter.svg +3 -0
  450. solara/website/public/success.html +25 -0
  451. solara/website/templates/index.html.j2 +117 -0
  452. solara/website/utils.py +51 -0
  453. solara/widgets/__init__.py +1 -0
  454. solara/widgets/vue/gridlayout.vue +107 -0
  455. solara/widgets/vue/html.vue +4 -0
  456. solara/widgets/vue/navigator.vue +134 -0
  457. solara/widgets/vue/vegalite.vue +130 -0
  458. solara/widgets/widgets.py +74 -0
  459. solara_ui-1.45.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
  460. solara_ui-1.45.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
  461. solara_ui-1.45.0.dist-info/METADATA +162 -0
  462. solara_ui-1.45.0.dist-info/RECORD +464 -0
  463. solara_ui-1.45.0.dist-info/WHEEL +4 -0
  464. solara_ui-1.45.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,484 @@
1
+ import contextlib
2
+ import hashlib
3
+ import json
4
+ import logging
5
+ import os
6
+ import sys
7
+ import time
8
+ from pathlib import Path
9
+ from typing import Dict, List, Optional, Tuple, TypeVar, Union
10
+
11
+ import ipykernel
12
+ import ipyvue
13
+ import ipywidgets
14
+ import jinja2
15
+ import requests
16
+ import solara
17
+ import solara.routing
18
+ import solara.settings
19
+ import solara.server.settings
20
+ from solara.lab import cookies as solara_cookies
21
+ from solara.lab import headers as solara_headers
22
+
23
+ from . import app, jupytertools, patch, settings, websocket
24
+ from .kernel import Kernel, deserialize_binary_message
25
+ from .kernel_context import initialize_virtual_kernel
26
+
27
+ COOKIE_KEY_SESSION_ID = "solara-session-id"
28
+
29
+ T = TypeVar("T")
30
+
31
+
32
+ directory = Path(__file__).parent
33
+ template_name = "index.html.j2"
34
+ ipykernel_major = int(ipykernel.__version__.split(".")[0])
35
+ ipywidgets_major = int(ipywidgets.__version__.split(".")[0])
36
+ cache_memory = solara.cache.Memory(max_items=128)
37
+ vue3 = ipyvue.__version__.startswith("3")
38
+ _redirects: Dict[str, str] = {}
39
+
40
+ # first look at the project directory, then the builtin solara directory
41
+
42
+
43
+ @solara.memoize(storage=cache_memory)
44
+ def get_jinja_env(app_name: str) -> jinja2.Environment:
45
+ jinja_loader = jinja2.FileSystemLoader(
46
+ [
47
+ app.apps["__default__"].directory.parent / "templates",
48
+ str(directory / "templates"),
49
+ ]
50
+ )
51
+ jinja_env = jinja2.Environment(loader=jinja_loader, autoescape=True)
52
+ return jinja_env
53
+
54
+
55
+ logger = logging.getLogger("solara.server.server")
56
+ nbextensions_ignorelist = [
57
+ "jupytext/index",
58
+ "nbextensions_configurator/config_menu/main",
59
+ "jupytext/index",
60
+ "nbdime/index",
61
+ "voila/extension",
62
+ "contrib_nbextensions_help_item/main",
63
+ "execute_time/ExecuteTime",
64
+ "dominocode/extension",
65
+ "low-code-assistant/extension",
66
+ "domino-code-assist/extension",
67
+ "jupyter-js/extension",
68
+ "jupyter-js-widgets/extension",
69
+ "jupyter_dash/main",
70
+ "dash/main",
71
+ *solara.server.settings.server.ignore_nbextensions,
72
+ ]
73
+
74
+
75
+ def readyz():
76
+ return {"status": "ok"}, 200
77
+
78
+
79
+ def wait_ready(url, timeout=10) -> None:
80
+ """Wait for a solara server at root url to be ready, or throw a TimeoutError
81
+
82
+ This uses the /readyz endpoint to check if the server is ready.
83
+
84
+ >>> solara.server.server.wait_ready("http://localhost:8888")
85
+ ...
86
+
87
+ """
88
+ t0 = time.time()
89
+ while True:
90
+ try:
91
+ r = requests.get(url + "/readyz")
92
+ if r.status_code == 200:
93
+ return
94
+ except Exception:
95
+ pass
96
+ time.sleep(0.1)
97
+ if time.time() - t0 > timeout:
98
+ raise TimeoutError(f"Timeout waiting for {url}")
99
+
100
+
101
+ def is_ready(url) -> bool:
102
+ """Returns whether a solara server at root url is ready.
103
+
104
+ This uses the /readyz endpoint to check if the server is ready.
105
+
106
+ >>> solara.server.server.is_ready("http://localhost:8888")
107
+ True
108
+
109
+ """
110
+ try:
111
+ r = requests.get(url + "/readyz")
112
+ if r.status_code == 200:
113
+ return True
114
+ except Exception:
115
+ pass
116
+ return False
117
+
118
+
119
+ async def app_loop(
120
+ ws: websocket.WebsocketWrapper,
121
+ cookies: Dict[str, str],
122
+ headers,
123
+ session_id: str,
124
+ kernel_id: str,
125
+ page_id: str,
126
+ user: dict = None,
127
+ ):
128
+ context = initialize_virtual_kernel(session_id, kernel_id, ws)
129
+ if context is None:
130
+ logging.warning("invalid kernel id: %r", kernel_id)
131
+ # to avoid very fast reconnects (we are in a thread anyway)
132
+ time.sleep(0.5)
133
+ return
134
+
135
+ if settings.main.tracer:
136
+ import viztracer
137
+
138
+ output_file = f"viztracer-{page_id}.html"
139
+ run_context = viztracer.VizTracer(output_file=output_file, max_stack_depth=10)
140
+ logger.warning(f"Running with tracer: {output_file}")
141
+ else:
142
+ run_context = solara.util.nullcontext()
143
+
144
+ kernel = context.kernel
145
+ try:
146
+ context.page_connect(page_id)
147
+ with run_context, context:
148
+ if user:
149
+ from solara_enterprise.auth import user as solara_user
150
+
151
+ solara_user.set(user)
152
+
153
+ solara_cookies.set(cookies) # type: ignore
154
+ solara_headers.set(headers) # type: ignore
155
+
156
+ while True:
157
+ if settings.main.timing:
158
+ widgets_ids = set(patch.widgets)
159
+ try:
160
+ message = await ws.receive()
161
+ except websocket.WebSocketDisconnect:
162
+ try:
163
+ if context.kernel is not None and context.kernel.session is not None:
164
+ context.kernel.session.websockets.remove(ws)
165
+ except KeyError:
166
+ pass
167
+ logger.debug("Disconnected")
168
+ break
169
+ t0 = time.time()
170
+ if isinstance(message, str):
171
+ msg = json.loads(message)
172
+ else:
173
+ msg = deserialize_binary_message(message)
174
+ t1 = time.time()
175
+ # we don't want to have the kernel closed while we are processing a message
176
+ # therefore we use this mutex that is also used in the context.close method
177
+ with context.lock:
178
+ if context.closed_event.is_set():
179
+ return
180
+ if not process_kernel_messages(kernel, msg):
181
+ # if we shut down the kernel, we do not keep the page session alive
182
+ context.close()
183
+ return
184
+ t2 = time.time()
185
+ if settings.main.timing:
186
+ widgets_ids_after = set(patch.widgets)
187
+ created_widgets_count = len(widgets_ids_after - widgets_ids)
188
+ close_widgets_count = len(widgets_ids - widgets_ids_after)
189
+ print( # noqa: T201
190
+ f"timing: total={t2 - t0:.3f}s, deserialize={t1 - t0:.3f}s, kernel={t2 - t1:.3f}s"
191
+ f" widget: created: {created_widgets_count} closed: {close_widgets_count}"
192
+ )
193
+ finally:
194
+ context.page_disconnect(page_id)
195
+
196
+
197
+ def process_kernel_messages(kernel: Kernel, msg: Dict) -> bool:
198
+ session = kernel.session
199
+ assert session is not None
200
+ comm_manager = kernel.comm_manager
201
+
202
+ def send_status(status, parent):
203
+ session.send(
204
+ kernel.iopub_socket,
205
+ "status",
206
+ {"execution_state": status},
207
+ parent=parent,
208
+ ident=None,
209
+ )
210
+
211
+ @contextlib.contextmanager
212
+ def busy_idle(parent):
213
+ send_status("busy", parent=parent)
214
+ try:
215
+ yield
216
+ finally:
217
+ send_status("idle", parent=parent)
218
+
219
+ msg_type = msg["header"]["msg_type"]
220
+
221
+ if ipykernel_major < 6:
222
+ # the channel argument was added in 6.0
223
+ kernel.set_parent(None, msg)
224
+ else:
225
+ kernel.set_parent(None, msg, msg["channel"])
226
+ if msg_type == "kernel_info_request":
227
+ content = {
228
+ "status": "ok",
229
+ "protocol_version": "5.3",
230
+ "implementation": Kernel.implementation,
231
+ "implementation_version": Kernel.implementation_version,
232
+ "language_info": {},
233
+ "banner": Kernel.banner,
234
+ "help_links": [],
235
+ }
236
+ with busy_idle(msg["header"]):
237
+ msg = kernel.session.send(kernel.shell_stream, "kernel_info_reply", content, msg["header"], None)
238
+ return True
239
+ elif msg_type in ["comm_open", "comm_msg", "comm_close"]:
240
+ with busy_idle(msg["header"]):
241
+ getattr(comm_manager, msg_type)(kernel.shell_stream, None, msg)
242
+ return True
243
+ elif msg_type in ["comm_info_request"]:
244
+ content = msg["content"]
245
+ target_name = msg.get("target_name", None)
246
+
247
+ comms = {
248
+ k: dict(target_name=v.target_name)
249
+ for (k, v) in comm_manager.comms.items() # type: ignore
250
+ if v.target_name == target_name or target_name is None # type: ignore
251
+ }
252
+ reply_content = dict(comms=comms, status="ok")
253
+ with busy_idle(msg["header"]):
254
+ msg = session.send(
255
+ kernel.shell_stream,
256
+ "comm_info_reply",
257
+ reply_content,
258
+ msg["header"],
259
+ None,
260
+ )
261
+ return True
262
+ elif msg_type == "shutdown_request":
263
+ send_status("dead", parent=msg["header"])
264
+ return False
265
+ else:
266
+ logger.error("Unsupported msg with msg_type %r", msg_type)
267
+ return False
268
+
269
+
270
+ def asset_directories():
271
+ application = [app.directory.parent / "assets" for app in app.apps.values()]
272
+ extra_paths = settings.assets.extra_paths()
273
+ solara_assets = solara_static.parent / "assets"
274
+ return [*application, *extra_paths, solara_assets]
275
+
276
+
277
+ def read_root(
278
+ path: str,
279
+ root_path: str = "",
280
+ jupyter_root_path: Union[str, None] = None,
281
+ render_kwargs={},
282
+ use_nbextensions=True,
283
+ ssg_data=None,
284
+ ) -> Optional[str]:
285
+ if settings.ssg.enabled and ssg_data is None:
286
+ # simply return the pre-rendered html
287
+ from solara_enterprise import ssg
288
+
289
+ content = ssg.ssg_content(path)
290
+ if content is not None:
291
+ return content
292
+
293
+ default_app = app.apps["__default__"]
294
+ default_app.check()
295
+ routes = default_app.routes
296
+ router = solara.routing.Router(path, routes)
297
+ if not router.possible_match:
298
+ return None
299
+ if use_nbextensions:
300
+ nbextensions, nbextensions_hashes = get_nbextensions()
301
+ else:
302
+ nbextensions, nbextensions_hashes = [], {}
303
+
304
+ from markupsafe import Markup
305
+
306
+ def resolve_static_path(path: str) -> Path:
307
+ # this solve a similar problem as the starlette and flask endpoints
308
+ # maybe this can be common code for all of them.
309
+ if path.startswith("/static/public/"):
310
+ directories = [default_app.directory.parent / "public"]
311
+ filename = path[len("/static/public/") :]
312
+ elif path.startswith("/static/assets/"):
313
+ directories = asset_directories()
314
+ filename = path[len("/static/assets/") :]
315
+ elif path.startswith("/static/"):
316
+ directories = [solara_static.parent / "static"]
317
+ filename = path[len("/static/") :]
318
+ else:
319
+ raise ValueError(f"invalid static path: {path}")
320
+ for directory in directories:
321
+ full_path = directory / filename
322
+ if full_path.exists():
323
+ return full_path
324
+ raise ValueError(f"static path not found: {filename} (path={path}), looked in {directories}")
325
+
326
+ def include_css(path: str) -> Markup:
327
+ filepath = resolve_static_path(path)
328
+ content, hash = solara.util.get_file_hash(filepath)
329
+ url = f"{root_path}{path}?v={hash}"
330
+ # when < 10k we embed, also when we use a url, it can be relative, which can break the url
331
+ embed = len(content) < 1024 * 10 and b"url" not in content
332
+ # Always embed the jupyterlab theme CSS to make theme switching possible (see solara.html.j2 template)
333
+ # TODO: Prevent browser from caching the theme CSS files
334
+ if path.endswith("theme-dark.css") or path.endswith("theme-light.css"):
335
+ content_utf8 = content.decode("utf-8")
336
+ code = content_utf8
337
+ elif embed:
338
+ content_utf8 = content.decode("utf-8")
339
+ code = f'<style class="solara-template-css">/*\npath={path}\n*/\n{content_utf8}</style>'
340
+ else:
341
+ code = f'<link rel="stylesheet" type="text/css" href="{url}" class="solara-template-css">'
342
+ return Markup(code)
343
+
344
+ def include_js(path: str, module=False) -> Markup:
345
+ filepath = resolve_static_path(path)
346
+ content, hash = solara.util.get_file_hash(filepath)
347
+ content_utf8 = content.decode("utf-8")
348
+ url = f"{root_path}{path}?v={hash}"
349
+ # when < 10k we embed, but if we use currentScript, it can break things
350
+ embed = len(content) < 1024 * 10 and b"currentScript" not in content
351
+ if embed:
352
+ if module:
353
+ code = f'<script type="module">/*\npath={path}\n*/{content_utf8}</script>'
354
+ else:
355
+ code = f"<script>/*\npath={path}\n*/{content_utf8}</script>"
356
+ else:
357
+ if module:
358
+ code = f'<script type="module" src="{url}"></script>'
359
+ else:
360
+ code = f'<script src="{url}"></script>'
361
+ return Markup(code)
362
+
363
+ resources = {
364
+ "theme": "light",
365
+ "nbextensions": nbextensions,
366
+ "nbextensions_hashes": nbextensions_hashes,
367
+ "include_css": include_css,
368
+ "include_js": include_js,
369
+ }
370
+ template: jinja2.Template = get_jinja_env(app_name="__default__").get_template(template_name)
371
+ pre_rendered_html = ""
372
+ pre_rendered_css = ""
373
+ pre_rendered_metas = ""
374
+ title = "Solara ☀️"
375
+ if ssg_data is not None:
376
+ pre_rendered_html = ssg_data["html"]
377
+ pre_rendered_css = "\n".join(ssg_data["styles"])
378
+ pre_rendered_metas = "\n ".join(ssg_data["metas"])
379
+ title = ssg_data["title"]
380
+
381
+ if solara.settings.assets.proxy:
382
+ # solara acts as a proxy
383
+ cdn = f"{root_path}/_solara/cdn"
384
+ else:
385
+ cdn = solara.settings.assets.cdn
386
+
387
+ if jupyter_root_path is None:
388
+ jupyter_root_path = f"{root_path}/jupyter"
389
+
390
+ render_settings = {
391
+ "title": title,
392
+ "path": path,
393
+ "root_path": root_path,
394
+ "jupyter_root_path": jupyter_root_path,
395
+ "resources": resources,
396
+ "theme": settings.theme.dict(),
397
+ "production": settings.main.mode == "production",
398
+ "pre_rendered_html": pre_rendered_html,
399
+ "pre_rendered_css": pre_rendered_css,
400
+ "pre_rendered_metas": pre_rendered_metas,
401
+ "assets": settings.assets.dict(),
402
+ "cdn": cdn,
403
+ "ipywidget_major_version": ipywidgets_major,
404
+ "solara_version": solara.__version__,
405
+ "platform": settings.main.platform,
406
+ "vue3": vue3,
407
+ "perform_check": settings.main.mode != "production" and solara.checks.should_perform_solara_check(),
408
+ **render_kwargs,
409
+ }
410
+ response = template.render(**render_settings)
411
+ return response
412
+
413
+
414
+ def find_prefixed_directory(path):
415
+ prefixes = [sys.prefix, os.path.expanduser("~/.local")]
416
+ for prefix in prefixes:
417
+ directory = f"{prefix}{path}"
418
+ if Path(directory).exists():
419
+ return directory
420
+ else:
421
+ raise RuntimeError(f"{path} not found at prefixes: {prefixes}")
422
+
423
+
424
+ @solara.memoize(storage=cache_memory)
425
+ def get_nbextensions_directories() -> List[Path]:
426
+ from jupyter_core.paths import jupyter_path
427
+
428
+ all_nb_directories = [Path(k) for k in jupyter_path("nbextensions")]
429
+ # FIXME: remove IPython nbextensions path after a migration period
430
+ try:
431
+ from IPython.paths import get_ipython_dir
432
+ except ImportError:
433
+ pass
434
+ else:
435
+ all_nb_directories.append(Path(get_ipython_dir()) / "nbextensions")
436
+ return [Path(k) for k in all_nb_directories]
437
+
438
+
439
+ @solara.memoize(storage=cache_memory)
440
+ def get_nbextensions() -> Tuple[List[str], Dict[str, Optional[str]]]:
441
+ from jupyter_core.paths import jupyter_config_path
442
+
443
+ paths = [Path(p) / "nbconfig" for p in jupyter_config_path()]
444
+
445
+ load_extensions = jupytertools.get_config(paths, "notebook")["load_extensions"]
446
+
447
+ def exists(name):
448
+ for directory in nbextensions_directories:
449
+ try:
450
+ file_path = directory / (name + ".js")
451
+ if file_path.exists():
452
+ return True
453
+ except PermissionError:
454
+ logger.warning(f"Caught PermissionError while checking for existence of nbextension {name!r} at path: {file_path}. This path will be ignored.")
455
+ logger.info(f"nbextension {name} not found")
456
+ return False
457
+
458
+ def hash_extension(name):
459
+ if sys.version_info[:2] < (3, 9):
460
+ # usedforsecurity is only available in Python 3.9+
461
+ h = hashlib.new("md5")
462
+ else:
463
+ h = hashlib.new("md5", usedforsecurity=False) # type: ignore
464
+
465
+ for directory in nbextensions_directories:
466
+ try:
467
+ file_path = directory / (name + ".js")
468
+ if file_path.exists():
469
+ for file in directory.glob("**/*.*"):
470
+ if file.is_file(): # Otherwise directories with a dot in the name are included
471
+ data = file.read_bytes()
472
+ h.update(data)
473
+ except PermissionError:
474
+ logger.warning(f"Caught PermissionError while checking for existence of nbextension {name!r} at path: {file_path}. This path will be ignored.")
475
+
476
+ return h.hexdigest()
477
+
478
+ nbextensions: List[str] = [name for name, enabled in load_extensions.items() if enabled and (name not in nbextensions_ignorelist) and exists(name)]
479
+ nbextensions_hashes = {name: hash_extension(name) for name in nbextensions}
480
+ return nbextensions, nbextensions_hashes
481
+
482
+
483
+ nbextensions_directories = get_nbextensions_directories()
484
+ solara_static = Path(__file__).parent / "static"