solara-ui 1.31.0__py2.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.
- prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- prefix/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara/__init__.py +124 -0
- solara/__main__.py +734 -0
- solara/alias.py +6 -0
- solara/autorouting.py +546 -0
- solara/cache.py +303 -0
- solara/checks.html +71 -0
- solara/checks.py +224 -0
- solara/comm.py +28 -0
- solara/components/__init__.py +59 -0
- solara/components/alert.py +155 -0
- solara/components/applayout.py +393 -0
- solara/components/button.py +85 -0
- solara/components/card.py +87 -0
- solara/components/checkbox.py +50 -0
- solara/components/code_highlight_css.py +11 -0
- solara/components/code_highlight_css.vue +63 -0
- solara/components/columns.py +159 -0
- solara/components/component_vue.py +110 -0
- solara/components/cross_filter.py +335 -0
- solara/components/dataframe.py +546 -0
- solara/components/datatable.py +221 -0
- solara/components/datatable.vue +175 -0
- solara/components/details.py +21 -0
- solara/components/download.vue +35 -0
- solara/components/echarts.py +75 -0
- solara/components/echarts.vue +128 -0
- solara/components/figure_altair.py +39 -0
- solara/components/file_browser.py +182 -0
- solara/components/file_download.py +199 -0
- solara/components/file_drop.py +139 -0
- solara/components/file_drop.vue +83 -0
- solara/components/file_list_widget.vue +78 -0
- solara/components/head.py +27 -0
- solara/components/head_tag.py +49 -0
- solara/components/head_tag.vue +60 -0
- solara/components/image.py +173 -0
- solara/components/input.py +436 -0
- solara/components/link.py +55 -0
- solara/components/markdown.py +378 -0
- solara/components/markdown_editor.py +25 -0
- solara/components/markdown_editor.vue +362 -0
- solara/components/matplotlib.py +74 -0
- solara/components/meta.py +47 -0
- solara/components/misc.py +333 -0
- solara/components/pivot_table.py +258 -0
- solara/components/pivot_table.vue +158 -0
- solara/components/progress.py +47 -0
- solara/components/select.py +182 -0
- solara/components/select.vue +27 -0
- solara/components/slider.py +442 -0
- solara/components/slider_date.vue +56 -0
- solara/components/spinner-solara.vue +105 -0
- solara/components/spinner.py +30 -0
- solara/components/sql_code.py +33 -0
- solara/components/sql_code.vue +128 -0
- solara/components/style.py +105 -0
- solara/components/switch.py +68 -0
- solara/components/tab_navigation.py +37 -0
- solara/components/title.py +90 -0
- solara/components/title.vue +38 -0
- solara/components/togglebuttons.py +200 -0
- solara/components/tooltip.py +61 -0
- solara/datatypes.py +143 -0
- solara/express.py +241 -0
- solara/hooks/__init__.py +4 -0
- solara/hooks/dataframe.py +99 -0
- solara/hooks/misc.py +263 -0
- solara/hooks/use_reactive.py +129 -0
- solara/hooks/use_thread.py +129 -0
- solara/kitchensink.py +8 -0
- solara/lab/__init__.py +34 -0
- solara/lab/components/__init__.py +6 -0
- solara/lab/components/chat.py +203 -0
- solara/lab/components/confirmation_dialog.py +163 -0
- solara/lab/components/cross_filter.py +7 -0
- solara/lab/components/input_date.py +298 -0
- solara/lab/components/menu.py +181 -0
- solara/lab/components/menu.vue +38 -0
- solara/lab/components/tabs.py +274 -0
- solara/lab/components/theming.py +98 -0
- solara/lab/components/theming.vue +72 -0
- solara/lab/hooks/__init__.py +0 -0
- solara/lab/hooks/dataframe.py +12 -0
- solara/lab/toestand.py +3 -0
- solara/lab/utils/__init__.py +2 -0
- solara/lab/utils/cookies.py +5 -0
- solara/lab/utils/dataframe.py +115 -0
- solara/lab/utils/headers.py +5 -0
- solara/layout.py +44 -0
- solara/lifecycle.py +46 -0
- solara/minisettings.py +133 -0
- solara/py.typed +0 -0
- solara/reactive.py +93 -0
- solara/routing.py +268 -0
- solara/scope/__init__.py +88 -0
- solara/scope/types.py +55 -0
- solara/server/__init__.py +0 -0
- solara/server/app.py +491 -0
- solara/server/assets/custom.css +1 -0
- solara/server/assets/custom.js +1 -0
- solara/server/assets/favicon.png +0 -0
- solara/server/assets/favicon.svg +5 -0
- solara/server/assets/style.css +1665 -0
- solara/server/assets/theme-dark.css +437 -0
- solara/server/assets/theme-light.css +420 -0
- solara/server/assets/theme.js +3 -0
- solara/server/cdn_helper.py +77 -0
- solara/server/esm.py +69 -0
- solara/server/fastapi.py +5 -0
- solara/server/flask.py +286 -0
- solara/server/jupyter/__init__.py +2 -0
- solara/server/jupyter/cdn_handler.py +28 -0
- solara/server/jupyter/server_extension.py +29 -0
- solara/server/jupytertools.py +46 -0
- solara/server/kernel.py +338 -0
- solara/server/kernel_context.py +357 -0
- solara/server/patch.py +552 -0
- solara/server/reload.py +242 -0
- solara/server/server.py +456 -0
- solara/server/settings.py +215 -0
- solara/server/shell.py +251 -0
- solara/server/starlette.py +601 -0
- solara/server/static/ansi.js +270 -0
- solara/server/static/highlight-dark.css +82 -0
- solara/server/static/highlight.css +43 -0
- solara/server/static/main-vuetify.js +260 -0
- solara/server/static/main.js +163 -0
- solara/server/static/solara_bootstrap.py +129 -0
- solara/server/static/sun.svg +23 -0
- solara/server/static/webworker.js +42 -0
- solara/server/telemetry.py +212 -0
- solara/server/templates/index.html.j2 +1 -0
- solara/server/templates/loader-plain.css +11 -0
- solara/server/templates/loader-plain.html +20 -0
- solara/server/templates/loader-solara.css +111 -0
- solara/server/templates/loader-solara.html +40 -0
- solara/server/templates/plain.html +82 -0
- solara/server/templates/solara.html.j2 +446 -0
- solara/server/threaded.py +75 -0
- solara/server/utils.py +30 -0
- solara/server/websocket.py +45 -0
- solara/settings.py +56 -0
- solara/tasks.py +837 -0
- solara/template/button.py +16 -0
- solara/template/markdown.py +42 -0
- solara/template/portal/.flake8 +6 -0
- solara/template/portal/.pre-commit-config.yaml +28 -0
- solara/template/portal/LICENSE +21 -0
- solara/template/portal/Procfile +7 -0
- solara/template/portal/mypy.ini +3 -0
- solara/template/portal/pyproject.toml +26 -0
- solara/template/portal/solara_portal/__init__.py +4 -0
- solara/template/portal/solara_portal/components/__init__.py +2 -0
- solara/template/portal/solara_portal/components/article.py +28 -0
- solara/template/portal/solara_portal/components/data.py +28 -0
- solara/template/portal/solara_portal/components/header.py +6 -0
- solara/template/portal/solara_portal/components/layout.py +6 -0
- solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +85 -0
- solara/template/portal/solara_portal/content/articles/substiterat-vati.md +70 -0
- solara/template/portal/solara_portal/data.py +60 -0
- solara/template/portal/solara_portal/pages/__init__.py +67 -0
- solara/template/portal/solara_portal/pages/article/__init__.py +26 -0
- solara/template/portal/solara_portal/pages/tabular.py +29 -0
- solara/template/portal/solara_portal/pages/viz/__init__.py +70 -0
- solara/template/portal/solara_portal/pages/viz/overview.py +14 -0
- solara/test/__init__.py +0 -0
- solara/test/pytest_plugin.py +697 -0
- solara/toestand.py +772 -0
- solara/util.py +308 -0
- solara/website/__init__.py +0 -0
- solara/website/assets/custom.css +468 -0
- solara/website/assets/images/logo-small.png +0 -0
- solara/website/assets/images/logo.svg +17 -0
- solara/website/assets/images/logo_white.svg +50 -0
- solara/website/assets/theme.js +8 -0
- solara/website/components/__init__.py +5 -0
- solara/website/components/algolia.vue +24 -0
- solara/website/components/algolia_api.vue +187 -0
- solara/website/components/docs.py +118 -0
- solara/website/components/header.py +72 -0
- solara/website/components/hero.py +15 -0
- solara/website/components/mailchimp.py +12 -0
- solara/website/components/mailchimp.vue +47 -0
- solara/website/components/markdown.py +30 -0
- solara/website/components/notebook.py +171 -0
- solara/website/pages/__init__.py +575 -0
- solara/website/pages/apps/__init__.py +16 -0
- solara/website/pages/apps/authorization/__init__.py +119 -0
- solara/website/pages/apps/authorization/admin.py +12 -0
- solara/website/pages/apps/authorization/users.py +12 -0
- solara/website/pages/apps/jupyter-dashboard-1.py +116 -0
- solara/website/pages/apps/layout-demo.py +40 -0
- solara/website/pages/apps/multipage/__init__.py +38 -0
- solara/website/pages/apps/multipage/page1.py +26 -0
- solara/website/pages/apps/multipage/page2.py +34 -0
- solara/website/pages/apps/scatter.py +136 -0
- solara/website/pages/apps/scrolling.py +63 -0
- solara/website/pages/apps/tutorial-streamlit.py +18 -0
- solara/website/pages/changelog/__init__.py +8 -0
- solara/website/pages/changelog/changelog.md +204 -0
- solara/website/pages/contact/__init__.py +8 -0
- solara/website/pages/contact/contact.md +17 -0
- solara/website/pages/doc_use_download.py +85 -0
- solara/website/pages/documentation/__init__.py +184 -0
- solara/website/pages/documentation/advanced/__init__.py +9 -0
- solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
- solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +6 -0
- solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +196 -0
- solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +125 -0
- solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +162 -0
- solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +69 -0
- solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +49 -0
- solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +124 -0
- solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +3 -0
- solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +31 -0
- solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +36 -0
- solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +59 -0
- solara/website/pages/documentation/advanced/content/15-reference/70-search.md +34 -0
- solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +34 -0
- solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +7 -0
- solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +148 -0
- solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +10 -0
- solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +35 -0
- solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +42 -0
- solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +28 -0
- solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +108 -0
- solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +23 -0
- solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +7 -0
- solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +166 -0
- solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +18 -0
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +240 -0
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +97 -0
- solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +12 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +171 -0
- solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
- solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +45 -0
- solara/website/pages/documentation/advanced/content/40-development/10-setup.md +76 -0
- solara/website/pages/documentation/api/__init__.py +19 -0
- solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +23 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +22 -0
- solara/website/pages/documentation/api/hooks/__init__.py +9 -0
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +25 -0
- solara/website/pages/documentation/api/hooks/use_dark_effective.py +12 -0
- solara/website/pages/documentation/api/hooks/use_effect.md +43 -0
- solara/website/pages/documentation/api/hooks/use_effect.py +9 -0
- solara/website/pages/documentation/api/hooks/use_exception.py +33 -0
- solara/website/pages/documentation/api/hooks/use_memo.md +16 -0
- solara/website/pages/documentation/api/hooks/use_memo.py +9 -0
- solara/website/pages/documentation/api/hooks/use_previous.py +33 -0
- solara/website/pages/documentation/api/hooks/use_reactive.py +16 -0
- solara/website/pages/documentation/api/hooks/use_state.py +10 -0
- solara/website/pages/documentation/api/hooks/use_state_or_update.py +69 -0
- solara/website/pages/documentation/api/hooks/use_thread.md +58 -0
- solara/website/pages/documentation/api/hooks/use_thread.py +44 -0
- solara/website/pages/documentation/api/hooks/use_trait_observe.py +12 -0
- solara/website/pages/documentation/api/routing/__init__.py +9 -0
- solara/website/pages/documentation/api/routing/generate_routes.py +10 -0
- solara/website/pages/documentation/api/routing/generate_routes_directory.py +10 -0
- solara/website/pages/documentation/api/routing/resolve_path.py +35 -0
- solara/website/pages/documentation/api/routing/route.py +31 -0
- solara/website/pages/documentation/api/routing/use_route.py +80 -0
- solara/website/pages/documentation/api/routing/use_router.py +16 -0
- solara/website/pages/documentation/api/utilities/__init__.py +9 -0
- solara/website/pages/documentation/api/utilities/component_vue.py +10 -0
- solara/website/pages/documentation/api/utilities/computed.py +16 -0
- solara/website/pages/documentation/api/utilities/display.py +16 -0
- solara/website/pages/documentation/api/utilities/get_kernel_id.py +16 -0
- solara/website/pages/documentation/api/utilities/get_session_id.py +16 -0
- solara/website/pages/documentation/api/utilities/memoize.py +35 -0
- solara/website/pages/documentation/api/utilities/on_kernel_start.py +27 -0
- solara/website/pages/documentation/api/utilities/reactive.py +16 -0
- solara/website/pages/documentation/api/utilities/widget.py +104 -0
- solara/website/pages/documentation/components/__init__.py +12 -0
- solara/website/pages/documentation/components/advanced/__init__.py +9 -0
- solara/website/pages/documentation/components/advanced/link.py +27 -0
- solara/website/pages/documentation/components/advanced/meta.py +20 -0
- solara/website/pages/documentation/components/advanced/style.py +45 -0
- solara/website/pages/documentation/components/common.py +9 -0
- solara/website/pages/documentation/components/data/__init__.py +9 -0
- solara/website/pages/documentation/components/data/dataframe.py +44 -0
- solara/website/pages/documentation/components/data/pivot_table.py +81 -0
- solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
- solara/website/pages/documentation/components/enterprise/avatar.py +24 -0
- solara/website/pages/documentation/components/enterprise/avatar_menu.py +25 -0
- solara/website/pages/documentation/components/input/__init__.py +9 -0
- solara/website/pages/documentation/components/input/button.py +23 -0
- solara/website/pages/documentation/components/input/checkbox.py +10 -0
- solara/website/pages/documentation/components/input/file_browser.py +32 -0
- solara/website/pages/documentation/components/input/file_drop.py +76 -0
- solara/website/pages/documentation/components/input/input.py +19 -0
- solara/website/pages/documentation/components/input/select.py +22 -0
- solara/website/pages/documentation/components/input/slider.py +29 -0
- solara/website/pages/documentation/components/input/switch.py +10 -0
- solara/website/pages/documentation/components/input/togglebuttons.py +21 -0
- solara/website/pages/documentation/components/lab/__init__.py +9 -0
- solara/website/pages/documentation/components/lab/chat.py +109 -0
- solara/website/pages/documentation/components/lab/confirmation_dialog.py +55 -0
- solara/website/pages/documentation/components/lab/cookies_headers.py +48 -0
- solara/website/pages/documentation/components/lab/input_date.py +20 -0
- solara/website/pages/documentation/components/lab/menu.py +22 -0
- solara/website/pages/documentation/components/lab/tab.py +25 -0
- solara/website/pages/documentation/components/lab/tabs.py +45 -0
- solara/website/pages/documentation/components/lab/task.py +11 -0
- solara/website/pages/documentation/components/lab/theming.py +72 -0
- solara/website/pages/documentation/components/lab/use_task.py +11 -0
- solara/website/pages/documentation/components/layout/__init__.py +9 -0
- solara/website/pages/documentation/components/layout/app_bar.py +16 -0
- solara/website/pages/documentation/components/layout/app_bar_title.py +16 -0
- solara/website/pages/documentation/components/layout/app_layout.py +24 -0
- solara/website/pages/documentation/components/layout/card.py +15 -0
- solara/website/pages/documentation/components/layout/card_actions.py +16 -0
- solara/website/pages/documentation/components/layout/column.py +30 -0
- solara/website/pages/documentation/components/layout/columns.py +27 -0
- solara/website/pages/documentation/components/layout/columns_responsive.py +68 -0
- solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
- solara/website/pages/documentation/components/layout/gridfixed.py +21 -0
- solara/website/pages/documentation/components/layout/hbox.py +18 -0
- solara/website/pages/documentation/components/layout/row.py +30 -0
- solara/website/pages/documentation/components/layout/sidebar.py +24 -0
- solara/website/pages/documentation/components/layout/vbox.py +19 -0
- solara/website/pages/documentation/components/output/__init__.py +9 -0
- solara/website/pages/documentation/components/output/file_download.py +11 -0
- solara/website/pages/documentation/components/output/html.py +21 -0
- solara/website/pages/documentation/components/output/image.py +11 -0
- solara/website/pages/documentation/components/output/markdown.py +57 -0
- solara/website/pages/documentation/components/output/markdown_editor.py +51 -0
- solara/website/pages/documentation/components/output/sql_code.py +85 -0
- solara/website/pages/documentation/components/output/tooltip.py +11 -0
- solara/website/pages/documentation/components/page/__init__.py +9 -0
- solara/website/pages/documentation/components/page/head.py +18 -0
- solara/website/pages/documentation/components/page/title.py +27 -0
- solara/website/pages/documentation/components/status/__init__.py +9 -0
- solara/website/pages/documentation/components/status/error.py +40 -0
- solara/website/pages/documentation/components/status/info.py +40 -0
- solara/website/pages/documentation/components/status/progress.py +10 -0
- solara/website/pages/documentation/components/status/spinner.py +11 -0
- solara/website/pages/documentation/components/status/success.py +40 -0
- solara/website/pages/documentation/components/status/warning.py +47 -0
- solara/website/pages/documentation/components/viz/__init__.py +9 -0
- solara/website/pages/documentation/components/viz/altair.py +42 -0
- solara/website/pages/documentation/components/viz/echarts.py +75 -0
- solara/website/pages/documentation/components/viz/matplotlib.py +30 -0
- solara/website/pages/documentation/components/viz/plotly.py +63 -0
- solara/website/pages/documentation/components/viz/plotly_express.py +41 -0
- solara/website/pages/documentation/examples/__init__.py +52 -0
- solara/website/pages/documentation/examples/ai/__init__.py +11 -0
- solara/website/pages/documentation/examples/ai/chatbot.py +95 -0
- solara/website/pages/documentation/examples/ai/tokenizer.py +107 -0
- solara/website/pages/documentation/examples/basics/__init__.py +10 -0
- solara/website/pages/documentation/examples/basics/sine.py +28 -0
- solara/website/pages/documentation/examples/fullscreen/__init__.py +10 -0
- solara/website/pages/documentation/examples/fullscreen/authorization.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/layout_demo.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/multipage.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/scatter.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/scrolling.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +3 -0
- solara/website/pages/documentation/examples/general/__init__.py +10 -0
- solara/website/pages/documentation/examples/general/custom_storage.py +70 -0
- solara/website/pages/documentation/examples/general/deploy_model.py +115 -0
- solara/website/pages/documentation/examples/general/live_update.py +38 -0
- solara/website/pages/documentation/examples/general/login_oauth.py +81 -0
- solara/website/pages/documentation/examples/general/mycard.vue +58 -0
- solara/website/pages/documentation/examples/general/pokemon_search.py +51 -0
- solara/website/pages/documentation/examples/general/vue_component.py +50 -0
- solara/website/pages/documentation/examples/ipycanvas.py +49 -0
- solara/website/pages/documentation/examples/libraries/__init__.py +10 -0
- solara/website/pages/documentation/examples/libraries/altair.py +64 -0
- solara/website/pages/documentation/examples/libraries/bqplot.py +39 -0
- solara/website/pages/documentation/examples/libraries/ipyleaflet.py +33 -0
- solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +66 -0
- solara/website/pages/documentation/examples/utilities/__init__.py +10 -0
- solara/website/pages/documentation/examples/utilities/calculator.py +157 -0
- solara/website/pages/documentation/examples/utilities/countdown_timer.py +64 -0
- solara/website/pages/documentation/examples/utilities/todo.py +196 -0
- solara/website/pages/documentation/examples/visualization/__init__.py +6 -0
- solara/website/pages/documentation/examples/visualization/annotator.py +69 -0
- solara/website/pages/documentation/examples/visualization/linked_views.py +84 -0
- solara/website/pages/documentation/examples/visualization/plotly.py +44 -0
- solara/website/pages/documentation/faq/__init__.py +12 -0
- solara/website/pages/documentation/faq/content/99-faq.md +76 -0
- solara/website/pages/documentation/getting_started/__init__.py +9 -0
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +89 -0
- solara/website/pages/documentation/getting_started/content/01-introduction.md +125 -0
- solara/website/pages/documentation/getting_started/content/02-installing.md +134 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +14 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +13 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +89 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +124 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +146 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +144 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +64 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +445 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +1000 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +11 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +223 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +88 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +7 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +273 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +80 -0
- solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +7 -0
- solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +26 -0
- solara/website/pages/docutils.py +38 -0
- solara/website/pages/showcase/__init__.py +105 -0
- solara/website/pages/showcase/domino_code_assist.py +60 -0
- solara/website/pages/showcase/planeto_tessa.py +19 -0
- solara/website/pages/showcase/solara_dev.py +54 -0
- solara/website/pages/showcase/solarathon_2023_team_2.py +22 -0
- solara/website/pages/showcase/solarathon_2023_team_4.py +22 -0
- solara/website/pages/showcase/solarathon_2023_team_5.py +23 -0
- solara/website/pages/showcase/solarathon_2023_team_6.py +34 -0
- solara/website/pages/showcase/wanderlust.py +27 -0
- solara/website/public/beach.jpeg +0 -0
- solara/website/public/logo.svg +6 -0
- solara/website/public/social/discord.svg +1 -0
- solara/website/public/social/github.svg +1 -0
- solara/website/public/social/twitter.svg +3 -0
- solara/website/public/success.html +25 -0
- solara/website/templates/index.html.j2 +117 -0
- solara/website/utils.py +51 -0
- solara/widgets/__init__.py +1 -0
- solara/widgets/vue/gridlayout.vue +110 -0
- solara/widgets/vue/html.vue +4 -0
- solara/widgets/vue/navigator.vue +104 -0
- solara/widgets/vue/vegalite.vue +115 -0
- solara/widgets/widgets.py +66 -0
- solara_ui-1.31.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- solara_ui-1.31.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara_ui-1.31.0.dist-info/METADATA +158 -0
- solara_ui-1.31.0.dist-info/RECORD +439 -0
- solara_ui-1.31.0.dist-info/WHEEL +5 -0
- solara_ui-1.31.0.dist-info/licenses/LICENSE +21 -0
solara/routing.py
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Callable, List, Optional, Tuple, Union, cast
|
|
4
|
+
|
|
5
|
+
import solara
|
|
6
|
+
from solara import _using_solara_server
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("solara.router")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class _LocationBase(abc.ABC):
|
|
12
|
+
@property
|
|
13
|
+
def pathname(self):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
@pathname.setter
|
|
17
|
+
# mypy does not accept this
|
|
18
|
+
# @abc.abstractmethod
|
|
19
|
+
def pathname(self):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _Location(_LocationBase):
|
|
24
|
+
def __init__(self, pathname, setter: Callable[[str], None]) -> None:
|
|
25
|
+
self._pathname = pathname
|
|
26
|
+
self.setter = setter
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def pathname(self):
|
|
30
|
+
return self._pathname
|
|
31
|
+
|
|
32
|
+
@pathname.setter
|
|
33
|
+
def pathname(self, value):
|
|
34
|
+
# import pdb
|
|
35
|
+
|
|
36
|
+
# pdb.set_trace()
|
|
37
|
+
self._pathname = value
|
|
38
|
+
self.setter(self._pathname)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Router:
|
|
42
|
+
search: Optional[str]
|
|
43
|
+
|
|
44
|
+
def __init__(self, path: str, routes: List[solara.Route], set_path: Callable[[str], None] = None):
|
|
45
|
+
# see https://developer.mozilla.org/en-US/docs/Web/API/Location for anatomy/nomenclature
|
|
46
|
+
if "?" in path:
|
|
47
|
+
self.path, self.search = path.split("?", 1)
|
|
48
|
+
else:
|
|
49
|
+
self.path = path
|
|
50
|
+
self.search = None
|
|
51
|
+
del path
|
|
52
|
+
self.set_path = set_path
|
|
53
|
+
self.parts = (self.path or "").strip("/").split("/")
|
|
54
|
+
self.routes = routes
|
|
55
|
+
self.root_path = ""
|
|
56
|
+
if _using_solara_server():
|
|
57
|
+
import solara.server.settings
|
|
58
|
+
|
|
59
|
+
self.root_path = solara.server.settings.main.root_path or ""
|
|
60
|
+
# each route in this list corresponds to a part in self.parts
|
|
61
|
+
self.path_routes: List["solara.Route"] = []
|
|
62
|
+
self.path_routes_siblings: List[List["solara.Route"]] = [] # siblings including itself
|
|
63
|
+
# routes = routes.copy()
|
|
64
|
+
route = None
|
|
65
|
+
for part in self.parts:
|
|
66
|
+
for route in routes:
|
|
67
|
+
if (route.path == part) or (route.path == "/" and not part):
|
|
68
|
+
self.path_routes.append(route)
|
|
69
|
+
self.path_routes_siblings.append(routes)
|
|
70
|
+
routes = route.children
|
|
71
|
+
break
|
|
72
|
+
if len(self.parts) == len(self.path_routes):
|
|
73
|
+
# e.g. '/foo/bar' -> ['foo', 'bar'] and bar has a default route
|
|
74
|
+
# but if '' -> [''] we should not
|
|
75
|
+
route = self.path_routes[-1]
|
|
76
|
+
if route:
|
|
77
|
+
default_routes = [k for k in route.children if k.path == "/"]
|
|
78
|
+
if self.parts and self.parts[0] and default_routes:
|
|
79
|
+
self.path_routes.append(default_routes[0])
|
|
80
|
+
self.path_routes_siblings.append(route.children)
|
|
81
|
+
|
|
82
|
+
assert len(self.path_routes) == len(self.path_routes_siblings)
|
|
83
|
+
self.possible_match = (len(self.path_routes[-1].children) == 0) if self.path_routes else False
|
|
84
|
+
|
|
85
|
+
def push(self, path: str):
|
|
86
|
+
assert self.set_path is not None
|
|
87
|
+
self.set_path(path)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
router_context = solara.create_context(Router("", []))
|
|
91
|
+
_location_context = solara.create_context(cast(_LocationBase, _Location("", lambda x: None)))
|
|
92
|
+
|
|
93
|
+
route_level_context = solara.create_context(0)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def use_route_level():
|
|
97
|
+
route_level = solara.use_context(route_level_context)
|
|
98
|
+
return route_level
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def use_router() -> Router:
|
|
102
|
+
"""Returns the current router object.
|
|
103
|
+
|
|
104
|
+
See also [Understanding Routing](/documentation/advanced/understanding/routing).
|
|
105
|
+
|
|
106
|
+
`use_router` returns the current router object. This is useful to build custom routing.
|
|
107
|
+
|
|
108
|
+
the router object contains the following properties/methods:
|
|
109
|
+
|
|
110
|
+
* `path` - the current pathname (e.g. `/fruit/banana`)
|
|
111
|
+
* `parts` - the current pathname split into parts (e.g. `['fruit', 'banana']`)
|
|
112
|
+
* `search` - the query parameters string (e.g. `color=yellow`).
|
|
113
|
+
* `push(path: str)` - navigate to path (e.g. `router.push('/fruit/banana')`)
|
|
114
|
+
|
|
115
|
+
## Typical usage:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import solara
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@solara.component
|
|
122
|
+
def Page():
|
|
123
|
+
router = solara.use_router()
|
|
124
|
+
|
|
125
|
+
def redirect():
|
|
126
|
+
router.push(f"/documentation/api/routing/use_route")
|
|
127
|
+
|
|
128
|
+
solara.Button("Navigate using an event", on_click=redirect)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
return solara.use_context(router_context)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def use_route(
|
|
136
|
+
level=0,
|
|
137
|
+
peek=False,
|
|
138
|
+
) -> Tuple[Optional[solara.Route], List[solara.Route]]:
|
|
139
|
+
"""Returns (if found) the current route that matches the pathname, or None
|
|
140
|
+
|
|
141
|
+
See also [Understanding Routing](/documentation/advanced/understanding/routing).
|
|
142
|
+
|
|
143
|
+
`use_route` returns (if found) the current route that matches the pathname, or None. It also returns all resolved routes of that level
|
|
144
|
+
(i.e. all siblings and itself). This return tuple is useful to build custom navigation (e.g. using tabs or buttons).
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
Routing starts with declaring a set of `routes` in your app (solara picks up the `routes` variable if it exists,
|
|
148
|
+
and it should be in the same namespace as `Page`).
|
|
149
|
+
In the demo below, we declared the following routes.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
routes = [
|
|
153
|
+
solara.Route(path="/"),
|
|
154
|
+
solara.Route(
|
|
155
|
+
path="fruit",
|
|
156
|
+
component=Fruit,
|
|
157
|
+
children=[
|
|
158
|
+
solara.Route(path="/"),
|
|
159
|
+
solara.Route(path="kiwi"),
|
|
160
|
+
solara.Route(path="banana"),
|
|
161
|
+
solara.Route(path="apple"),
|
|
162
|
+
],
|
|
163
|
+
),
|
|
164
|
+
]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Note that all routes are relative, since a component does not know if it is embedded into a larger application, which may also do routing.
|
|
168
|
+
Therefore you should never use the `route.path` for navigation since the route object has no knowledge of the full url
|
|
169
|
+
(e.g. `/documentation/api/routing/use_route/fruit/banana`) but only knows its small piece of the pathname (e.g. `banana`)
|
|
170
|
+
|
|
171
|
+
Use [`resolve_path`](/documentation/api/routing/resolve_path) to request the full url for navigation,
|
|
172
|
+
or simply use the `Link` component that can do this for us.
|
|
173
|
+
|
|
174
|
+
If the current route has children, any child component that calls `use_route` will return the matched route and its siblings of our children.
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
## Arguments
|
|
178
|
+
|
|
179
|
+
* `level`: the level of the route to return. 0 is the current route, -1 is the parent route, 1 the child route, etc.
|
|
180
|
+
* `peek`: if True, the route level is not incremented. This is useful to peek at the next route level without changing the current route level.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
router = solara.use_context(router_context)
|
|
184
|
+
route_level = solara.use_context(route_level_context)
|
|
185
|
+
if not peek:
|
|
186
|
+
route_level_context.provide(route_level + 1)
|
|
187
|
+
route_level += level
|
|
188
|
+
if route_level < len(router.path_routes):
|
|
189
|
+
return router.path_routes[route_level], router.path_routes_siblings[route_level]
|
|
190
|
+
else:
|
|
191
|
+
return None, []
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def find_route(path: str) -> Optional[solara.Route]:
|
|
195
|
+
router = solara.get_context(router_context)
|
|
196
|
+
route_level = min(solara.get_context(route_level_context), len(router.path_routes_siblings) - 1)
|
|
197
|
+
for route in router.path_routes_siblings[route_level]:
|
|
198
|
+
if path.startswith(route.path) or (not path and route.path == "/"):
|
|
199
|
+
return route
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def use_pathname():
|
|
204
|
+
location_proxy = solara.use_context(_location_context)
|
|
205
|
+
|
|
206
|
+
def setter(value):
|
|
207
|
+
location_proxy.pathname = value
|
|
208
|
+
|
|
209
|
+
return location_proxy.pathname, setter
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def resolve_path(path_or_route: Union[str, solara.Route], level=0) -> str:
|
|
213
|
+
"""Resolve a relative path or a route to an absolute path.
|
|
214
|
+
|
|
215
|
+
If the path is a string and starts with a `/'`, it is returned as is.
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
## Typical usage:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
...
|
|
222
|
+
route_current, routes_current_level = solara.routes()
|
|
223
|
+
# route_current.path == "banana"
|
|
224
|
+
path = solara.resolve_path(route_current)
|
|
225
|
+
# path == "/fruit/banana"
|
|
226
|
+
path_same = solara.resolve_path("banana")
|
|
227
|
+
# path_same == path == "/fruit/banana"
|
|
228
|
+
...
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Arguments
|
|
232
|
+
|
|
233
|
+
* path_or_route: a path string or a [`solara.Route`](/documentation/api/routing/route) object to resolve.
|
|
234
|
+
|
|
235
|
+
## See also
|
|
236
|
+
|
|
237
|
+
* [Multipage](/documentation/advanced/howto/multipage).
|
|
238
|
+
* [Understanding Routing](/documentation/advanced/understanding/routing).
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
"""
|
|
242
|
+
router = solara.get_context(router_context)
|
|
243
|
+
if isinstance(path_or_route, str):
|
|
244
|
+
path = path_or_route
|
|
245
|
+
if path.startswith("/"):
|
|
246
|
+
return path
|
|
247
|
+
route_level = solara.get_context(route_level_context) + level
|
|
248
|
+
parts = [*router.parts[:route_level], path]
|
|
249
|
+
path = "/" + "/".join(parts)
|
|
250
|
+
if path.startswith("//"):
|
|
251
|
+
path = path[1:]
|
|
252
|
+
return path
|
|
253
|
+
elif isinstance(path_or_route, solara.Route):
|
|
254
|
+
route: solara.Route = path_or_route
|
|
255
|
+
path = _resolve_path("/", route, router.routes)
|
|
256
|
+
if path.startswith("//"):
|
|
257
|
+
path = path[1:]
|
|
258
|
+
return path
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _resolve_path(prefix: str, findroute: solara.Route, routes: List[solara.Route]):
|
|
262
|
+
for route in routes:
|
|
263
|
+
path = (prefix + "/" + route.path) if route.path != "/" else prefix
|
|
264
|
+
if findroute is route:
|
|
265
|
+
return path
|
|
266
|
+
possible_path = _resolve_path(path, findroute=findroute, routes=route.children)
|
|
267
|
+
if possible_path is not None:
|
|
268
|
+
return possible_path
|
solara/scope/__init__.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import threading
|
|
4
|
+
from typing import MutableMapping
|
|
5
|
+
|
|
6
|
+
from .types import ObservableMutableMapping
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _in_solara_server():
|
|
10
|
+
return "solara.server" in sys.modules
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ConnectionScope(ObservableMutableMapping):
|
|
14
|
+
def __init__(self, name="connection"):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self._global_dict = {}
|
|
17
|
+
self.name = name
|
|
18
|
+
self.lock = threading.Lock()
|
|
19
|
+
|
|
20
|
+
def _get_dict(self) -> MutableMapping:
|
|
21
|
+
if _in_solara_server():
|
|
22
|
+
import solara.server.kernel_context
|
|
23
|
+
|
|
24
|
+
context = solara.server.kernel_context.get_current_context()
|
|
25
|
+
if self.name not in context.user_dicts:
|
|
26
|
+
with self.lock:
|
|
27
|
+
if self.name not in context.user_dicts:
|
|
28
|
+
context.user_dicts[self.name] = {}
|
|
29
|
+
return context.user_dicts[self.name]
|
|
30
|
+
else:
|
|
31
|
+
return self._global_dict
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ObservableDict(ObservableMutableMapping):
|
|
35
|
+
def __init__(self):
|
|
36
|
+
super().__init__()
|
|
37
|
+
self._global_dict = {}
|
|
38
|
+
|
|
39
|
+
def _get_dict(self) -> MutableMapping:
|
|
40
|
+
return self._global_dict
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
worker = ObservableDict()
|
|
44
|
+
connection = ConnectionScope()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_kernel_id(ipython_fallback=True) -> str:
|
|
48
|
+
"""Returns the kernel id, a unique string for each virtual kernel.
|
|
49
|
+
|
|
50
|
+
See [Understanding solara server](/docs/understanding/solara-server) for understanding the concept of virtual kernels
|
|
51
|
+
and their lifetime.
|
|
52
|
+
|
|
53
|
+
This unique ID can be useful to to implement storing state, scoped to a kernel. See [the scope example](/examples/general/custom_storage) for an example.
|
|
54
|
+
|
|
55
|
+
If `ipython_fallback` is `True` (default), this function will also work in IPython notebooks, where it will return the IPython kernel id.
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
import solara.server.kernel_context
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
context = solara.server.kernel_context.get_current_context()
|
|
62
|
+
except RuntimeError as e:
|
|
63
|
+
if not ipython_fallback:
|
|
64
|
+
raise
|
|
65
|
+
import IPython
|
|
66
|
+
|
|
67
|
+
ipython = IPython.get_ipython()
|
|
68
|
+
if not ipython or not hasattr(ipython, "kernel"):
|
|
69
|
+
raise RuntimeError("Not in a kernel") from e
|
|
70
|
+
kernel = ipython.kernel
|
|
71
|
+
regex = r"[\\/]kernel-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.json$"
|
|
72
|
+
connection_file = kernel.config["IPKernelApp"]["connection_file"]
|
|
73
|
+
return re.compile(regex).search(connection_file).group(1) # type: ignore
|
|
74
|
+
return context.id
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_session_id() -> str:
|
|
78
|
+
"""Returns the session id, which is stored using a browser cookie.
|
|
79
|
+
|
|
80
|
+
See [Understanding solara server](/docs/understanding/solara-server#session) for more information about the Solara sessions.
|
|
81
|
+
|
|
82
|
+
This unique ID can be useful to to implement storing state, scoped to a browser session. See [the scope example](/examples/general/custom_storage)
|
|
83
|
+
for an example.
|
|
84
|
+
"""
|
|
85
|
+
import solara.server.kernel_context
|
|
86
|
+
|
|
87
|
+
context = solara.server.kernel_context.get_current_context()
|
|
88
|
+
return context.session_id
|
solara/scope/types.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from typing import Any, Callable, Dict, List, MutableMapping
|
|
4
|
+
from warnings import warn
|
|
5
|
+
|
|
6
|
+
ObserverCallback = Callable[[Any, Any], None]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MutableMappingBase(MutableMapping):
|
|
10
|
+
@abstractmethod
|
|
11
|
+
def _get_dict(self) -> MutableMapping:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
def __delitem__(self, key) -> None:
|
|
15
|
+
self._get_dict().__delitem__(key)
|
|
16
|
+
|
|
17
|
+
def __getitem__(self, key):
|
|
18
|
+
return self._get_dict().__getitem__(key)
|
|
19
|
+
|
|
20
|
+
def __iter__(self):
|
|
21
|
+
return self._get_dict().__iter__()
|
|
22
|
+
|
|
23
|
+
def __len__(self):
|
|
24
|
+
return self._get_dict().__len__()
|
|
25
|
+
|
|
26
|
+
def __setitem__(self, key, value):
|
|
27
|
+
self._get_dict().__setitem__(key, value)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ObservableMutableMapping(MutableMappingBase):
|
|
31
|
+
# list of observers for each key
|
|
32
|
+
observers: Dict[Any, List[ObserverCallback]]
|
|
33
|
+
|
|
34
|
+
def __init__(self) -> None:
|
|
35
|
+
super().__init__()
|
|
36
|
+
self.observers = {}
|
|
37
|
+
self.lock = threading.Lock()
|
|
38
|
+
|
|
39
|
+
def subscribe_key(self, key, callback: ObserverCallback):
|
|
40
|
+
if key not in self.observers:
|
|
41
|
+
with self.lock:
|
|
42
|
+
if key not in self.observers:
|
|
43
|
+
self.observers[key] = []
|
|
44
|
+
self.observers[key].append(callback)
|
|
45
|
+
if self.observers[key].count(callback) > 1:
|
|
46
|
+
warn("Callback already subscribed")
|
|
47
|
+
|
|
48
|
+
def unsubscribe():
|
|
49
|
+
self.observers[key].remove(callback)
|
|
50
|
+
|
|
51
|
+
return unsubscribe
|
|
52
|
+
|
|
53
|
+
def trigger_key(self, key):
|
|
54
|
+
for callback in self.observers[key]:
|
|
55
|
+
callback(key, self[key])
|
|
File without changes
|