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.
- 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 +765 -0
- solara/_stores.py +297 -0
- solara/alias.py +6 -0
- solara/autorouting.py +555 -0
- solara/cache.py +305 -0
- solara/checks.html +71 -0
- solara/checks.py +227 -0
- solara/comm.py +28 -0
- solara/components/__init__.py +77 -0
- solara/components/alert.py +155 -0
- solara/components/applayout.py +397 -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 +134 -0
- solara/components/cross_filter.py +335 -0
- solara/components/dataframe.py +546 -0
- solara/components/datatable.py +214 -0
- solara/components/datatable.vue +175 -0
- solara/components/details.py +56 -0
- solara/components/download.vue +35 -0
- solara/components/echarts.py +86 -0
- solara/components/echarts.vue +139 -0
- solara/components/figure_altair.py +39 -0
- solara/components/file_browser.py +181 -0
- solara/components/file_download.py +199 -0
- solara/components/file_drop.py +159 -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 +456 -0
- solara/components/input_text_area.py +86 -0
- solara/components/link.py +55 -0
- solara/components/markdown.py +441 -0
- solara/components/markdown_editor.py +33 -0
- solara/components/markdown_editor.vue +359 -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 +45 -0
- solara/components/sql_code.py +41 -0
- solara/components/sql_code.vue +125 -0
- solara/components/style.py +105 -0
- solara/components/switch.py +71 -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/core.py +42 -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 +151 -0
- solara/hooks/use_thread.py +129 -0
- solara/kitchensink.py +8 -0
- solara/lab/__init__.py +34 -0
- solara/lab/components/__init__.py +7 -0
- solara/lab/components/chat.py +215 -0
- solara/lab/components/confirmation_dialog.py +163 -0
- solara/lab/components/cross_filter.py +7 -0
- solara/lab/components/input_date.py +339 -0
- solara/lab/components/input_time.py +133 -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 +2 -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 +165 -0
- solara/lab/utils/headers.py +5 -0
- solara/layout.py +44 -0
- solara/lifecycle.py +46 -0
- solara/minisettings.py +141 -0
- solara/py.typed +0 -0
- solara/reactive.py +99 -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 +527 -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 +1681 -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 +91 -0
- solara/server/esm.py +71 -0
- solara/server/fastapi.py +5 -0
- solara/server/flask.py +297 -0
- solara/server/jupyter/__init__.py +2 -0
- solara/server/jupyter/cdn_handler.py +28 -0
- solara/server/jupyter/server_extension.py +40 -0
- solara/server/jupyter/solara.py +91 -0
- solara/server/jupytertools.py +46 -0
- solara/server/kernel.py +388 -0
- solara/server/kernel_context.py +467 -0
- solara/server/patch.py +564 -0
- solara/server/pyinstaller/__init__.py +9 -0
- solara/server/pyinstaller/hook-ipyreact.py +5 -0
- solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
- solara/server/pyinstaller/hook-solara.py +9 -0
- solara/server/qt.py +113 -0
- solara/server/reload.py +251 -0
- solara/server/server.py +484 -0
- solara/server/settings.py +249 -0
- solara/server/shell.py +269 -0
- solara/server/starlette.py +770 -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 +272 -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 +486 -0
- solara/server/threaded.py +84 -0
- solara/server/utils.py +44 -0
- solara/server/websocket.py +45 -0
- solara/settings.py +86 -0
- solara/tasks.py +893 -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 +783 -0
- solara/toestand.py +998 -0
- solara/util.py +348 -0
- solara/validate_hooks.py +258 -0
- solara/website/__init__.py +0 -0
- solara/website/assets/custom.css +444 -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.py +6 -0
- solara/website/components/algolia.vue +24 -0
- solara/website/components/algolia_api.vue +202 -0
- solara/website/components/breadcrumbs.py +28 -0
- solara/website/components/contact.py +144 -0
- solara/website/components/docs.py +143 -0
- solara/website/components/header.py +75 -0
- solara/website/components/mailchimp.py +12 -0
- solara/website/components/mailchimp.vue +47 -0
- solara/website/components/markdown.py +99 -0
- solara/website/components/markdown_nav.vue +34 -0
- solara/website/components/notebook.py +171 -0
- solara/website/components/sidebar.py +105 -0
- solara/website/pages/__init__.py +370 -0
- solara/website/pages/about/__init__.py +9 -0
- solara/website/pages/about/about.md +3 -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/careers/__init__.py +27 -0
- solara/website/pages/changelog/__init__.py +10 -0
- solara/website/pages/changelog/changelog.md +372 -0
- solara/website/pages/contact/__init__.py +34 -0
- solara/website/pages/doc_use_download.py +85 -0
- solara/website/pages/documentation/__init__.py +90 -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 +417 -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 +50 -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 +72 -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 +192 -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 +256 -0
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +108 -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 +7 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +187 -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 +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +20 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +20 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +20 -0
- solara/website/pages/documentation/api/hooks/__init__.py +9 -0
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +23 -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 +31 -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 +30 -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 +66 -0
- solara/website/pages/documentation/api/hooks/use_thread.md +64 -0
- solara/website/pages/documentation/api/hooks/use_thread.py +42 -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 +29 -0
- solara/website/pages/documentation/api/routing/use_route.py +76 -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 +44 -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 +25 -0
- solara/website/pages/documentation/components/advanced/meta.py +17 -0
- solara/website/pages/documentation/components/advanced/style.py +43 -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 +30 -0
- solara/website/pages/documentation/components/input/file_drop.py +76 -0
- solara/website/pages/documentation/components/input/input.py +43 -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/input_time.py +15 -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 +74 -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 +66 -0
- solara/website/pages/documentation/components/layout/details.py +13 -0
- solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
- solara/website/pages/documentation/components/layout/gridfixed.py +19 -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 +19 -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 +83 -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 +15 -0
- solara/website/pages/documentation/components/page/title.py +25 -0
- solara/website/pages/documentation/components/status/__init__.py +9 -0
- solara/website/pages/documentation/components/status/error.py +39 -0
- solara/website/pages/documentation/components/status/info.py +39 -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 +77 -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 +54 -0
- solara/website/pages/documentation/examples/ai/__init__.py +11 -0
- solara/website/pages/documentation/examples/ai/chatbot.py +113 -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 +32 -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 +65 -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 +62 -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 +67 -0
- solara/website/pages/documentation/examples/visualization/linked_views.py +81 -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 +112 -0
- solara/website/pages/documentation/getting_started/__init__.py +9 -0
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +107 -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 +65 -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 +1021 -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 +228 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +278 -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 +305 -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/home.vue +1199 -0
- solara/website/pages/our_team/__init__.py +83 -0
- solara/website/pages/pricing/__init__.py +31 -0
- solara/website/pages/roadmap/__init__.py +11 -0
- solara/website/pages/roadmap/roadmap.md +47 -0
- solara/website/pages/scale_ipywidgets.py +45 -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 +107 -0
- solara/widgets/vue/html.vue +4 -0
- solara/widgets/vue/navigator.vue +134 -0
- solara/widgets/vue/vegalite.vue +130 -0
- solara/widgets/widgets.py +74 -0
- solara_ui-1.45.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- solara_ui-1.45.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara_ui-1.45.0.dist-info/METADATA +162 -0
- solara_ui-1.45.0.dist-info/RECORD +464 -0
- solara_ui-1.45.0.dist-info/WHEEL +4 -0
- solara_ui-1.45.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Using static files and resources in your Solara application
|
|
3
|
+
description: When using Solara, you can host static files, like images, which will then be available at /static/public, in the ../public folder.
|
|
4
|
+
---
|
|
5
|
+
# Static files
|
|
6
|
+
|
|
7
|
+
Files located on your local filesystem at the `../public` directory will be served by the Solara server at `/static/public`. A typical directory layout looks like this:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
├── pages
|
|
11
|
+
│ ├── 01-landing-page.md
|
|
12
|
+
│ ├── 02-some_app.py
|
|
13
|
+
└── public
|
|
14
|
+
└── beach.jpeg
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For instance, on this server, the `beach.jpeg` file will be available at `/static/public/beach.jpeg` and the full URL will be [`https://solara.dev/static/public/beach.jpeg`](https://solara.dev/static/public/beach.jpeg)
|
|
18
|
+
|
|
19
|
+
Putting the `public` directory 1 level higher than the `pages` directory avoids name collision with pages.
|
|
20
|
+
|
|
21
|
+
```solara
|
|
22
|
+
import solara
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@solara.component
|
|
26
|
+
def Page():
|
|
27
|
+
image_url = "/static/public/beach.jpeg"
|
|
28
|
+
with solara.Card(title="The following image is served from the ../public directory"):
|
|
29
|
+
solara.Image(image_url)
|
|
30
|
+
|
|
31
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Incorporating your assets, styles, and logos into your app
|
|
3
|
+
description: Solara looks for overrides of certain style and asset files in the assets folder by default. You can use these to incorporate your branding into your dashboard or app.
|
|
4
|
+
---
|
|
5
|
+
# Assets files
|
|
6
|
+
|
|
7
|
+
Asset files are special files with are loaded by Solara-server and thus have a special meaning, and come with defaults. Current supported assets files are:
|
|
8
|
+
|
|
9
|
+
* `favicon.png` and/or `favicon.svg` - Image shown by the browser (usually in the tab). If SVG is not provided, default `favicon.svg` of the solara server may override your custom favicon.png depending on the browser. Providing both PNG and SVG versions is recommended.
|
|
10
|
+
* `style.css` - Default `CSS` used by Solara.
|
|
11
|
+
* `custom.css` - Custom `CSS` you can override for your project (empty `CSS` file by default).
|
|
12
|
+
* `custom.js` - Custom Javascript you can use for your project (empty Javascript file by default).
|
|
13
|
+
* `theme.js` - Javascript file containing the definitions for [vuetify themes](https://v2.vuetifyjs.com/en/features/theme/) ([example theme.js file](https://github.com/widgetti/solara/blob/master/solara/website/assets/theme.js)).
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Assets files can be overridden by putting a file in the `../assets` directory. A typical directory layout looks like this:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
├── pages
|
|
20
|
+
│ ├── 01-landing-page.md
|
|
21
|
+
│ ├── 02-some_app.py
|
|
22
|
+
└── public
|
|
23
|
+
└── beach.jpeg
|
|
24
|
+
└── assets
|
|
25
|
+
├── custom.css
|
|
26
|
+
├── custom.js
|
|
27
|
+
├── theme.js
|
|
28
|
+
└── favicon.png
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
All assets files are served under `/static/assets/<filename>`, but how the assets go to the browser is considered an implementation detail (we could bundle/minimize the css for instance).
|
|
32
|
+
|
|
33
|
+
Putting the `assets` directory 1 level higher than the `pages` directory avoids name collision with pages.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Although the `assets` directory can be used for serving arbitrary files, we recommend using the [static files](/documentation/advanced/reference/static-files) directory instead, to avoid name collisions.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## Extra asset locations
|
|
40
|
+
|
|
41
|
+
If for instance you are creating a library on top of Solara, you might want to have your own assets files, like stylesheets or JavaScript files.
|
|
42
|
+
For this purpose, solara-server can be configured to look into other directories for assets files by setting the `SOLARA_ASSETS_EXTRA_LOCATIONS` environment variable.
|
|
43
|
+
This string contains a comma-separated list of directories or Python package names to look for asset files. The directories are searched in order, after looking in the application specific directory, and the first file found is used.
|
|
44
|
+
|
|
45
|
+
For example, if we run solara as:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
$ export SOLARA_ASSETS_EXTRA_LOCATIONS=/path/to/assets,my_package.assets
|
|
49
|
+
$ solara run solara.website.pages
|
|
50
|
+
Solara server is starting at http://localhost:8765...
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
And we would fetch `http://localhost:8765/static/assets/my-image.jpg`, Solara-server would look for the file in the following order:
|
|
54
|
+
|
|
55
|
+
1. `.../solara/website/assets/my-image.jpg`
|
|
56
|
+
1. `/path/to/assets/my-image.jpg`
|
|
57
|
+
1. `.../my_package/assets/my-image.jpg`
|
|
58
|
+
1. `...site-package/solara/server/assets/my-image.jpg`
|
|
59
|
+
|
|
60
|
+
## Recommended pattern for libraries to add asset locations
|
|
61
|
+
|
|
62
|
+
If you are creating a library on top of Solara, and you want to programmatically add asset locations, you can do so by adding the following code to your library:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import solara.server.settings
|
|
66
|
+
import my_package.assets
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
path = my_package.assets.__path__[0]
|
|
70
|
+
# append at the end, so SOLARA_ASSETS_EXTRA_LOCATIONS can override
|
|
71
|
+
solara.server.settings.assets.extra_locations.append(path)
|
|
72
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Generating a static site version of your app or dashboard
|
|
3
|
+
description: Solara's static site generation (SSG) feature allows you to pre-render HTML for your app or dashboard, improving the user experience by providing quick page loads.
|
|
4
|
+
---
|
|
5
|
+
## Static Site Generation
|
|
6
|
+
## Introduction
|
|
7
|
+
Solara's static site generation (SSG) feature allows you to pre-render HTML for your website, improving the user experience by providing quick page loads. When a user requests a page, the pre-rendered HTML is served directly to the user. After the page is displayed, the Solara server will connect and take over rendering to make the page interactive.
|
|
8
|
+
|
|
9
|
+
Using SSG is mostly useful when the content of your website is the same for all users. This is the case for this page (the Solara page itself).
|
|
10
|
+
|
|
11
|
+
## Benefits of SSG
|
|
12
|
+
Another benefit of using SSG is improved search engine optimization (SEO). By allowing web crawlers to index your pages, you can improve the visibility of your website in search engine results.
|
|
13
|
+
|
|
14
|
+
In addition to improving SEO, using SSG can also help with indexing your pages and making them more easily discoverable by users.
|
|
15
|
+
|
|
16
|
+
## Using Solara's SSG feature.
|
|
17
|
+
|
|
18
|
+
### Requirements
|
|
19
|
+
|
|
20
|
+
Using SSR requires installation of [Playwright for Python](https://playwright.dev/python/). Follow their [installation instructions](https://playwright.dev/python/docs/library) or simply execute:
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
$ pip solara-enterprise[ssg]
|
|
25
|
+
$ playwright install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Pre-deployment
|
|
29
|
+
|
|
30
|
+
Using the command
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
$ solara ssg your.awesome.app
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Will run the solara server and use playwright to fetch all known pages and save them to the `../build` directory. Solara knows about your pages because of its [routing support](/documentation/advanced/understanding/routing).
|
|
37
|
+
|
|
38
|
+
All HTML files in the `../build` will be used to pre-populate the HTML served to the user.
|
|
39
|
+
|
|
40
|
+
### During deployment
|
|
41
|
+
|
|
42
|
+
For fast and simpler deployment, you can also add the `--ssg` flag to the `solara run` command, e.g.:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
$ solara run our.awesome.app --ssg
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This will start you server immediately, and start a thread in the background that will fetch the known pages and put the in the `../build` directory, similar to the [pre-deployment](#pre-deployment) procedure.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
The downsides of this method, is that users or crawlers may request a page when SSR is not done yet, leading to a slower page load or missing content for the crawler.
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
### Environment variables
|
|
56
|
+
|
|
57
|
+
* `SOLARA_SSG_BUILD_PATH`: Override the directory where there html pages are stored.
|
|
58
|
+
* `SOLARA_SSG_ENABLED`: Alternative to passing the `--ssg` flag. Should be used when running solara without `solara run` (e.g. using gunicorn/uvicorn).
|
|
59
|
+
* `SOLARA_SSG_HEADED`: Run playwright using `headed` mode (in contrast to `headless`). Useful for debugging.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Incorporating search into your Solara application
|
|
3
|
+
description: If you are using static site generation (SSG) in your Solara application, you can make use of our search feature for it too!
|
|
4
|
+
---
|
|
5
|
+
# Search
|
|
6
|
+
|
|
7
|
+
Solara can provide search, if [SSG](/documentation/advanced/reference/static-site-generation) is enabled. This allows you to add a search box to you website, which performs a full-text search to provide quick access to pages. The solara website itself uses the
|
|
8
|
+
search feature as well in the toolbar.
|
|
9
|
+
|
|
10
|
+
## Using Solara's Search feature.
|
|
11
|
+
|
|
12
|
+
By running `solara run myapp.pages --ssg --search` solara will fetch all your pages, and build up a search index afterards. This option can also be abled using the environment variable `SOLARA_SEARCH_ENABLED=True`.
|
|
13
|
+
|
|
14
|
+
You can import as use the Search component as follow:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
import solara
|
|
18
|
+
from solara_enterprise.search.search import Search
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@solara.component
|
|
22
|
+
def Page():
|
|
23
|
+
with MyToolbar():
|
|
24
|
+
...
|
|
25
|
+
Search()
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
This feature requires `solara-enterprise`, which can be installed as follows:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pip install solara-enterprise
|
|
34
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Automatic reloading of source files when developing with Solara
|
|
3
|
+
description: Solara automatically detects changes in certain source file types, and hot reloads your application when you save them.
|
|
4
|
+
---
|
|
5
|
+
# Reloading
|
|
6
|
+
|
|
7
|
+
## Reloading of Python files
|
|
8
|
+
|
|
9
|
+
Solara will auto detect if your script or the sourcecode of an imported module has changes. If so, Solara will reload the page.
|
|
10
|
+
|
|
11
|
+
(*Note: Upgrade to solara 1.14.0 for a fix in hot reloading using `pip install "solara>=1.14.0"`*)
|
|
12
|
+
|
|
13
|
+
## Reloading of .vue files
|
|
14
|
+
|
|
15
|
+
The solara server automatically watches all `.vue` files that are used by vue templates (there are some used in solara.components for example).
|
|
16
|
+
When a `.vue` file is saved, the widgets get updated automatically, without needing a page reload, aiding rapid development.
|
|
17
|
+
|
|
18
|
+
## Reloading of .vue files
|
|
19
|
+
|
|
20
|
+
The [Style component](/documentation/components/advanced/style) accepts a Path as argument, when that is used and the server is in development mode (the default), also
|
|
21
|
+
CSS files will be hot reloaded.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Restarting the server after changes to the solara packages
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
You don't need to care about this feature if you only use solara, this is only relevant for development on solara itself, [see also development instructions](/documentation/advanced/development/setup).
|
|
28
|
+
|
|
29
|
+
If the `--auto-restart/-a` flag is passed to solara-server and any changes occur in the `solara` package (excluding `solara.webpage`), solara-server will restart. This speeds up development on `solara-server` for developers since you do not
|
|
30
|
+
need to manually restart the server in the terminal.
|
|
31
|
+
|
|
32
|
+
## Disabling reloading
|
|
33
|
+
|
|
34
|
+
In production mode (pass the `--production` argument to `solara run`) watching of files is disabled, and no reloading of files or vue templates will occur. If you run solara integrated in flask or uvicorn as laid out in [deployment documentation](https://solara.dev/documentation/getting_started/deploying/self-hosted)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Using Solara within notebooks
|
|
3
|
+
description: Solara can be used to generate an interactive app directly using your notebook file by running just one command.
|
|
4
|
+
---
|
|
5
|
+
# Notebook support
|
|
6
|
+
|
|
7
|
+
We also support notebooks, simply assign to the `Page` variable in a code cell, save your notebook, and run `$ solara run myapp.ipynb`. If you widget or component is called differently, run like `$ solara run myapp.ipynb:myobject.nested_widget`.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Caching resources for your solara application or dashboard
|
|
3
|
+
description: Solara has a dict-like object at `solara.cache.storage` that can be used to store objects in under a key. So we can use this global
|
|
4
|
+
object as normal dict.
|
|
5
|
+
---
|
|
6
|
+
# Caching
|
|
7
|
+
|
|
8
|
+
Solara has a dict-like object at `solara.cache.storage` that can be used to store objects in under a key. So we can use this global
|
|
9
|
+
object as normal dict, e.g.:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import solara
|
|
13
|
+
solara.cache.storage["my-key"] = expensive_function_call()
|
|
14
|
+
assert "my-key" in solara.cache.storage
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Note that at any time later on, the key may be removed from this object, as a cache always has a limited capacity.
|
|
18
|
+
|
|
19
|
+
The `solara.cache.storage` cache object is used by [memoize](/documentation/api/utilities/memoize), if no storage argument is passed to this decorator.
|
|
20
|
+
|
|
21
|
+
## Types of cache
|
|
22
|
+
|
|
23
|
+
Solara core comes by default with an in-memory cache using a [LRU](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) (Least recently used) strategy. When the
|
|
24
|
+
cache becomes too full, this removes entries used least recently.
|
|
25
|
+
|
|
26
|
+
The cache is set by default to:
|
|
27
|
+
```python
|
|
28
|
+
solara.cache.storage = solara.cache.Memory(maxsize=128)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Which will remove the least recently used element when the 129th item is added.
|
|
32
|
+
|
|
33
|
+
The memory cache is also configurable using environment variable:
|
|
34
|
+
```
|
|
35
|
+
$ export SOLARA_CACHE=memory # already the default
|
|
36
|
+
$ export SOLARA_CACHE_MEMORY_MAX_ITEMS=128 # already the default
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Custom caches
|
|
40
|
+
An infinite cache can be set using:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
solara.cache.storage = {} # a regular dict
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The [cachetools](https://cachetools.readthedocs.io/) project has some caching types that behave like a Python dict, and are compatible with Solara, e.g.:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import cachetools
|
|
50
|
+
import solara
|
|
51
|
+
solara.cache.storage = cachetools.FIFOCache(maxsize=100)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Solara-enterprise
|
|
55
|
+
|
|
56
|
+
With solara-enterprise, we have more cache storage options.
|
|
57
|
+
|
|
58
|
+
### Memory (byte size based)
|
|
59
|
+
|
|
60
|
+
The cache will limit the total number of bytes to a set maximum, instead of the number of items as is with the normal 'memory' cache.
|
|
61
|
+
|
|
62
|
+
This can be set using code:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import solara
|
|
66
|
+
solara.cache.configure("memory-size")
|
|
67
|
+
# or more explicit
|
|
68
|
+
import solara_enterprise.cache.memory_size
|
|
69
|
+
solara.cache.storage = solara_enterprise.cache.memory_size.MemorySize(
|
|
70
|
+
max_size="1GB" # already the default
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The 'memory-size' cache can also be configured using environment variables:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
$ export SOLARA_CACHE=memory-size
|
|
78
|
+
$ export SOLARA_CACHE_MEMORY_MAX_SIZE=1GB # already the default
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### Disk cache
|
|
84
|
+
|
|
85
|
+
This cache will persist the entries to disk, allowing multiple processes to share the same data. This cache type is ideal when using multiple workers on a single node.
|
|
86
|
+
|
|
87
|
+
This can be set using code:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import solara
|
|
91
|
+
solara.cache.configure("disk")
|
|
92
|
+
# or more explicit
|
|
93
|
+
import solara_enterprise.cache.disk
|
|
94
|
+
solara.cache.storage = solara_enterprise.cache.disk.Disk(
|
|
95
|
+
max_size="10GB", path="/home/maarten/.solara/cache" # already the default
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or configurable using environment variable:
|
|
100
|
+
```
|
|
101
|
+
$ export SOLARA_CACHE=disk
|
|
102
|
+
$ export SOLARA_CACHE_DISK_MAX_SIZE=10GB # already the default
|
|
103
|
+
$ export SOLARA_CACHE_PATH_=/home/maarten/.solara/cache # already the default
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Redis cache
|
|
107
|
+
|
|
108
|
+
This cache will store the entries in a [Redis](https://redis.io/) server, allowing multiple nodes to share the same data. This is ideal in a cluster/distributed configuration.
|
|
109
|
+
|
|
110
|
+
This can be set using code:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import solara
|
|
114
|
+
solara.cache.configure("redis")
|
|
115
|
+
# or more explicit
|
|
116
|
+
import solara_enterprise.cache.redis
|
|
117
|
+
# optionally pass in a redis.Client object
|
|
118
|
+
solara.cache.storage = solara_enterprise.cache.redis.Redis()
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Or configured using environment variable:
|
|
122
|
+
```
|
|
123
|
+
$ export SOLARA_CACHE=redis
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Multi-level cache
|
|
127
|
+
|
|
128
|
+
We can chain a few caches to get a multilevel cache. This allows us to get the benefits of the low latency memory cache while sharing it with other workers and nodes.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import solara
|
|
132
|
+
solara.cache.configure("memory,disk,redis")
|
|
133
|
+
# or more explicit
|
|
134
|
+
import solara_enterprise.cache.multi_level
|
|
135
|
+
import solara_enterprise.cache.disk
|
|
136
|
+
import solara_enterprise.cache.redis
|
|
137
|
+
l1 = solara.cache.Memory()
|
|
138
|
+
l2 = solara_enterprise.cache.disk.Disk()
|
|
139
|
+
l3 = solara_enterprise.cache.redis.Redis()
|
|
140
|
+
solara.cache.storage = solara_enterprise.cache.multi_level.MultiLevel(
|
|
141
|
+
l1, l2, l3
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Or configured using an environment variable:
|
|
146
|
+
```
|
|
147
|
+
$ export SOLARA_CACHE="memory,disk,redis"
|
|
148
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding Solara's functionality
|
|
3
|
+
description: Solara builds on existing technologies. If you are new to Solara or some of the underlying technologies, you may feel lost at times.
|
|
4
|
+
These 'understanding' guides are meant to help you understand topics at a deeper level and how they connect to Solara.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Introduction
|
|
8
|
+
|
|
9
|
+
Solara builds on existing technologies. If you are new to Solara or some of the underlying technologies, you may feel lost at times.
|
|
10
|
+
These 'understanding' guides are meant to help you understand topics at a deeper level and how they connect to Solara.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding how ipywidgets work together with Solara
|
|
3
|
+
description: Solara's primarily standalone app approach differs from the ipywidgets one. This article dives deeper into the different approaches and adapting to using
|
|
4
|
+
ipywidgets within Solara.
|
|
5
|
+
---
|
|
6
|
+
# IPywidgets
|
|
7
|
+
|
|
8
|
+
* [Documentation](https://ipywidgets.readthedocs.io/en/stable/)
|
|
9
|
+
* [GitHub](https://github.com/jupyter-widgets/ipywidgets)
|
|
10
|
+
|
|
11
|
+
IPywidgets is a Python library for creating UI objects that live in the Python side *and* on the browser side. They provide bi-directional communication, meaning you can change a slider in the browser, or from the Python side. `IPywidgets` takes care of communication and synchronization.
|
|
12
|
+
|
|
13
|
+
With ipywidgets you get access to the browser without writing a single line of JavaScript or CSS.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Solara and ipywidgets
|
|
17
|
+
|
|
18
|
+
Solara can use almost all existing ipywidgets, from the core library that provides sliders, to [ipyvuetify](./ipyvuetify) which gives us rich UI elements, to ipyvolume that gives us interactive 3d visualizations.
|
|
19
|
+
|
|
20
|
+
## Where do ipywidgets work?
|
|
21
|
+
|
|
22
|
+
There are various places where ipywidgets work, and [Solara server](./solara-server) is one of these. There is a [list of frontends that support](https://github.com/jupyter/jupyter/wiki/Jupyter-Widgets#frontends-that-support-jupyter-widgets) meaning that you ipywidgets based applications run
|
|
23
|
+
on many places (From Jupyter Notebook, Jupyter Lab, Google Colab to even VS Code).
|
|
24
|
+
|
|
25
|
+
## Which ipywidget libraries exist?
|
|
26
|
+
|
|
27
|
+
There is a list [of ipywidget libraries](https://github.com/jupyter/jupyter/wiki/Jupyter-Widgets#custom-jupyter-widgets), but that are probably
|
|
28
|
+
many more.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Do all ipywidget libraries work with Solara server?
|
|
32
|
+
|
|
33
|
+
All these libraries should work with [Solara server](./solara-server), but we have not tested all of them. If you use a regular ipywidget based app, you should not run into issues. If you do, consider [opening a GitHub issue](https://github.com/widgetti/solara/issues/new)
|
|
34
|
+
|
|
35
|
+
If you write a Reacton-based Solara application, check out [the reacton page](./reacton).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Using ipyvuetify widgets with Solara
|
|
3
|
+
description: Ipyvuetify is an ipywidgets based library that wraps the Vuetify javascript framework for use with python widgets. Learn how to use these to build apps with Solara.
|
|
4
|
+
---
|
|
5
|
+
# ipyvuetify
|
|
6
|
+
|
|
7
|
+
* [Documentation](https://ipyvuetify.readthedocs.io/)
|
|
8
|
+
* [GitHub](https://github.com/widgetti/ipyvuetify)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
ipyvuetify is an [ipywidget based](./ipywidgets) library, that wraps the [Vuetify component library](https://v2.vuetifyjs.com/) to give beautiful
|
|
12
|
+
material design based widgets.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## Reacton and ipyvuetify
|
|
17
|
+
|
|
18
|
+
We consider ipyvuetify one of the most essential ipywidget libraries, and that is the reason why [Reacton](/documentation/advanced/understanding/reacton) ships with
|
|
19
|
+
generated ipyvuetify components to make your app type safe.
|
|
20
|
+
|
|
21
|
+
```solara
|
|
22
|
+
|
|
23
|
+
import solara
|
|
24
|
+
# rv is the reacton-ipyvuetify wrapper for Reacton/Solara
|
|
25
|
+
import reacton.ipyvuetify as rv
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@solara.component
|
|
29
|
+
def Page():
|
|
30
|
+
clicks, set_clicks = solara.use_state(0)
|
|
31
|
+
def my_click_handler(*ignore_args):
|
|
32
|
+
# trigger a new render with a new value for clicks
|
|
33
|
+
set_clicks(clicks+1)
|
|
34
|
+
button = rv.Btn(children=[f"Clicked {clicks} times"])
|
|
35
|
+
rv.use_event(button, 'click', my_click_handler)
|
|
36
|
+
return button
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Solara and ipyvuetify
|
|
41
|
+
|
|
42
|
+
Many of the Solara components are based on ipyvuetify. Do not hesitate the look at the [source code of the Solara components](https://github.com/widgetti/solara/tree/master/solara/components) to learn how to create your own components.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding how Solara builds on Reacton
|
|
3
|
+
description: Solara adapts the React way of using components declaratively to build UIs and brings it to Python.
|
|
4
|
+
---
|
|
5
|
+
# Reacton
|
|
6
|
+
|
|
7
|
+
* [Documentation](https://reacton.solara.dev/)
|
|
8
|
+
* [GitHub](https://github.com/widgetti/reacton/)
|
|
9
|
+
|
|
10
|
+
Reacton is a React-like layer around ipywidgets.
|
|
11
|
+
|
|
12
|
+
Using a declarative way, in a React (JS) style, makes your codebase smaller, less error-prone, and easier to reason about. We don't see a good reason not to use it.
|
|
13
|
+
|
|
14
|
+
Also, React has proven itself, and by adopting a proven technology, we can stand on the shoulders of giants, make use of a lot of existing resources, and do not have to reinvent the wheel.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Solara or Reacton?
|
|
18
|
+
|
|
19
|
+
We consider Solara a superset of Reacton, and that's why the full namespace of the `reacton` package is imported into the `solara` package.
|
|
20
|
+
Therefore, you can write `solara.use_state` or `reacton.use_state`, they are the same function.
|
|
21
|
+
|
|
22
|
+
The reason for this is simplicity for newcomers, who don't care about the difference between `solara` and `reacton`.
|
|
23
|
+
But in practice, it also saves having to import both `solara` and `reacton`.
|
|
24
|
+
Also, when writing Solara based apps, one does not think about Reacton anymore, it is all Solara.
|
|
25
|
+
|
|
26
|
+
## How do I use Reacton or Solara with ipywidget library X
|
|
27
|
+
|
|
28
|
+
[The reacton documentation has a page on this](https://reacton.solara.dev/en/latest/libraries/)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding the basics of Reacton
|
|
3
|
+
description: Using your favorite component, we try to understand better how it works to improve your understanding of Reacton and, thus, how to use Solara.
|
|
4
|
+
---
|
|
5
|
+
# Reacton basic understanding
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Let us take our favorite component, and try to understand a bit better how it works to improve your understanding of Reacton and thus how to use Solara.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
```solara
|
|
12
|
+
import solara
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@solara.component
|
|
16
|
+
def ClickButton():
|
|
17
|
+
clicks, set_clicks = solara.use_state(0)
|
|
18
|
+
|
|
19
|
+
def my_click_hander():
|
|
20
|
+
set_clicks(clicks + 1)
|
|
21
|
+
|
|
22
|
+
return solara.Button(label=f"Clicked: {clicks}", on_click=my_click_hander)
|
|
23
|
+
|
|
24
|
+
Page = ClickButton
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This example does a few things:
|
|
28
|
+
|
|
29
|
+
* Add state (`clicks`) to the component.
|
|
30
|
+
* Create a callback function (`my_click_handler`). When executed, it will increase ask Solara/Reacton to increase the `clicks` value on the next render, by calling `set_clicks`.
|
|
31
|
+
* Pass the callback function to the child component (`Button`).
|
|
32
|
+
* Set the `label` value on each render.
|
|
33
|
+
|
|
34
|
+
Now if a user clicks the button:
|
|
35
|
+
|
|
36
|
+
* The `my_click_hander` callback will be called by Solara/Reacton.
|
|
37
|
+
* Your code (the body of `my_click_hander`) will be executed and will ask Reacton to change the state of `clicks` by increasing the value by 1.
|
|
38
|
+
* Solara/Reacton got asked to change the of `clicks`, and will execute your render function (the body of the `ClickButton` component) once.
|
|
39
|
+
* Solara/Reacton will compare the return value of your component and will update the associated widget. In this case it will update the label to `"`Clicked: 1"`.
|
|
40
|
+
|
|
41
|
+
This pattern is very common, where a parent component (ClickButton) managed the state (the number of times clicked), and state changes (increasing the clicks by 1 on a button click).
|
|
42
|
+
|
|
43
|
+
## Graphically
|
|
44
|
+
|
|
45
|
+
Is the above text a bit dry? Maybe the annotated code will make it easier to understand for you.
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## Going deeper
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
Still not satisfied? Let's go through all the steps in more detail in this sequence diagram:
|
|
54
|
+
|
|
55
|
+
```mermaid
|
|
56
|
+
sequenceDiagram
|
|
57
|
+
actor You
|
|
58
|
+
participant Frontend as Frontend
|
|
59
|
+
participant ipywidgets as IPyWidgets
|
|
60
|
+
participant react as Reacton
|
|
61
|
+
participant component as ButtonClick
|
|
62
|
+
participant app as Solara
|
|
63
|
+
|
|
64
|
+
app->>component: el=ButtonClick()
|
|
65
|
+
app->>react: render(el)
|
|
66
|
+
|
|
67
|
+
activate react
|
|
68
|
+
react->>component: render()
|
|
69
|
+
component->>react: use_state(0)<br>(returns 0)
|
|
70
|
+
|
|
71
|
+
react->>react: reconsolidate()
|
|
72
|
+
react->>ipywidgets: create Button<br>description="Clicked: 0"
|
|
73
|
+
deactivate react
|
|
74
|
+
ipywidgets--)Frontend: create Button view
|
|
75
|
+
|
|
76
|
+
You->>Frontend: clicks button
|
|
77
|
+
|
|
78
|
+
Frontend--)ipywidgets: Button clicked
|
|
79
|
+
ipywidgets->>component: on_click
|
|
80
|
+
activate component
|
|
81
|
+
component->>react: set_clicks(1)
|
|
82
|
+
activate react
|
|
83
|
+
deactivate component
|
|
84
|
+
react->>+component: render()
|
|
85
|
+
component->>-react: use_state(0)<br> (now returns 1)
|
|
86
|
+
react->>react: reconsolidate()
|
|
87
|
+
react->>ipywidgets: update Button<br>description="Clicked 1"
|
|
88
|
+
deactivate react
|
|
89
|
+
ipywidgets--)Frontend: update Button<br>description="Clicked 1"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
In words
|
|
93
|
+
|
|
94
|
+
1. Solara create `el = ButtonClick()` from your component.
|
|
95
|
+
1. The `display(el)` triggers the call to Reacton.
|
|
96
|
+
1. The render call enters the render phase, which will call the function body (which we call render function) of the `ButtonClick` component.
|
|
97
|
+
1. Our ButtonClick render function calls [`use_state`](/documentation/api/hooks/use_state). Because this is our first render phase, this returns the initial value (0).
|
|
98
|
+
1. The ButtonClick render function returns a Button element (not a widget!) with `description="Clicked: 0 times"`.
|
|
99
|
+
1. The Reacton render call is done with the render phase, and enters the reconciliation phase, where it looks at the difference between the real widgets and the virtual widgets tree (represented by the Reacton elements). We find there is no previous widget associated with the virtual widget (or element) and decide to create a widget.
|
|
100
|
+
1. Asynchronously via the Jupyter protocol, a widget model and view are created and displayed to the user in the browser.
|
|
101
|
+
1. The user clicks on the button.
|
|
102
|
+
1. The `on_click` handler gets triggered on the Python side, inside of the `ButtonClick` component (called `my_click_handler`).
|
|
103
|
+
1. `my_click_handler` handler calls `set_clicks(1)` which triggers a re-render.
|
|
104
|
+
1. The render call enters the render phase, which calls the render function of `ButtonClick` for the second time.
|
|
105
|
+
1. Our ButtonClick render function calls [`reacton.use_state`](#use_state). Because this is our second render phase, this returns the last set value, which is 1.
|
|
106
|
+
1. The ButtonClick render function returns a new Button element (not a widget!) with the description `"Clicked: 1 times"`.
|
|
107
|
+
1. The Reacton render call is done with the render phase, and enters the reconciliation phase, where it looks at the difference between the real widgets and the virtual widgets tree (represented by the Reacton elements). We find there is a widget associated with the virtual widget (or element) and decide to update the changed attributes of the widget and set `description` to `"Clicked: 1 times"`.
|
|
108
|
+
1. Asynchronously via the Jupyter protocol, the widet model and view are being updated in the browser.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The anatomy of Solara's functionality
|
|
3
|
+
description: Dive deep into how Solara uses the technologies it builds on.
|
|
4
|
+
---
|
|
5
|
+
# Anatomy
|
|
6
|
+
|
|
7
|
+
For communication, it is useful to speak the same language and use the same idiom.
|
|
8
|
+
As a reference, we provide this "anatomy" image of our favorite `ClickButton` component with a layout that we consider best practice.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
## Explanations
|
|
13
|
+
|
|
14
|
+
* Import `solara` and you also get the `reacton` namespace with it (saves typing, and finding/remembering which hooks is in which packages)
|
|
15
|
+
* Add a `@solara.component` decorator to turn your function into a component.
|
|
16
|
+
* Start with `use_state` hooks and other hooks. This avoids issues with [conditional hooks](/documentation/advanced/understanding/rules-of-hooks) or hooks in loops.
|
|
17
|
+
* Data/state flows down (to children)
|
|
18
|
+
* Information (events, data) flows up from children via events and callbacks (`on_<some_event_name>=my_callback`).
|
|
19
|
+
* If you need multiple components, use a [parent container component](/documentation/components/layout/app_layout) as context manager. A good default name to give this context manager is `main`. Don't forget to return it in your render function!
|
|
20
|
+
* The body of your component (the function you wrote) is called the render function.
|
|
21
|
+
* In between the hooks as defining all your elements, you put your custom code, like checking variables, defining callbacks, and other logic.
|
|
22
|
+
* The only way for a component to cause itself to rerender is to have state (using `use_state`) and change it (calling the second return value with a different value).
|
|
23
|
+
* Reacton is declarative. Your render function gets executed after every state change (and thus should be relatively cheap to execute). Reacton will find out the changes for you and will add, remove and update the associated widgets for you. This means you can easily do conditional rendering (creating an element in an if statement or in a loop).
|