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,67 @@
|
|
|
1
|
+
"""# Image annotation with Solara
|
|
2
|
+
|
|
3
|
+
This example displays how to annotate images with different drawing tools in plotly figures. Use the canvas
|
|
4
|
+
below to draw shapes and visualize the canvas callback.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Check [plotly docs](https://dash.plotly.com/annotations) for more information about image annotation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
import plotly.graph_objects as go
|
|
13
|
+
|
|
14
|
+
import solara
|
|
15
|
+
|
|
16
|
+
title = "Plotly Image Annotator"
|
|
17
|
+
shapes = solara.reactive(None)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CustomEncoder(json.JSONEncoder):
|
|
21
|
+
"""
|
|
22
|
+
Custom JSON encoder for Plotly objects.
|
|
23
|
+
|
|
24
|
+
Plotly may return objects that the standard JSON encoder can't handle. This
|
|
25
|
+
encoder converts such objects to str, allowing serialization by json.dumps
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def default(self, o):
|
|
29
|
+
if isinstance(o, object):
|
|
30
|
+
return str(o)
|
|
31
|
+
return super().default(o)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@solara.component
|
|
35
|
+
def Page():
|
|
36
|
+
def on_relayout(data):
|
|
37
|
+
if data is None:
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
relayout_data = data["relayout_data"]
|
|
41
|
+
|
|
42
|
+
if "shapes" in relayout_data:
|
|
43
|
+
shapes.value = relayout_data["shapes"]
|
|
44
|
+
|
|
45
|
+
fig = go.FigureWidget(
|
|
46
|
+
layout=go.Layout(
|
|
47
|
+
showlegend=False,
|
|
48
|
+
autosize=True,
|
|
49
|
+
dragmode="drawrect",
|
|
50
|
+
modebar={
|
|
51
|
+
"add": [
|
|
52
|
+
"drawclosedpath",
|
|
53
|
+
"drawcircle",
|
|
54
|
+
"drawrect",
|
|
55
|
+
"eraseshape",
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
solara.FigurePlotly(fig, on_relayout=on_relayout)
|
|
62
|
+
if not shapes.value:
|
|
63
|
+
solara.Markdown("## Draw on the canvas")
|
|
64
|
+
else:
|
|
65
|
+
solara.Markdown("## Data returned by drawing")
|
|
66
|
+
formatted_shapes = str(json.dumps(shapes.value, indent=2, cls=CustomEncoder))
|
|
67
|
+
solara.Preformatted(formatted_shapes)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""# Linked views
|
|
2
|
+
|
|
3
|
+
This example shows how to create linked views. The clicked row information is passed up to the parent component using an event,
|
|
4
|
+
and then passed down to both child components.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import dataclasses
|
|
9
|
+
from typing import Callable, cast
|
|
10
|
+
|
|
11
|
+
import plotly.express as px
|
|
12
|
+
|
|
13
|
+
import solara
|
|
14
|
+
|
|
15
|
+
df = px.data.iris()
|
|
16
|
+
columns = list(df.columns)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclasses.dataclass
|
|
20
|
+
class ClickPoint:
|
|
21
|
+
row_index: int
|
|
22
|
+
x_column: str
|
|
23
|
+
y_column: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def find_row_index(fig, click_data):
|
|
27
|
+
# goes from trace index and point index to row index in a dataframe
|
|
28
|
+
# requires passing df.index as to custom_data
|
|
29
|
+
trace_index = click_data["points"]["trace_indexes"][0]
|
|
30
|
+
point_index = click_data["points"]["point_indexes"][0]
|
|
31
|
+
trace = fig.data[trace_index]
|
|
32
|
+
return trace.customdata[point_index][0]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@solara.component
|
|
36
|
+
def ClickScatter(df, x, y, color, click_row, on_click: Callable[[ClickPoint], None]):
|
|
37
|
+
x, set_x = solara.use_state(x)
|
|
38
|
+
y, set_y = solara.use_state(y)
|
|
39
|
+
fig = px.scatter(df, x, y, color=color, custom_data=[df.index])
|
|
40
|
+
|
|
41
|
+
def on_click_trace(click_data):
|
|
42
|
+
# sanity checks
|
|
43
|
+
assert click_data["event_type"] == "plotly_click"
|
|
44
|
+
row_index = find_row_index(fig, click_data)
|
|
45
|
+
on_click(ClickPoint(row_index, x, y))
|
|
46
|
+
|
|
47
|
+
if click_row:
|
|
48
|
+
click_x = df[x].values[click_row]
|
|
49
|
+
click_y = df[y].values[click_row]
|
|
50
|
+
fig.add_trace(px.scatter(x=[click_x], y=[click_y], text=["⭐️"]).data[0])
|
|
51
|
+
# make the figure a bit smaller
|
|
52
|
+
fig.update_layout(width=340)
|
|
53
|
+
with solara.Column(style={"width": "340px"}) as main:
|
|
54
|
+
solara.FigurePlotly(fig, on_click=on_click_trace)
|
|
55
|
+
solara.Select(label="X-axis", value=x, values=columns, on_value=set_x)
|
|
56
|
+
solara.Select(label="Y-axis", value=y, values=columns, on_value=set_y)
|
|
57
|
+
return main
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@solara.component
|
|
61
|
+
def Page():
|
|
62
|
+
click_point, set_click_point = solara.use_state(cast(ClickPoint, None))
|
|
63
|
+
if click_point:
|
|
64
|
+
clicked_row = click_point.row_index
|
|
65
|
+
else:
|
|
66
|
+
clicked_row = None
|
|
67
|
+
|
|
68
|
+
with solara.Row(justify="center", style={"flex-wrap": "wrap"}):
|
|
69
|
+
ClickScatter(df, "sepal_length", "sepal_width", "species", clicked_row, on_click=set_click_point)
|
|
70
|
+
ClickScatter(df, "petal_length", "petal_width", "species", clicked_row, on_click=set_click_point)
|
|
71
|
+
if click_point is not None:
|
|
72
|
+
clicked_row = click_point.row_index
|
|
73
|
+
solara.Success(f"Clicked on row {clicked_row}. Which is highlighted in the both plots.")
|
|
74
|
+
solara.Markdown(
|
|
75
|
+
f"""
|
|
76
|
+
```python
|
|
77
|
+
row_data = {df.iloc[clicked_row].to_dict()}
|
|
78
|
+
```"""
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
solara.Info("Click to select a point")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""# Scatter plot using Plotly
|
|
2
|
+
|
|
3
|
+
This example shows how to use Plotly to create a scatter plot and a slider to do some filtering.
|
|
4
|
+
|
|
5
|
+
Inspired by the dash documentation.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Note
|
|
9
|
+
|
|
10
|
+
Solara supports plotly and plotly express. Create your figure (not a figure widget)
|
|
11
|
+
and pass it to the [FigurePlotly](/documentation/components/viz/plotly) component.
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import pandas as pd
|
|
16
|
+
import plotly.express as px
|
|
17
|
+
import solara
|
|
18
|
+
|
|
19
|
+
title = "Scatter plot using Plotly"
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv")
|
|
23
|
+
except Exception:
|
|
24
|
+
df = None
|
|
25
|
+
|
|
26
|
+
if df is not None:
|
|
27
|
+
year_min = df["year"].min()
|
|
28
|
+
year_max = df["year"].max()
|
|
29
|
+
years = df["year"].unique().tolist()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@solara.component
|
|
33
|
+
def Page():
|
|
34
|
+
with solara.Div() as main:
|
|
35
|
+
index = solara.ui_slider(value=0, min=0, max=len(years) - 1, tick_labels=years, key="year slider index")
|
|
36
|
+
selected_year = years[index]
|
|
37
|
+
|
|
38
|
+
filtered_df = df[df.year == selected_year].copy()
|
|
39
|
+
|
|
40
|
+
fig = px.scatter(filtered_df, x="gdpPercap", y="lifeExp", size="pop", color="continent", hover_name="country", log_x=True, size_max=55)
|
|
41
|
+
fig.update_layout(transition_duration=1500)
|
|
42
|
+
|
|
43
|
+
solara.FigurePlotly(fig, dependencies=[selected_year])
|
|
44
|
+
return main
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import solara
|
|
4
|
+
from solara.website.components.markdown import MarkdownWithMetadata
|
|
5
|
+
|
|
6
|
+
title = "FAQ"
|
|
7
|
+
HERE = Path(__file__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@solara.component
|
|
11
|
+
def Page(route_external=None):
|
|
12
|
+
MarkdownWithMetadata(Path(HERE.parent / "content" / "99-faq.md").read_text())
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: FAQ about Solara
|
|
3
|
+
description: Answers to some common questions about using Solara, and building your app using the framework
|
|
4
|
+
---
|
|
5
|
+
# FAQ
|
|
6
|
+
|
|
7
|
+
## I am not interested in the server, I'm happy with Jupyter/Voila, what's in it for me?
|
|
8
|
+
|
|
9
|
+
That means you simply do not use or install the server component, just use the Reacton components and run it with Voila.
|
|
10
|
+
|
|
11
|
+
## Is the Solara server better than Voilà?
|
|
12
|
+
|
|
13
|
+
No, they are different, and there are situations where I would recommend Voila instead of Solara.
|
|
14
|
+
|
|
15
|
+
If your app is compute-heavy, and a lot of the compute is happening in pure Python, the GIL (Global Interpreter Lock) can become a bottleneck with Solara, and Voila might give you better performance per client.
|
|
16
|
+
|
|
17
|
+
If you have a lot of users with short sessions, Solara spares you from having to start up a kernel for each request. Since Solara can use multiple workers in the near future, you can still scale up using multiple processes. Voila will have one process per user, while Solara can share a process with many users.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Can Solara run a normal Python script?
|
|
21
|
+
|
|
22
|
+
Yes, this is the preferred way of using Solara. You edit a Python script, save it, Solara will detect the file change and reload the page in your browser (no interaction is needed).
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
$ solara myapp.py
|
|
26
|
+
Solara server is starting at http://localhost:8766
|
|
27
|
+
... file change detected ...
|
|
28
|
+
(server refreshes, your page will reload)
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Can Solara run from a Python package/module?
|
|
33
|
+
|
|
34
|
+
Over time, when your application becomes larger, you probably want to structure your application into a Python package. Instead of a filename, you pass in the package name on the command line
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
$ solara mystartup.killerapp --dev
|
|
38
|
+
....
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Can Solara run Jupyter notebook?
|
|
42
|
+
|
|
43
|
+
Yes, Solara will execute each cell, and after that will look for a variable or component called `Page`, like with a normal script. All other output, Markdown or other types of cells will be ignored.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## Can I use Solara in my existing FastAPI/Starlette/Flask server?
|
|
48
|
+
|
|
49
|
+
Yes, take a look at the `solara.server.starlette` and `solara.server.fastapi` and `solara.server.flask` module. The usage will change over time, so read the source and be ready to change this in the future. We do plan to provide a stable API for this in the future.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## How to fix: inotify watch limit reached?
|
|
53
|
+
|
|
54
|
+
Add the line
|
|
55
|
+
|
|
56
|
+
fs.inotify.max_user_watches=524288
|
|
57
|
+
|
|
58
|
+
To your /etc/sysctl.conf file, and run `sudo sysctl -p.`
|
|
59
|
+
|
|
60
|
+
Or if you are using visual studio code, please read: https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## How can I recognize if I run in Solara, Voila or Jupyter Notebook/Lab
|
|
64
|
+
|
|
65
|
+
Voila and Solara set the following environment variables (based on the CGI spec):
|
|
66
|
+
|
|
67
|
+
* SERVER_SOFTWARE
|
|
68
|
+
* Solara: e.g. 'solara/1.2.3'
|
|
69
|
+
* Voila: e.g. 'voila/1.2.3'
|
|
70
|
+
* SERVER_PORT (e.g. '8765')
|
|
71
|
+
* SERVER_NAME (e.g. 'killerapp.com')
|
|
72
|
+
* SCRIPT_NAME (only Voila, e.g. 'voila/render/notebook.ipynb')
|
|
73
|
+
* PATH_TRANSLATED (only Solara e.g. '/mnt/someapp/app.py')
|
|
74
|
+
|
|
75
|
+
Jupyter Notebook/Lab/Server do not set these variables. With this information,
|
|
76
|
+
it should be possible to recognize in which environment you are running in.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## I cannot find or run `solara` from the command line
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
On Linux or OSX you might see
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
$ solara
|
|
86
|
+
command not found: solara
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
On Windows you might see
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
C:Users\myusername> solara
|
|
93
|
+
solara: The term 'solara' is not recognized as the name of a cdlet, function,
|
|
94
|
+
script file, or operable program.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The solara command before version 1.30 was installed with the package `solara`, but now it is installed with the package `solara-server`.
|
|
98
|
+
|
|
99
|
+
If you upgrade from an older version to 1.30 or later, the order in which pip installs packages can cause the `solara` command to be uninstalled. To fix this, reinstall the `solara-server` package:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
$ pip install solara-server --force-reinstall
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
# I see an error in the browser console
|
|
106
|
+
|
|
107
|
+
If you see an error like this in the browser console:
|
|
108
|
+
```
|
|
109
|
+
Uncaught Error: Script error for "base/js/namespace", needed by: /jupyter/nbextensions/dash/main.js
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
See [ignoring notebook extensions](/documentation/advanced/understanding/solara-server#ignoring-notebook-extensions) for more information.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from solara.autorouting import generate_routes_directory
|
|
4
|
+
from solara.website.components.markdown import MarkdownWithMetadata
|
|
5
|
+
|
|
6
|
+
HERE = Path(__file__)
|
|
7
|
+
# if we didn't put the content in the subdirectory, but pointed to the current file
|
|
8
|
+
# we would include the current file recursively, causing an infinite loop
|
|
9
|
+
routes = generate_routes_directory(HERE.parent / "content", MarkdownWithMetadata)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Solara Quickstart
|
|
3
|
+
description: Get started with building web- and data-apps in pure python with Solara.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Quickstart
|
|
7
|
+
|
|
8
|
+
This 1-minute quickstart will get you to:
|
|
9
|
+
|
|
10
|
+
* Install Solara.
|
|
11
|
+
* Write your first Solara script.
|
|
12
|
+
* Run your script using Solara server.
|
|
13
|
+
* (Optional) Reuse your code in the Jupyter notebook.
|
|
14
|
+
|
|
15
|
+
If you are an existing ipywidget user and do not want to learn the component based method, you might want to skip the quickstart and directly go to the [IPywidgets user tutorial](/documentation/getting_started/tutorials/ipywidgets).
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Run `pip install solara`, or follow the [Installation instructions](/documentation/getting_started/installing) for more detailed instructions.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## First script
|
|
24
|
+
|
|
25
|
+
Put the following Python snippet in a file (we suggest `sol.py`), or put it in a Jupyter notebook cell:
|
|
26
|
+
|
|
27
|
+
```solara {pycafe-link}
|
|
28
|
+
import solara
|
|
29
|
+
|
|
30
|
+
# Declare reactive variables at the top level. Components using these variables
|
|
31
|
+
# will be re-executed when their values change.
|
|
32
|
+
sentence = solara.reactive("Solara makes our team more productive.")
|
|
33
|
+
word_limit = solara.reactive(10)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@solara.component
|
|
37
|
+
def Page():
|
|
38
|
+
# Calculate word_count within the component to ensure re-execution when reactive variables change.
|
|
39
|
+
word_count = len(sentence.value.split())
|
|
40
|
+
|
|
41
|
+
solara.SliderInt("Word limit", value=word_limit, min=2, max=20)
|
|
42
|
+
solara.InputText(label="Your sentence", value=sentence, continuous_update=True)
|
|
43
|
+
|
|
44
|
+
# Display messages based on the current word count and word limit.
|
|
45
|
+
if word_count >= int(word_limit.value):
|
|
46
|
+
solara.Error(f"With {word_count} words, you passed the word limit of {word_limit.value}.")
|
|
47
|
+
elif word_count >= int(0.8 * word_limit.value):
|
|
48
|
+
solara.Warning(f"With {word_count} words, you are close to the word limit of {word_limit.value}.")
|
|
49
|
+
else:
|
|
50
|
+
solara.Success("Great short writing!")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# The following line is required only when running the code in a Jupyter notebook:
|
|
54
|
+
Page()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Yes, the above example is running live on the Solara documentation web server. If you change the slider the output updates.
|
|
58
|
+
|
|
59
|
+
## Run the script using Solara server
|
|
60
|
+
|
|
61
|
+
Run from the command line in the same directory where you put your file (`sol.py`):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
$ solara run sol.py
|
|
65
|
+
Solara server is starting at http://localhost:8765
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If you open the URL in your browser ([http://localhost:8765](http://localhost:8765)), you should see the same graph in your browser, now running on your computer.
|
|
69
|
+
|
|
70
|
+
## Reuse your code in the Jupyter notebook.
|
|
71
|
+
|
|
72
|
+
From Jupyter Notebook (classic) or Jupyter Lab, navigate to the same directory as `sol.py`. Enter the following code in a notebook cell:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from sol import Page
|
|
76
|
+
display(Page())
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
You should see the following output:
|
|
80
|
+
|
|
81
|
+
<img src="https://dxhl76zpt6fap.cloudfront.net/public/quickstart-notebook.webp" alt="Markdown Monster icon" style="border: 1px solid #ccc;" />
|
|
82
|
+
|
|
83
|
+
In case you forgot how to start a notebook server:
|
|
84
|
+
|
|
85
|
+
$ jupyter notebook
|
|
86
|
+
|
|
87
|
+
Or the more modern Jupyter lab:
|
|
88
|
+
|
|
89
|
+
$ jupyter lab
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Run as app (experimental)
|
|
93
|
+
|
|
94
|
+
You can also run the script as a standalone app. This requires the extra packages `qtpy` and `PySide6` (or `PyQt6`) to be installed.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
$ pip install qtpy PySide6
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Run from the command line in the same directory where you put your file (`sol.py`):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
$ solara run sol.py --qt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
<img src="https://dxhl76zpt6fap.cloudfront.net/public/solara-quickstart-app.webp" alt="Markdown Monster icon"/>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: A quick introduction to Solara
|
|
3
|
+
description: Solara is an Open Source library that lets you use and build data-focused web apps (data apps) using reusable UI components. Here you'll learn the basics!
|
|
4
|
+
---
|
|
5
|
+
# Introduction
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## What is Solara?
|
|
9
|
+
|
|
10
|
+
Solara is an Open Source library that lets you use and build data-focused web apps (data apps) using reusable UI components. Your app will work in the Jupyter notebook and production-grade web frameworks (FastAPI, Starlette, Flask, ...).
|
|
11
|
+
|
|
12
|
+
Solara uses proven technologies and mature standards. Grow from a one-off experiment in the Jupyter notebook to a dynamic data portal in production. Built on top of [Reacton](/documentation/advanced/understanding/reacton) to keep your code complexity under control and [IPywidgets](/documentation/advanced/understanding/ipywidgets) to access a rich set of UI libraries without having to write Javascript or CSS.
|
|
13
|
+
|
|
14
|
+
We care about developer experience. Solara will give your hot code reloading and type hints for faster development.
|
|
15
|
+
|
|
16
|
+
## Why is Solara created?
|
|
17
|
+
|
|
18
|
+
How much time have you wasted investing in a web framework only to find out that what you need is impossible to do?
|
|
19
|
+
|
|
20
|
+
Many frameworks only solve a specific set of problems. Once you step outside of the paved path, you get stuck.
|
|
21
|
+
|
|
22
|
+
On the other extreme, you might be working with a library with no clear patterns that let you do anything. You may only be weeks away from a total code complexity nightmare, which slowly kills your project.
|
|
23
|
+
|
|
24
|
+
At the same time, starting a new framework from scratch would be unwise. We prefer to build on top of solid, battle-tested libraries, such as [IPywidgets](/documentation/advanced/understanding/ipywidgets).
|
|
25
|
+
|
|
26
|
+
## Why use Solara?
|
|
27
|
+
|
|
28
|
+
Instead of inventing a new API with an unknown track record, we take a different approach. We look at the JavaScript world. React is a technology that has proven itself for many years. It has shown to be a good all-around model for building complex UIs.
|
|
29
|
+
|
|
30
|
+
[Reacton](/documentation/advanced/understanding/reacton) is the equivalent of ReactJS for Python (and IPywidgets). It allows us to use the same reusable components and hooks as in the ReactJS ecosystem. Using Reacton, we build web/data applications without suffering from complex code bases.
|
|
31
|
+
|
|
32
|
+
Looking again at the JavaScript world, we see software such as NextJS is putting a framework around ReactJS. NextJS is more opinionated than ReactJS and adds more "batteries" such as routing.
|
|
33
|
+
|
|
34
|
+
Solara plays a similar role as NextJS. It builds on top of Reacton but handles things like routing for you.
|
|
35
|
+
|
|
36
|
+
But Solara is also different and is even more opinionated than NextJS. The reason for this is its focus on the data-heavy Python ecosystem. For this reason, it comes with many components and hooks that make building beautiful data apps easier (see our [Documentation](/documentation)).
|
|
37
|
+
|
|
38
|
+
Solara is a clear, systematic, Python-based web framework using industry-trusted technology. Smooth developer experience and enforced code modularity will allow you to build a data app at any scale while maintaining simple code.
|
|
39
|
+
|
|
40
|
+
## A quick Solara example
|
|
41
|
+
|
|
42
|
+
For your understanding, it might be good just to run an example.
|
|
43
|
+
|
|
44
|
+
Follow the [installation instructions](/documentation/getting_started/installing) or do the TLDR:
|
|
45
|
+
|
|
46
|
+
$ pip install solara
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
Create a file `myapp.py`, or put the following code in the Jupyter notebook:
|
|
50
|
+
|
|
51
|
+
```solara {pycafe-link}
|
|
52
|
+
import solara
|
|
53
|
+
|
|
54
|
+
clicks = solara.reactive(0)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@solara.component
|
|
58
|
+
def Page():
|
|
59
|
+
def increase_clicks():
|
|
60
|
+
clicks.value += 1
|
|
61
|
+
|
|
62
|
+
solara.Button(label=f"Clicked {clicks} times", on_click=increase_clicks)
|
|
63
|
+
|
|
64
|
+
# in the Jupyter notebook, uncomment the next line:
|
|
65
|
+
# display(Page())
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
*Note that the above output is __live__, you can click the button and see the behaviour*.
|
|
69
|
+
|
|
70
|
+
Run solara-server (if *not* using the Jupyter notebook)
|
|
71
|
+
|
|
72
|
+
$ solara run myapp.py
|
|
73
|
+
Solara server is starting at http://localhost:8765
|
|
74
|
+
|
|
75
|
+
The browser should open http://127.0.0.1:8765
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## How does Solara fit into the big picture?
|
|
81
|
+
|
|
82
|
+
Solara is actually two things.
|
|
83
|
+
|
|
84
|
+
### Solara server
|
|
85
|
+
[Solara server](/documentation/advanced/understanding/solara-server) renders ipywidgets in the browser in a very efficient manner and takes care of many other things
|
|
86
|
+
such as [routing](/documentation/advanced/understanding/routing) and [Static Site Generation](/documentation/advanced/reference/static-site-generation).
|
|
87
|
+
|
|
88
|
+
### Solara UI
|
|
89
|
+
|
|
90
|
+
The UI part is built on top of [Reacton](/documentation/advanced/understanding/reacton), which uses the existing IPyWidgets stack. It gives a consistent set
|
|
91
|
+
of modern UI components with the Material Design look, as well as a set of routines to make application development of data heavy web apps
|
|
92
|
+
easier.
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
### Overview
|
|
96
|
+
If you use Jupyter, then you probably use the Jupyter notebook, Lab, or [Voila](/documentation/advanced/understanding/voila) to get your widgets into the browser. You may not care about [Solara server](/documentation/advanced/understanding/solara-server) and can focus on just the UI part.
|
|
97
|
+
|
|
98
|
+
If you don't use Jupyter, don't know what it is, or are an ML Ops, Dev Ops, or Sys Admin, you are probably more interested in the Solara server.
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
## How do I learn Solara?
|
|
103
|
+
|
|
104
|
+
We recommend going through the documentation linearly following the arrows on the bottom, meaning you will go through:
|
|
105
|
+
|
|
106
|
+
* [Installing](/documentation/getting_started/installing)
|
|
107
|
+
* [Quick start](/documentation/getting_started)
|
|
108
|
+
* [Tutorials](/documentation/getting_started/tutorials)
|
|
109
|
+
|
|
110
|
+
If you want to know more about specific parts, you can go through the [How-to section](/documentation/advanced/howto) to learn more. Feel free to skip chapters, and go back to topics when you need to.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
If you want to know what components or hooks are available, or want to know more about a specific component, check out the [Documentation](/documentation) which includes live code examples. Other reference documentation can be found at the [reference section](/documentation/advanced/reference)
|
|
114
|
+
|
|
115
|
+
If you feel like you miss some basic understanding and want to give a bit deeper into the what and why feel free to explore the [Understanding section](/documentation/advanced/understanding).
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
[Our examples](/documentation/examples) may help you see how particular problems can be solved using Solara, or as inspiration. If you want to contribute an example, contact us on GitHub or directly open a [Pull Request](https://github.com/widgetti/solara/).
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## Where can I hire an expert?
|
|
122
|
+
|
|
123
|
+
If you need consulting, training or development, you can reach us at:
|
|
124
|
+
|
|
125
|
+
contact@solara.dev
|