solara-ui 1.36.0__tar.gz → 1.37.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {solara_ui-1.36.0 → solara_ui-1.37.0}/PKG-INFO +1 -1
- {solara_ui-1.36.0 → solara_ui-1.37.0}/pyproject.toml +3 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/__init__.py +2 -2
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/autorouting.py +12 -1
- solara_ui-1.37.0/solara/core.py +42 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/server.py +3 -2
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/solara_bootstrap.py +1 -1
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/settings.py +13 -0
- solara_ui-1.37.0/solara/validate_hooks.py +260 -0
- solara_ui-1.37.0/solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +192 -0
- solara_ui-1.37.0/tests/unit/hook_use_invalid_test.py +165 -0
- solara_ui-1.36.0/solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +0 -7
- {solara_ui-1.36.0 → solara_ui-1.37.0}/.gitignore +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/LICENSE +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/README.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/prefix/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/__main__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/alias.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/cache.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/checks.html +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/checks.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/comm.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/alert.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/applayout.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/button.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/card.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/checkbox.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/code_highlight_css.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/code_highlight_css.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/columns.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/component_vue.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/cross_filter.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/datatable.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/datatable.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/details.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/download.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/echarts.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/echarts.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/figure_altair.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/file_browser.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/file_download.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/file_drop.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/file_drop.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/file_list_widget.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/head.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/head_tag.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/head_tag.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/image.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/input.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/link.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/markdown.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/markdown_editor.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/markdown_editor.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/matplotlib.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/meta.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/misc.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/pivot_table.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/pivot_table.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/progress.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/select.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/select.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/slider.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/slider_date.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/spinner-solara.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/spinner.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/sql_code.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/sql_code.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/style.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/switch.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/tab_navigation.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/title.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/title.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/togglebuttons.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/components/tooltip.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/datatypes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/express.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/hooks/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/hooks/dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/hooks/misc.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/hooks/use_reactive.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/hooks/use_thread.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/kitchensink.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/chat.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/confirmation_dialog.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/cross_filter.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/input_date.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/menu.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/menu.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/tabs.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/theming.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/components/theming.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/hooks/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/hooks/dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/toestand.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/utils/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/utils/cookies.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/utils/dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lab/utils/headers.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/layout.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/lifecycle.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/minisettings.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/py.typed +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/reactive.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/routing.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/scope/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/scope/types.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/app.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/custom.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/custom.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/favicon.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/favicon.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/style.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/theme-dark.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/theme-light.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/assets/theme.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/cdn_helper.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/esm.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/fastapi.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/flask.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/jupyter/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/jupyter/cdn_handler.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/jupyter/server_extension.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/jupytertools.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/kernel.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/kernel_context.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/patch.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/reload.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/settings.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/shell.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/starlette.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/ansi.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/highlight-dark.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/highlight.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/main-vuetify.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/main.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/sun.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/static/webworker.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/telemetry.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/index.html.j2 +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/loader-plain.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/loader-plain.html +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/loader-solara.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/loader-solara.html +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/plain.html +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/templates/solara.html.j2 +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/threaded.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/utils.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/server/websocket.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/tasks.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/button.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/markdown.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/.flake8 +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/.pre-commit-config.yaml +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/LICENSE +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/Procfile +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/mypy.ini +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/pyproject.toml +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/components/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/components/article.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/components/data.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/components/header.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/components/layout.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/content/articles/substiterat-vati.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/data.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/pages/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/pages/article/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/pages/tabular.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/pages/viz/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/template/portal/solara_portal/pages/viz/overview.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/test/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/test/pytest_plugin.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/toestand.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/util.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/assets/custom.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/assets/images/logo-small.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/assets/images/logo.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/assets/images/logo_white.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/assets/theme.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/algolia.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/algolia.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/algolia_api.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/docs.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/header.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/hero.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/mailchimp.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/mailchimp.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/markdown.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/notebook.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/components/sidebar.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/authorization/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/authorization/admin.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/authorization/users.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/jupyter-dashboard-1.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/layout-demo.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/multipage/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/multipage/page1.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/multipage/page2.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/scatter.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/scrolling.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/apps/tutorial-streamlit.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/changelog/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/changelog/changelog.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/contact/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/contact/contact.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/doc_use_download.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/70-search.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/advanced/content/40-development/10-setup.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/cross_filter/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_cross_filter.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_dark_effective.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_effect.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_effect.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_exception.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_memo.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_memo.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_previous.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_reactive.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_state.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_state_or_update.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_thread.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_thread.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/hooks/use_trait_observe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/generate_routes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/generate_routes_directory.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/resolve_path.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/route.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/use_route.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/routing/use_router.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/component_vue.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/computed.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/display.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/get_kernel_id.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/get_session_id.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/memoize.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/on_kernel_start.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/reactive.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/api/utilities/widget.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/advanced/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/advanced/link.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/advanced/meta.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/advanced/style.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/common.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/data/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/data/dataframe.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/data/pivot_table.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/enterprise/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/enterprise/avatar.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/enterprise/avatar_menu.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/button.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/checkbox.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/file_browser.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/file_drop.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/input.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/select.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/slider.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/switch.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/input/togglebuttons.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/chat.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/confirmation_dialog.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/cookies_headers.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/input_date.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/menu.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/tab.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/tabs.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/task.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/theming.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/lab/use_task.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/app_bar.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/app_bar_title.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/app_layout.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/card.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/card_actions.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/column.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/columns.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/columns_responsive.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/details.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/griddraggable.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/gridfixed.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/hbox.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/row.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/sidebar.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/layout/vbox.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/file_download.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/html.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/image.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/markdown.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/markdown_editor.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/sql_code.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/output/tooltip.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/page/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/page/head.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/page/title.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/error.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/info.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/progress.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/spinner.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/success.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/status/warning.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/altair.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/echarts.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/matplotlib.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/plotly.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/components/viz/plotly_express.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/ai/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/ai/chatbot.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/ai/tokenizer.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/basics/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/basics/sine.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/authorization.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/layout_demo.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/multipage.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/scatter.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/scrolling.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/custom_storage.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/deploy_model.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/live_update.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/login_oauth.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/mycard.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/pokemon_search.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/general/vue_component.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/ipycanvas.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/libraries/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/libraries/altair.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/libraries/bqplot.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/libraries/ipyleaflet.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/utilities/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/utilities/calculator.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/utilities/countdown_timer.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/utilities/todo.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/visualization/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/visualization/annotator.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/visualization/linked_views.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/examples/visualization/plotly.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/faq/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/faq/content/99-faq.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/00-quickstart.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/01-introduction.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/02-installing.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/docutils.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/domino_code_assist.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/planeto_tessa.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/solara_dev.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/solarathon_2023_team_2.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/solarathon_2023_team_4.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/solarathon_2023_team_5.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/solarathon_2023_team_6.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/pages/showcase/wanderlust.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/beach.jpeg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/logo.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/social/discord.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/social/github.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/social/twitter.svg +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/public/success.html +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/templates/index.html.j2 +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/website/utils.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/vue/gridlayout.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/vue/html.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/vue/navigator.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/vue/vegalite.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/solara/widgets/widgets.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/conftest.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/docs/docs_howto_event_with_future_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/docs/docs_howto_event_with_polling_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/docs/docs_howto_no_browser_api_find_testing_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/docs/docs_howto_no_browser_testing_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/docs/docs_howto_no_browser_threaded_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/api_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/app_widget.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/apps/not-allowed +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/apps/public/test.txt +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/apps/secure/app.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets1/common.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets1/unique1.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets2/common.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets2/custom.css +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets2/custom.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets/assets2/unique2.js +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/assets_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/async_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/cdn_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/cmdline_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/conftest.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/create_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/enterprise/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/enterprise/oauth_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/error_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/esm_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/file_download_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/flask_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/input_date_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/latex_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/lifecycle_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/markdown_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/menu_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/popout_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/reconnect_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/reload/apps.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/router_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/server_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/ssg_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/starlette_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/test.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/testapp.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/integration/widget_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/latex_test.py/test_widget_latex_solara-flask-chromium-linux-ipywidgets-7-changed-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/latex_test.py/test_widget_latex_solara-flask-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/latex_test.py/test_widget_latex_solara-flask-chromium-linux-ipywidgets-8-changed-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/latex_test.py/test_widget_latex_solara-flask-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-jupyter_lab-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-jupyter_lab-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-jupyter_notebook-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-jupyter_notebook-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-solara-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-solara-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-voila-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-flask-voila-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-starlette-solara-chromium-linux-ipywidgets-7-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_slider_all-starlette-solara-chromium-linux-ipywidgets-8-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_solara_button_all-flask-jupyter_lab-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_solara_button_all-flask-jupyter_notebook-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_solara_button_all-flask-solara-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_solara_button_all-flask-voila-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_solara_button_all-starlette-solara-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_widget_button_solara-flask-chromium-linux-ipyvuetify3-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_widget_button_solara-flask-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_widget_button_solara-starlette-chromium-linux-ipyvuetify3-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/ui/snapshots/tests/integration/widget_test.py/test_widget_button_solara-starlette-chromium-linux-reference.png +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/app_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/applayout_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/autorouting_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/cache_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/cdn_helper_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/chat_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/checkbox_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/common.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/component_frontend_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/component_vue_test.vue +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/confirmation_dialog_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/conftest.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/cross_filter_component_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/cross_filter_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/dataframe_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/datatable_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/display_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/express_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/file_browser_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/file_download_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/hooks_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/input_date_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/input_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/kernel_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/lab/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/lifecycle_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/matplotlib_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/no_solara_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/output_widget_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/patch_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/pivottable_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/reload_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/router_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/select_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/settings_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/shell_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/slider_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/food/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/food/food.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/food/index.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/kernel_start.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/01-home.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/02-my_fruit.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/03-some-markdown.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/04-a_directory/00-another-markdown.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/04-a_directory/01-not-an-app.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/04-a_directory/__init__.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/05-and-notebooks.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/06-custom-routes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/10-single-file-directory/single-file.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/99-some_other_python_script.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage/some_other_file.txt +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage-widgets/00-overview.md +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage-widgets/01-views.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage-widgets/02-likes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage-widgets/03-volume.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/multipage-widgets/04-color.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/notebookapp_component.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/notebookapp_element.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/notebookapp_widget.ipynb +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/single_file.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/single_file_multiple_routes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/solara_test_apps/single_file_routes.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/switch_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/tabs_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/task_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/telemetry_tests.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/toestand_computed_reload.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/toestand_test.py +0 -0
- {solara_ui-1.36.0 → solara_ui-1.37.0}/tests/unit/toggle_button_test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Build webapps using IPywidgets"""
|
|
2
2
|
|
|
3
|
-
__version__ = "1.
|
|
3
|
+
__version__ = "1.37.0"
|
|
4
4
|
github_url = "https://github.com/widgetti/solara"
|
|
5
5
|
git_branch = "master"
|
|
6
6
|
|
|
@@ -21,7 +21,6 @@ def _using_solara_server():
|
|
|
21
21
|
# isort: skip_file
|
|
22
22
|
# ruff: noqa: F401 F403
|
|
23
23
|
from reacton import (
|
|
24
|
-
component,
|
|
25
24
|
component_interactive,
|
|
26
25
|
value_component,
|
|
27
26
|
create_context,
|
|
@@ -42,6 +41,7 @@ from reacton import (
|
|
|
42
41
|
use_state_widget,
|
|
43
42
|
)
|
|
44
43
|
from reacton.core import Element
|
|
44
|
+
from .core import component
|
|
45
45
|
|
|
46
46
|
try:
|
|
47
47
|
import ipyvuetify.components as v # type: ignore
|
|
@@ -4,6 +4,7 @@ import importlib
|
|
|
4
4
|
import inspect
|
|
5
5
|
import pkgutil
|
|
6
6
|
import re
|
|
7
|
+
import linecache
|
|
7
8
|
import warnings
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from types import ModuleType
|
|
@@ -46,7 +47,17 @@ def source_to_module(path: Path, initial_namespace={}) -> ModuleType:
|
|
|
46
47
|
cell_index += 1 # used 1 based
|
|
47
48
|
if cell.cell_type == "code":
|
|
48
49
|
source = cell.source
|
|
49
|
-
|
|
50
|
+
# similar to ipython/ipython/IPython/core/compilerop.py
|
|
51
|
+
# inspect.py:findsource accepts non-filenames with '<' and '>' around it
|
|
52
|
+
cell_path = f"<{str(path)} input cell {cell_index}>"
|
|
53
|
+
# put an entry in linecache so that we can use inspect.getsource
|
|
54
|
+
entry = (
|
|
55
|
+
len(source),
|
|
56
|
+
None,
|
|
57
|
+
[line + "\n" for line in source.splitlines()],
|
|
58
|
+
cell_path,
|
|
59
|
+
)
|
|
60
|
+
linecache.cache[cell_path] = entry
|
|
50
61
|
ast = compile(source, cell_path, "exec")
|
|
51
62
|
exec(ast, mod.__dict__)
|
|
52
63
|
else:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import Any, Callable, Dict, Union, overload, TypeVar
|
|
3
|
+
import typing_extensions
|
|
4
|
+
import reacton
|
|
5
|
+
from . import validate_hooks
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
P = typing_extensions.ParamSpec("P")
|
|
9
|
+
FuncT = TypeVar("FuncT", bound=Callable[..., reacton.core.Element])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@overload
|
|
13
|
+
def component(obj: None = None, mime_bundle: Dict[str, Any] = ...) -> Callable[[FuncT], FuncT]: ...
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@overload
|
|
17
|
+
def component(obj: FuncT, mime_bundle: Dict[str, Any] = ...) -> FuncT: ...
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@overload
|
|
21
|
+
def component(obj: Callable[P, None], mime_bundle: Dict[str, Any] = ...) -> Callable[P, reacton.core.Element]: ...
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def component(
|
|
25
|
+
obj: Union[Callable[P, None], FuncT, None] = None, mime_bundle: Dict[str, Any] = reacton.core.mime_bundle_default
|
|
26
|
+
) -> Union[Callable[[FuncT], FuncT], FuncT, Callable[P, reacton.core.Element]]:
|
|
27
|
+
def wrapper(obj: Union[Callable[P, None], FuncT]) -> FuncT:
|
|
28
|
+
try:
|
|
29
|
+
validate_hooks.HookValidator(obj).run()
|
|
30
|
+
except Exception as e:
|
|
31
|
+
if not isinstance(e, validate_hooks.HookValidationError):
|
|
32
|
+
# we probably failed because of a unknown reason, but we do not want to break the user's code
|
|
33
|
+
warnings.warn(f"Failed to validate hooks for component {obj.__qualname__}: {e}")
|
|
34
|
+
else:
|
|
35
|
+
raise
|
|
36
|
+
|
|
37
|
+
return reacton.component(obj, mime_bundle) # type: ignore
|
|
38
|
+
|
|
39
|
+
if obj is not None:
|
|
40
|
+
return wrapper(obj)
|
|
41
|
+
else:
|
|
42
|
+
return wrapper
|
|
@@ -452,8 +452,9 @@ def get_nbextensions() -> Tuple[List[str], Dict[str, Optional[str]]]:
|
|
|
452
452
|
file_path = directory / (name + ".js")
|
|
453
453
|
if file_path.exists():
|
|
454
454
|
for file in directory.glob("**/*.*"):
|
|
455
|
-
|
|
456
|
-
|
|
455
|
+
if file.is_file(): # Otherwise directories with a dot in the name are included
|
|
456
|
+
data = file.read_bytes()
|
|
457
|
+
h.update(data)
|
|
457
458
|
except PermissionError:
|
|
458
459
|
logger.warning(f"Caught PermissionError while checking for existence of nbextension {name!r} at path: {file_path}. This path will be ignored.")
|
|
459
460
|
|
|
@@ -119,7 +119,7 @@ async def main():
|
|
|
119
119
|
]
|
|
120
120
|
for dep in requirements:
|
|
121
121
|
await micropip.install(dep, keep_going=True)
|
|
122
|
-
await micropip.install("/wheels/solara-1.
|
|
122
|
+
await micropip.install("/wheels/solara-1.37.0-py2.py3-none-any.whl", keep_going=True)
|
|
123
123
|
import solara
|
|
124
124
|
|
|
125
125
|
el = solara.Warning("lala")
|
|
@@ -52,5 +52,18 @@ class Assets(BaseSettings):
|
|
|
52
52
|
env_file = ".env"
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
class MainSettings(BaseSettings):
|
|
56
|
+
check_hooks: str = "warn"
|
|
57
|
+
|
|
58
|
+
class Config:
|
|
59
|
+
env_prefix = "solara_"
|
|
60
|
+
case_sensitive = False
|
|
61
|
+
env_file = ".env"
|
|
62
|
+
|
|
63
|
+
|
|
55
64
|
assets: Assets = Assets()
|
|
56
65
|
cache: Cache = Cache()
|
|
66
|
+
main = MainSettings()
|
|
67
|
+
|
|
68
|
+
if main.check_hooks not in ["off", "warn", "raise"]:
|
|
69
|
+
raise ValueError(f"Invalid value for check_hooks: {main.check_hooks}, expected one of ['off', 'warn', 'raise']")
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import inspect
|
|
3
|
+
import re
|
|
4
|
+
import typing as t
|
|
5
|
+
from enum import Enum
|
|
6
|
+
import sys
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
DEFAULT_USE_FUNCTIONS = ("^use_.*$",)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InvalidReactivityCause(Enum):
|
|
13
|
+
USE_AFTER_RETURN = "early return"
|
|
14
|
+
CONDITIONAL_USE = "conditional"
|
|
15
|
+
LOOP_USE = "loop"
|
|
16
|
+
NESTED_FUNCTION_USE = "nested function"
|
|
17
|
+
VARIABLE_ASSIGNMENT = "assignment"
|
|
18
|
+
EXCEPTION_USE = "exception"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
noqa_code_to_cause = {
|
|
22
|
+
"SH101": InvalidReactivityCause.USE_AFTER_RETURN,
|
|
23
|
+
"SH102": InvalidReactivityCause.CONDITIONAL_USE,
|
|
24
|
+
"SH103": InvalidReactivityCause.LOOP_USE,
|
|
25
|
+
"SH104": InvalidReactivityCause.NESTED_FUNCTION_USE,
|
|
26
|
+
"SH105": InvalidReactivityCause.VARIABLE_ASSIGNMENT,
|
|
27
|
+
"SH106": InvalidReactivityCause.EXCEPTION_USE,
|
|
28
|
+
}
|
|
29
|
+
cause_to_noqa_code = {v: k for k, v in noqa_code_to_cause.items()}
|
|
30
|
+
noqa_pattern = re.compile(r".*# noqa(?::\s*([A-Z]{2,3}\d{2,3})(?:,\s*([A-Z]{2,3}\d{2,3}))*)?")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if sys.version_info < (3, 11):
|
|
34
|
+
ScopeNodeType = t.Union[ast.For, ast.While, ast.If, ast.Try, ast.FunctionDef]
|
|
35
|
+
TryNodes = (ast.Try,)
|
|
36
|
+
else:
|
|
37
|
+
# except* nodes are only standardized in 3.11+
|
|
38
|
+
ScopeNodeType = t.Union[ast.For, ast.While, ast.If, ast.Try, ast.TryStar, ast.FunctionDef]
|
|
39
|
+
TryNodes = (ast.Try, ast.TryStar)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def line_to_noqa(line: str) -> t.Optional[t.Set[InvalidReactivityCause]]:
|
|
43
|
+
"""Return set of noqa code for which to not do quality assurance checks, or None when to do all qa."""
|
|
44
|
+
if "#" in line:
|
|
45
|
+
no_qa = set()
|
|
46
|
+
match = noqa_pattern.match(line)
|
|
47
|
+
if match is not None:
|
|
48
|
+
# not sure why we get some None values
|
|
49
|
+
groups = [k for k in match.groups() if k is not None]
|
|
50
|
+
if groups: # `noqa: SHXXX`` found
|
|
51
|
+
for group in groups:
|
|
52
|
+
if group not in noqa_code_to_cause:
|
|
53
|
+
if group.startswith("SH"):
|
|
54
|
+
raise ValueError(f"Unknown noqa code {group}")
|
|
55
|
+
else:
|
|
56
|
+
no_qa.add(noqa_code_to_cause[group])
|
|
57
|
+
else: # we found `noqa`
|
|
58
|
+
# skip all qa
|
|
59
|
+
no_qa = set(noqa_code_to_cause.values())
|
|
60
|
+
return no_qa
|
|
61
|
+
else:
|
|
62
|
+
return None # no noqa found
|
|
63
|
+
return None # fast path, no comment found
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def should_skip_qa(global_no_qa: t.Optional[t.Set[InvalidReactivityCause]], cause: InvalidReactivityCause, line: str) -> bool:
|
|
67
|
+
line_qa = line_to_noqa(line)
|
|
68
|
+
if global_no_qa is None and line_qa is None:
|
|
69
|
+
# there is not a noqa on the function or line
|
|
70
|
+
return False
|
|
71
|
+
else:
|
|
72
|
+
noqa = global_no_qa or set()
|
|
73
|
+
if line_qa is not None:
|
|
74
|
+
noqa |= line_qa
|
|
75
|
+
return cause in noqa
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class HookValidationError(Exception):
|
|
79
|
+
def __init__(self, cause: InvalidReactivityCause, message: str):
|
|
80
|
+
self.cause = cause
|
|
81
|
+
super().__init__(message)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class HookValidator(ast.NodeVisitor):
|
|
85
|
+
def __init__(self, component: t.Callable, use_functions=DEFAULT_USE_FUNCTIONS):
|
|
86
|
+
self.use_functions = [re.compile(use_func) for use_func in use_functions]
|
|
87
|
+
|
|
88
|
+
self.root_function_return: t.Optional[ast.Return] = None
|
|
89
|
+
self.outer_scope: t.Optional[ScopeNodeType] = None
|
|
90
|
+
|
|
91
|
+
self.filename = component.__code__.co_filename
|
|
92
|
+
self.line_offset = component.__code__.co_firstlineno - 1
|
|
93
|
+
self.component = component
|
|
94
|
+
|
|
95
|
+
self.source = inspect.getsource(self.component)
|
|
96
|
+
# lines before we dedent
|
|
97
|
+
self.lines = self.source.split("\n")
|
|
98
|
+
# dedent the source code to avoid indentation errors
|
|
99
|
+
parsed_source = inspect.cleandoc(self.source)
|
|
100
|
+
parsed = ast.parse(parsed_source)
|
|
101
|
+
# Get nodes from inside the function body
|
|
102
|
+
func_definition = t.cast(ast.FunctionDef, parsed.body[0])
|
|
103
|
+
self.function_scope: ast.FunctionDef = func_definition
|
|
104
|
+
self._root_function_scope = self.function_scope
|
|
105
|
+
# None means, *DO* qa
|
|
106
|
+
self.no_qa: t.Optional[t.Set[InvalidReactivityCause]] = None
|
|
107
|
+
|
|
108
|
+
def run(self):
|
|
109
|
+
import solara.settings
|
|
110
|
+
|
|
111
|
+
if solara.settings.main.check_hooks == "off":
|
|
112
|
+
return
|
|
113
|
+
func_def_line = self.lines[self._root_function_scope.lineno - 1]
|
|
114
|
+
self.no_qa = line_to_noqa(func_def_line)
|
|
115
|
+
try:
|
|
116
|
+
for node in self._root_function_scope.body:
|
|
117
|
+
self.visit(node)
|
|
118
|
+
except HookValidationError as e:
|
|
119
|
+
if solara.settings.main.check_hooks == "error":
|
|
120
|
+
raise e
|
|
121
|
+
elif solara.settings.main.check_hooks == "warn":
|
|
122
|
+
warnings.warn(str(e))
|
|
123
|
+
|
|
124
|
+
def matches_use_function(self, name: str) -> bool:
|
|
125
|
+
return any(use_func.match(name) for use_func in self.use_functions)
|
|
126
|
+
|
|
127
|
+
def node_to_scope_cause(self, node: ScopeNodeType) -> InvalidReactivityCause:
|
|
128
|
+
if isinstance(node, ast.If):
|
|
129
|
+
return InvalidReactivityCause.CONDITIONAL_USE
|
|
130
|
+
elif isinstance(node, (ast.For, ast.While)):
|
|
131
|
+
return InvalidReactivityCause.LOOP_USE
|
|
132
|
+
elif isinstance(node, ast.FunctionDef):
|
|
133
|
+
return InvalidReactivityCause.NESTED_FUNCTION_USE
|
|
134
|
+
elif isinstance(node, TryNodes):
|
|
135
|
+
return InvalidReactivityCause.EXCEPTION_USE
|
|
136
|
+
else:
|
|
137
|
+
warnings.warn(f"Unexpected scope node type: {node}, line={node.lineno}")
|
|
138
|
+
|
|
139
|
+
def visit_Call(self, node: ast.Call):
|
|
140
|
+
"""Records calls of use functions, i.e. solara.use_state(...)"""
|
|
141
|
+
func = node.func
|
|
142
|
+
if isinstance(func, ast.Call):
|
|
143
|
+
# Nested function, it will appear in another node later
|
|
144
|
+
return
|
|
145
|
+
if isinstance(func, ast.Name):
|
|
146
|
+
id_ = func.id
|
|
147
|
+
elif isinstance(func, ast.Attribute):
|
|
148
|
+
id_ = func.attr
|
|
149
|
+
else:
|
|
150
|
+
warnings.warn(f"Unexpected function node type: {func}, line={node.lineno}")
|
|
151
|
+
return
|
|
152
|
+
if self.matches_use_function(id_):
|
|
153
|
+
self.error_on_early_return(node, id_)
|
|
154
|
+
self.error_on_invalid_scope(node, id_)
|
|
155
|
+
self.generic_visit(node)
|
|
156
|
+
|
|
157
|
+
def visit_If(self, node: ast.If):
|
|
158
|
+
self._visit_children_using_scope(node)
|
|
159
|
+
|
|
160
|
+
def visit_For(self, node: ast.For):
|
|
161
|
+
self._visit_children_using_scope(node)
|
|
162
|
+
|
|
163
|
+
def visit_While(self, node: ast.While):
|
|
164
|
+
self._visit_children_using_scope(node)
|
|
165
|
+
|
|
166
|
+
def visit_Try(self, node: ast.Try) -> t.Any:
|
|
167
|
+
self._visit_children_using_scope(node)
|
|
168
|
+
|
|
169
|
+
if sys.version_info >= (3, 11):
|
|
170
|
+
|
|
171
|
+
def visit_TryStar(self, node: ast.TryStar) -> t.Any:
|
|
172
|
+
self._visit_children_using_scope(node)
|
|
173
|
+
|
|
174
|
+
def visit_FunctionDef(self, node: ast.FunctionDef):
|
|
175
|
+
old_function_scope = self.function_scope
|
|
176
|
+
self.function_scope = node
|
|
177
|
+
self._visit_children_using_scope(node)
|
|
178
|
+
self.function_scope = old_function_scope
|
|
179
|
+
|
|
180
|
+
def _visit_children_using_scope(self, node: ScopeNodeType):
|
|
181
|
+
outer_scope = self.outer_scope
|
|
182
|
+
self.outer_scope = node
|
|
183
|
+
for child in node.body:
|
|
184
|
+
self.visit(child)
|
|
185
|
+
self.outer_scope = outer_scope
|
|
186
|
+
|
|
187
|
+
def visit_Assign(self, node: ast.Assign):
|
|
188
|
+
self.error_on_invalid_assign(node)
|
|
189
|
+
self.generic_visit(node)
|
|
190
|
+
|
|
191
|
+
def visit_Return(self, node: ast.Return):
|
|
192
|
+
"""
|
|
193
|
+
Records the earliest return statement in the function
|
|
194
|
+
"""
|
|
195
|
+
# Returns are valid in nested functions
|
|
196
|
+
if self.function_scope != self._root_function_scope:
|
|
197
|
+
return
|
|
198
|
+
self.root_function_return = node
|
|
199
|
+
self.generic_visit(node)
|
|
200
|
+
|
|
201
|
+
def error_on_invalid_assign(self, node: ast.Assign):
|
|
202
|
+
if isinstance(node.value, ast.Attribute) and self.matches_use_function(node.value.attr):
|
|
203
|
+
line = node.lineno + self.line_offset
|
|
204
|
+
cause = InvalidReactivityCause.VARIABLE_ASSIGNMENT
|
|
205
|
+
message = f"Assigning the hook `{node.value.attr}` to a variable is not allowed since it complicates the tracking of valid hook use {_hint_supress(line, cause)}"
|
|
206
|
+
|
|
207
|
+
raise HookValidationError(
|
|
208
|
+
cause,
|
|
209
|
+
f"{self.get_source_context(line)}: {message}",
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
def error_on_early_return(self, use_node: ast.Call, use_node_id: str):
|
|
213
|
+
"""
|
|
214
|
+
Checks if the latest use of a reactive function occurs after the earliest return
|
|
215
|
+
"""
|
|
216
|
+
if self.root_function_return and self.root_function_return.lineno <= use_node.lineno:
|
|
217
|
+
offset_return = self.root_function_return.lineno + self.line_offset
|
|
218
|
+
offset_use = use_node.lineno + self.line_offset
|
|
219
|
+
cause = InvalidReactivityCause.USE_AFTER_RETURN
|
|
220
|
+
line = self.lines[use_node.lineno - 1]
|
|
221
|
+
if should_skip_qa(self.no_qa, cause, line):
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
raise HookValidationError(
|
|
225
|
+
cause,
|
|
226
|
+
f"""{self.get_source_context(offset_use)}: `{use_node_id}` found despite early return on line {offset_return}
|
|
227
|
+
{_hint_supress(line, cause)}""",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def error_on_invalid_scope(self, use_node: ast.Call, use_node_id: str):
|
|
231
|
+
"""
|
|
232
|
+
Checks if the latest use of a reactive function occurs after the earliest return or in an invalid scope
|
|
233
|
+
such as try-except blocks.
|
|
234
|
+
"""
|
|
235
|
+
if self.outer_scope is None:
|
|
236
|
+
return
|
|
237
|
+
offset_use = use_node.lineno + self.line_offset
|
|
238
|
+
cause = self.node_to_scope_cause(self.outer_scope)
|
|
239
|
+
|
|
240
|
+
scope_line = self.outer_scope.lineno + self.line_offset
|
|
241
|
+
line = self.lines[use_node.lineno - 1]
|
|
242
|
+
if should_skip_qa(self.no_qa, cause, line):
|
|
243
|
+
return
|
|
244
|
+
raise HookValidationError(
|
|
245
|
+
cause,
|
|
246
|
+
f"""{self.get_source_context(offset_use)}: `{use_node_id}` found within a {cause.value} created on line {scope_line}
|
|
247
|
+
{_hint_supress(line, cause)}""",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def get_source_context(self, lineno):
|
|
251
|
+
return f"{self.filename}:{lineno}: {self.component.__qualname__}"
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _hint_supress(line, cause):
|
|
255
|
+
return f"""To suppress this check, replace the line with:
|
|
256
|
+
{line} # noqa: {cause_to_noqa_code[cause]}
|
|
257
|
+
|
|
258
|
+
Make sure you understand the consequences of this, by reading about the rules of hooks at:
|
|
259
|
+
https://solara.dev/documentation/advanced/understanding/rules-of-hooks
|
|
260
|
+
"""
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The rules of hooks in Solara
|
|
3
|
+
description: Learn the rules that govern the usage of hooks in your Solara application.
|
|
4
|
+
----
|
|
5
|
+
# Rules of hooks
|
|
6
|
+
|
|
7
|
+
Hooks are Python function whose name start with `use_`. The most used hook is [use_state](https://solara.dev/documentation/api/hooks/use_state) which is used to manage the state of a component.
|
|
8
|
+
|
|
9
|
+
Hooks can only be called at the top level of a function component or a custom hook. They cannot be called inside loops, conditions, or nested functions.
|
|
10
|
+
The reason for this is that hooks rely on the order in which they are called to maintain state between renders. If a hook is called conditionally, it may not be called on every render, which can mix up the states.
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import solara
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@solara.component
|
|
17
|
+
def Page():
|
|
18
|
+
x, set_x = solara.use_state(1) # state 'slot' 1
|
|
19
|
+
if x < 10:
|
|
20
|
+
y, set_y = solara.use_state(2) # state 'slot' 2
|
|
21
|
+
else:
|
|
22
|
+
y, set_y = solara.use_state("foo") # *also* state 'slot' 2
|
|
23
|
+
solara.Text("Done")
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
In the above example, the `use_state(2)` and `use_state("foo")` is called conditionally, which means that the state 'slot' 2 (meaning, `y` and `set_y`) sometimes refer to the integer `2` and sometimes to the string `"foo"`. This gives unexpected behavior and will lead to bugs.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
The rules of hooks are checked by Solara, if you break the rules, you will get a warning, and in the future (Solara v2.0) you will get an error (an exception is raised).
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import solara
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@solara.component
|
|
38
|
+
def Page():
|
|
39
|
+
for i in range(10):
|
|
40
|
+
solara.use_state(1)
|
|
41
|
+
solara.Text("Done")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Will give the warning:
|
|
45
|
+
```
|
|
46
|
+
/some/prefix/site-packages/solara/solara/validate_hooks.py:122: UserWarning: /my/app.py:56: Page: `use_state` found within a loop created on line 55
|
|
47
|
+
To suppress this check, replace the line with:
|
|
48
|
+
solara.use_state(1) # noqa: SH103
|
|
49
|
+
|
|
50
|
+
Make sure you understand the consequences of this, by reading about the rules of hooks at:
|
|
51
|
+
https://solara.dev/documentation/advanced/understanding/rules-of-hooks
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
As the warning suggests, you can suppress the warning by adding `# noqa: SH103` to the line that breaks the rules.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import solara
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@solara.component
|
|
61
|
+
def Page():
|
|
62
|
+
for i in range(10):
|
|
63
|
+
solara.use_state(1) # noqa: SH103
|
|
64
|
+
|
|
65
|
+
solara.Text("Done")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The warning can also be suppressed for the whole component by adding `# noqa: SH103` to the function definition.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import solara
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@solara.component
|
|
75
|
+
def Page(): # noqa: SH103
|
|
76
|
+
for i in range(10):
|
|
77
|
+
solara.use_state(1)
|
|
78
|
+
|
|
79
|
+
solara.Text("Done")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
However, we strongly advise against this, and you should only use it if you know what you are doing (knowing the the loop will always run a fixed amount of times).
|
|
84
|
+
|
|
85
|
+
If you want to have an error raised instead of a warning, you can set the environment variable `SOLARA_CHECK_HOOKS=raise`, this is
|
|
86
|
+
planned to be the default in Solara v2.0.
|
|
87
|
+
|
|
88
|
+
In that case, you should get an error like this:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
solara.validate_hooks.HookValidationError: /my/app.py:56: Page: `use_state` found within a loop created on line 55
|
|
93
|
+
To suppress this check, replace the line with:
|
|
94
|
+
solara.use_state(1) # noqa: SH103
|
|
95
|
+
|
|
96
|
+
Make sure you understand the consequences of this, by reading about the rules of hooks at:
|
|
97
|
+
https://solara.dev/documentation/advanced/understanding/rules-of-hooks
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
For convenience, you can also disable the check by setting the environment variable `SOLARA_CHECK_HOOKS=off`, but we strongly advise against this.
|
|
102
|
+
|
|
103
|
+
## Types of error
|
|
104
|
+
|
|
105
|
+
### Early return (SH101)
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
import solara
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@solara.component
|
|
112
|
+
def Page():
|
|
113
|
+
solara.Text("Done")
|
|
114
|
+
if x < 10:
|
|
115
|
+
return # will cause the below use_state to not always be called
|
|
116
|
+
solara.use_state(1)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Conditional use (SH102)
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import solara
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@solara.component
|
|
126
|
+
def Page():
|
|
127
|
+
if x < 10:
|
|
128
|
+
solara.use_state(1) # will cause the use_state to not always be called
|
|
129
|
+
solara.Text("Done")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
### Loop use (SH103)
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
import solara
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@solara.component
|
|
140
|
+
def Page():
|
|
141
|
+
for i in range(x):
|
|
142
|
+
solara.use_state(1) # will cause the use_state to not always be a constant number of times
|
|
143
|
+
solara.Text("Done")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Nested function use (SH104)
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import solara
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@solara.component
|
|
153
|
+
def Page():
|
|
154
|
+
def inner():
|
|
155
|
+
solara.use_state(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
156
|
+
inner()
|
|
157
|
+
solara.Text("Done")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
### Variable assignment (SH105)
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
import solara
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@solara.component
|
|
168
|
+
def Page():
|
|
169
|
+
x = solara.use_state
|
|
170
|
+
x(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
171
|
+
solara.Text("Done")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
### Exception use (SH106)
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import solara
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@solara.component
|
|
182
|
+
def Page():
|
|
183
|
+
try:
|
|
184
|
+
this_might_fail()
|
|
185
|
+
solara.use_state(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
186
|
+
except:
|
|
187
|
+
pass
|
|
188
|
+
solara.Text("Done")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For this reason, it's also advised to always call hooks first, before doing anything else in a function component that might raise
|
|
192
|
+
an exception.
|