solara 1.30.1__py2.py3-none-any.whl → 1.32.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {solara-1.30.1.dist-info → solara-1.32.0.dist-info}/METADATA +12 -42
- solara-1.32.0.dist-info/RECORD +5 -0
- {solara-1.30.1.dist-info → solara-1.32.0.dist-info}/WHEEL +1 -1
- {solara/template/portal → solara-1.32.0.dist-info/licenses}/LICENSE +1 -1
- solara/__init__.py +0 -123
- solara/__main__.py +0 -734
- solara/alias.py +0 -6
- solara/autorouting.py +0 -545
- solara/cache.py +0 -294
- solara/checks.html +0 -71
- solara/checks.py +0 -224
- solara/comm.py +0 -28
- solara/components/__init__.py +0 -59
- solara/components/alert.py +0 -155
- solara/components/applayout.py +0 -393
- solara/components/button.py +0 -85
- solara/components/card.py +0 -87
- solara/components/checkbox.py +0 -50
- solara/components/code_highlight_css.py +0 -11
- solara/components/code_highlight_css.vue +0 -63
- solara/components/columns.py +0 -159
- solara/components/component_vue.py +0 -110
- solara/components/cross_filter.py +0 -335
- solara/components/dataframe.py +0 -546
- solara/components/datatable.py +0 -221
- solara/components/datatable.vue +0 -175
- solara/components/details.py +0 -21
- solara/components/download.vue +0 -35
- solara/components/echarts.py +0 -75
- solara/components/echarts.vue +0 -128
- solara/components/figure_altair.py +0 -39
- solara/components/file_browser.py +0 -182
- solara/components/file_download.py +0 -199
- solara/components/file_drop.py +0 -139
- solara/components/file_drop.vue +0 -83
- solara/components/file_list_widget.vue +0 -78
- solara/components/head.py +0 -27
- solara/components/head_tag.py +0 -49
- solara/components/head_tag.vue +0 -60
- solara/components/image.py +0 -173
- solara/components/input.py +0 -440
- solara/components/link.py +0 -55
- solara/components/markdown.py +0 -371
- solara/components/markdown_editor.py +0 -25
- solara/components/markdown_editor.vue +0 -362
- solara/components/matplotlib.py +0 -74
- solara/components/meta.py +0 -47
- solara/components/misc.py +0 -333
- solara/components/pivot_table.py +0 -258
- solara/components/pivot_table.vue +0 -158
- solara/components/progress.py +0 -47
- solara/components/select.py +0 -186
- solara/components/select.vue +0 -27
- solara/components/slider.py +0 -442
- solara/components/slider_date.vue +0 -56
- solara/components/spinner-solara.vue +0 -105
- solara/components/spinner.py +0 -30
- solara/components/sql_code.py +0 -33
- solara/components/sql_code.vue +0 -128
- solara/components/style.py +0 -105
- solara/components/switch.py +0 -68
- solara/components/tab_navigation.py +0 -37
- solara/components/title.py +0 -90
- solara/components/title.vue +0 -38
- solara/components/togglebuttons.py +0 -202
- solara/components/tooltip.py +0 -61
- solara/datatypes.py +0 -143
- solara/express.py +0 -241
- solara/hooks/__init__.py +0 -4
- solara/hooks/dataframe.py +0 -99
- solara/hooks/misc.py +0 -263
- solara/hooks/use_reactive.py +0 -129
- solara/hooks/use_thread.py +0 -129
- solara/kitchensink.py +0 -8
- solara/lab/__init__.py +0 -34
- solara/lab/components/__init__.py +0 -6
- solara/lab/components/chat.py +0 -203
- solara/lab/components/confirmation_dialog.py +0 -165
- solara/lab/components/cross_filter.py +0 -7
- solara/lab/components/input_date.py +0 -298
- solara/lab/components/menu.py +0 -181
- solara/lab/components/menu.vue +0 -38
- solara/lab/components/tabs.py +0 -274
- solara/lab/components/theming.py +0 -98
- solara/lab/components/theming.vue +0 -72
- solara/lab/hooks/__init__.py +0 -0
- solara/lab/hooks/dataframe.py +0 -12
- solara/lab/toestand.py +0 -3
- solara/lab/utils/__init__.py +0 -2
- solara/lab/utils/cookies.py +0 -5
- solara/lab/utils/dataframe.py +0 -115
- solara/lab/utils/headers.py +0 -5
- solara/layout.py +0 -44
- solara/minisettings.py +0 -133
- solara/py.typed +0 -0
- solara/reactive.py +0 -93
- solara/routing.py +0 -268
- solara/scope/__init__.py +0 -88
- solara/scope/types.py +0 -55
- solara/server/__init__.py +0 -0
- solara/server/app.py +0 -490
- solara/server/assets/custom.css +0 -1
- solara/server/assets/custom.js +0 -1
- solara/server/assets/favicon.png +0 -0
- solara/server/assets/favicon.svg +0 -5
- solara/server/assets/style.css +0 -1665
- solara/server/assets/theme-dark.css +0 -437
- solara/server/assets/theme-light.css +0 -420
- solara/server/assets/theme.js +0 -3
- solara/server/cdn_helper.py +0 -77
- solara/server/esm.py +0 -69
- solara/server/fastapi.py +0 -5
- solara/server/flask.py +0 -286
- solara/server/jupyter/__init__.py +0 -2
- solara/server/jupyter/cdn_handler.py +0 -28
- solara/server/jupyter/server_extension.py +0 -29
- solara/server/jupytertools.py +0 -46
- solara/server/kernel.py +0 -319
- solara/server/kernel_context.py +0 -396
- solara/server/patch.py +0 -552
- solara/server/reload.py +0 -242
- solara/server/server.py +0 -437
- solara/server/settings.py +0 -212
- solara/server/shell.py +0 -240
- solara/server/starlette.py +0 -597
- solara/server/static/ansi.js +0 -270
- solara/server/static/highlight-dark.css +0 -82
- solara/server/static/highlight.css +0 -43
- solara/server/static/main-vuetify.js +0 -260
- solara/server/static/main.js +0 -163
- solara/server/static/solara_bootstrap.py +0 -129
- solara/server/static/sun.svg +0 -23
- solara/server/static/webworker.js +0 -42
- solara/server/telemetry.py +0 -212
- solara/server/templates/index.html.j2 +0 -1
- solara/server/templates/loader-plain.css +0 -11
- solara/server/templates/loader-plain.html +0 -20
- solara/server/templates/loader-solara.css +0 -111
- solara/server/templates/loader-solara.html +0 -40
- solara/server/templates/plain.html +0 -82
- solara/server/templates/solara.html.j2 +0 -446
- solara/server/threaded.py +0 -75
- solara/server/utils.py +0 -30
- solara/server/websocket.py +0 -44
- solara/settings.py +0 -56
- solara/tasks.py +0 -847
- solara/template/button.py +0 -16
- solara/template/markdown.py +0 -42
- solara/template/portal/.flake8 +0 -6
- solara/template/portal/.pre-commit-config.yaml +0 -28
- solara/template/portal/Procfile +0 -7
- solara/template/portal/mypy.ini +0 -3
- solara/template/portal/pyproject.toml +0 -26
- solara/template/portal/solara_portal/__init__.py +0 -3
- solara/template/portal/solara_portal/components/__init__.py +0 -2
- solara/template/portal/solara_portal/components/article.py +0 -28
- solara/template/portal/solara_portal/components/data.py +0 -28
- solara/template/portal/solara_portal/components/header.py +0 -6
- solara/template/portal/solara_portal/components/layout.py +0 -6
- solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +0 -85
- solara/template/portal/solara_portal/content/articles/substiterat-vati.md +0 -70
- solara/template/portal/solara_portal/data.py +0 -60
- solara/template/portal/solara_portal/pages/__init__.py +0 -67
- solara/template/portal/solara_portal/pages/article/__init__.py +0 -26
- solara/template/portal/solara_portal/pages/tabular.py +0 -29
- solara/template/portal/solara_portal/pages/viz/__init__.py +0 -69
- solara/template/portal/solara_portal/pages/viz/overview.py +0 -14
- solara/test/__init__.py +0 -0
- solara/test/pytest_plugin.py +0 -698
- solara/toestand.py +0 -772
- solara/util.py +0 -308
- solara/website/__init__.py +0 -0
- solara/website/assets/custom.css +0 -462
- solara/website/assets/images/logo-small.png +0 -0
- solara/website/assets/images/logo.svg +0 -17
- solara/website/assets/images/logo_white.svg +0 -50
- solara/website/assets/theme.js +0 -8
- solara/website/components/__init__.py +0 -5
- solara/website/components/algolia.vue +0 -24
- solara/website/components/algolia_api.vue +0 -157
- solara/website/components/docs.py +0 -118
- solara/website/components/header.py +0 -72
- solara/website/components/hero.py +0 -15
- solara/website/components/mailchimp.py +0 -12
- solara/website/components/mailchimp.vue +0 -47
- solara/website/components/markdown.py +0 -30
- solara/website/components/notebook.py +0 -172
- solara/website/pages/__init__.py +0 -575
- solara/website/pages/apps/__init__.py +0 -16
- solara/website/pages/apps/authorization/__init__.py +0 -118
- solara/website/pages/apps/authorization/admin.py +0 -12
- solara/website/pages/apps/authorization/users.py +0 -12
- solara/website/pages/apps/jupyter-dashboard-1.py +0 -116
- solara/website/pages/apps/layout-demo.py +0 -40
- solara/website/pages/apps/multipage/__init__.py +0 -38
- solara/website/pages/apps/multipage/page1.py +0 -26
- solara/website/pages/apps/multipage/page2.py +0 -34
- solara/website/pages/apps/scatter.py +0 -136
- solara/website/pages/apps/scrolling.py +0 -63
- solara/website/pages/apps/tutorial-streamlit.py +0 -18
- solara/website/pages/changelog/__init__.py +0 -8
- solara/website/pages/changelog/changelog.md +0 -195
- solara/website/pages/contact/__init__.py +0 -8
- solara/website/pages/contact/contact.md +0 -17
- solara/website/pages/doc_use_download.py +0 -85
- solara/website/pages/documentation/__init__.py +0 -184
- solara/website/pages/documentation/advanced/__init__.py +0 -9
- solara/website/pages/documentation/advanced/content/00-overview.md +0 -1
- solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +0 -6
- solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +0 -196
- solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +0 -125
- solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +0 -154
- solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +0 -69
- solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +0 -49
- solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +0 -124
- solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +0 -10
- solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +0 -35
- solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +0 -42
- solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +0 -28
- solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +0 -108
- solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +0 -23
- solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +0 -7
- solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +0 -166
- solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +0 -18
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +0 -240
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +0 -86
- solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +0 -12
- solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +0 -1
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +0 -171
- solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
- solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +0 -45
- solara/website/pages/documentation/advanced/content/40-development/10-setup.md +0 -76
- solara/website/pages/documentation/api/__init__.py +0 -19
- solara/website/pages/documentation/api/cross_filter/__init__.py +0 -9
- solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +0 -23
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +0 -22
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +0 -22
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +0 -22
- solara/website/pages/documentation/api/hooks/__init__.py +0 -9
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +0 -25
- solara/website/pages/documentation/api/hooks/use_dark_effective.py +0 -13
- solara/website/pages/documentation/api/hooks/use_effect.md +0 -43
- solara/website/pages/documentation/api/hooks/use_effect.py +0 -9
- solara/website/pages/documentation/api/hooks/use_exception.py +0 -33
- solara/website/pages/documentation/api/hooks/use_memo.md +0 -16
- solara/website/pages/documentation/api/hooks/use_memo.py +0 -9
- solara/website/pages/documentation/api/hooks/use_previous.py +0 -32
- solara/website/pages/documentation/api/hooks/use_reactive.py +0 -15
- solara/website/pages/documentation/api/hooks/use_state.py +0 -11
- solara/website/pages/documentation/api/hooks/use_state_or_update.py +0 -68
- solara/website/pages/documentation/api/hooks/use_thread.md +0 -58
- solara/website/pages/documentation/api/hooks/use_thread.py +0 -44
- solara/website/pages/documentation/api/hooks/use_trait_observe.py +0 -13
- solara/website/pages/documentation/api/routing/__init__.py +0 -9
- solara/website/pages/documentation/api/routing/generate_routes.py +0 -11
- solara/website/pages/documentation/api/routing/generate_routes_directory.py +0 -11
- solara/website/pages/documentation/api/routing/resolve_path.py +0 -36
- solara/website/pages/documentation/api/routing/route.py +0 -32
- solara/website/pages/documentation/api/routing/use_route.py +0 -80
- solara/website/pages/documentation/api/routing/use_router.py +0 -15
- solara/website/pages/documentation/api/utilities/__init__.py +0 -9
- solara/website/pages/documentation/api/utilities/component_vue.py +0 -11
- solara/website/pages/documentation/api/utilities/computed.py +0 -16
- solara/website/pages/documentation/api/utilities/display.py +0 -15
- solara/website/pages/documentation/api/utilities/get_kernel_id.py +0 -16
- solara/website/pages/documentation/api/utilities/get_session_id.py +0 -16
- solara/website/pages/documentation/api/utilities/memoize.py +0 -36
- solara/website/pages/documentation/api/utilities/on_kernel_start.py +0 -27
- solara/website/pages/documentation/api/utilities/reactive.py +0 -15
- solara/website/pages/documentation/api/utilities/widget.py +0 -104
- solara/website/pages/documentation/components/__init__.py +0 -12
- solara/website/pages/documentation/components/advanced/__init__.py +0 -9
- solara/website/pages/documentation/components/advanced/link.py +0 -28
- solara/website/pages/documentation/components/advanced/meta.py +0 -21
- solara/website/pages/documentation/components/advanced/style.py +0 -44
- solara/website/pages/documentation/components/common.py +0 -9
- solara/website/pages/documentation/components/data/__init__.py +0 -9
- solara/website/pages/documentation/components/data/dataframe.py +0 -44
- solara/website/pages/documentation/components/data/pivot_table.py +0 -81
- solara/website/pages/documentation/components/enterprise/__init__.py +0 -9
- solara/website/pages/documentation/components/enterprise/avatar.py +0 -19
- solara/website/pages/documentation/components/enterprise/avatar_menu.py +0 -20
- solara/website/pages/documentation/components/input/__init__.py +0 -9
- solara/website/pages/documentation/components/input/button.py +0 -22
- solara/website/pages/documentation/components/input/checkbox.py +0 -12
- solara/website/pages/documentation/components/input/file_browser.py +0 -33
- solara/website/pages/documentation/components/input/file_drop.py +0 -75
- solara/website/pages/documentation/components/input/input.py +0 -18
- solara/website/pages/documentation/components/input/select.py +0 -21
- solara/website/pages/documentation/components/input/slider.py +0 -28
- solara/website/pages/documentation/components/input/switch.py +0 -12
- solara/website/pages/documentation/components/input/togglebuttons.py +0 -20
- solara/website/pages/documentation/components/lab/__init__.py +0 -9
- solara/website/pages/documentation/components/lab/chat.py +0 -108
- solara/website/pages/documentation/components/lab/confirmation_dialog.py +0 -55
- solara/website/pages/documentation/components/lab/cookies_headers.py +0 -48
- solara/website/pages/documentation/components/lab/input_date.py +0 -19
- solara/website/pages/documentation/components/lab/menu.py +0 -21
- solara/website/pages/documentation/components/lab/tab.py +0 -24
- solara/website/pages/documentation/components/lab/tabs.py +0 -44
- solara/website/pages/documentation/components/lab/task.py +0 -12
- solara/website/pages/documentation/components/lab/theming.py +0 -72
- solara/website/pages/documentation/components/lab/use_task.py +0 -12
- solara/website/pages/documentation/components/layout/__init__.py +0 -9
- solara/website/pages/documentation/components/layout/app_bar.py +0 -15
- solara/website/pages/documentation/components/layout/app_bar_title.py +0 -15
- solara/website/pages/documentation/components/layout/app_layout.py +0 -23
- solara/website/pages/documentation/components/layout/card.py +0 -14
- solara/website/pages/documentation/components/layout/card_actions.py +0 -15
- solara/website/pages/documentation/components/layout/column.py +0 -29
- solara/website/pages/documentation/components/layout/columns.py +0 -26
- solara/website/pages/documentation/components/layout/columns_responsive.py +0 -67
- solara/website/pages/documentation/components/layout/griddraggable.py +0 -61
- solara/website/pages/documentation/components/layout/gridfixed.py +0 -21
- solara/website/pages/documentation/components/layout/hbox.py +0 -17
- solara/website/pages/documentation/components/layout/row.py +0 -29
- solara/website/pages/documentation/components/layout/sidebar.py +0 -23
- solara/website/pages/documentation/components/layout/vbox.py +0 -19
- solara/website/pages/documentation/components/output/__init__.py +0 -9
- solara/website/pages/documentation/components/output/file_download.py +0 -12
- solara/website/pages/documentation/components/output/html.py +0 -22
- solara/website/pages/documentation/components/output/image.py +0 -12
- solara/website/pages/documentation/components/output/markdown.py +0 -59
- solara/website/pages/documentation/components/output/markdown_editor.py +0 -53
- solara/website/pages/documentation/components/output/sql_code.py +0 -84
- solara/website/pages/documentation/components/output/tooltip.py +0 -12
- solara/website/pages/documentation/components/page/__init__.py +0 -9
- solara/website/pages/documentation/components/page/head.py +0 -19
- solara/website/pages/documentation/components/page/title.py +0 -28
- solara/website/pages/documentation/components/status/__init__.py +0 -9
- solara/website/pages/documentation/components/status/error.py +0 -40
- solara/website/pages/documentation/components/status/info.py +0 -40
- solara/website/pages/documentation/components/status/progress.py +0 -10
- solara/website/pages/documentation/components/status/spinner.py +0 -10
- solara/website/pages/documentation/components/status/success.py +0 -40
- solara/website/pages/documentation/components/status/warning.py +0 -47
- solara/website/pages/documentation/components/viz/__init__.py +0 -9
- solara/website/pages/documentation/components/viz/altair.py +0 -44
- solara/website/pages/documentation/components/viz/echarts.py +0 -78
- solara/website/pages/documentation/components/viz/matplotlib.py +0 -32
- solara/website/pages/documentation/components/viz/plotly.py +0 -63
- solara/website/pages/documentation/components/viz/plotly_express.py +0 -41
- solara/website/pages/documentation/examples/__init__.py +0 -52
- solara/website/pages/documentation/examples/ai/__init__.py +0 -10
- solara/website/pages/documentation/examples/ai/chatbot.py +0 -96
- solara/website/pages/documentation/examples/ai/tokenizer.py +0 -106
- solara/website/pages/documentation/examples/basics/__init__.py +0 -2
- solara/website/pages/documentation/examples/basics/sine.py +0 -28
- solara/website/pages/documentation/examples/fullscreen/__init__.py +0 -9
- solara/website/pages/documentation/examples/fullscreen/authorization.py +0 -3
- solara/website/pages/documentation/examples/fullscreen/layout_demo.py +0 -3
- solara/website/pages/documentation/examples/fullscreen/multipage.py +0 -3
- solara/website/pages/documentation/examples/fullscreen/scatter.py +0 -3
- solara/website/pages/documentation/examples/fullscreen/scrolling.py +0 -3
- solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +0 -3
- solara/website/pages/documentation/examples/general/__init__.py +0 -9
- solara/website/pages/documentation/examples/general/custom_storage.py +0 -69
- solara/website/pages/documentation/examples/general/deploy_model.py +0 -114
- solara/website/pages/documentation/examples/general/live_update.py +0 -38
- solara/website/pages/documentation/examples/general/login_oauth.py +0 -76
- solara/website/pages/documentation/examples/general/mycard.vue +0 -58
- solara/website/pages/documentation/examples/general/pokemon_search.py +0 -51
- solara/website/pages/documentation/examples/general/vue_component.py +0 -50
- solara/website/pages/documentation/examples/ipycanvas.py +0 -49
- solara/website/pages/documentation/examples/libraries/__init__.py +0 -9
- solara/website/pages/documentation/examples/libraries/altair.py +0 -63
- solara/website/pages/documentation/examples/libraries/bqplot.py +0 -39
- solara/website/pages/documentation/examples/libraries/ipyleaflet.py +0 -32
- solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +0 -65
- solara/website/pages/documentation/examples/utilities/__init__.py +0 -9
- solara/website/pages/documentation/examples/utilities/calculator.py +0 -157
- solara/website/pages/documentation/examples/utilities/countdown_timer.py +0 -64
- solara/website/pages/documentation/examples/utilities/todo.py +0 -195
- solara/website/pages/documentation/examples/visualization/__init__.py +0 -6
- solara/website/pages/documentation/examples/visualization/annotator.py +0 -68
- solara/website/pages/documentation/examples/visualization/linked_views.py +0 -84
- solara/website/pages/documentation/examples/visualization/plotly.py +0 -43
- solara/website/pages/documentation/faq/__init__.py +0 -12
- solara/website/pages/documentation/faq/content/99-faq.md +0 -76
- solara/website/pages/documentation/getting_started/__init__.py +0 -9
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +0 -89
- solara/website/pages/documentation/getting_started/content/01-introduction.md +0 -125
- solara/website/pages/documentation/getting_started/content/02-installing.md +0 -85
- solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +0 -14
- solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +0 -13
- solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +0 -89
- solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +0 -124
- solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +0 -146
- solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +0 -144
- solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +0 -64
- 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 +0 -445
- solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +0 -1000
- solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +0 -11
- solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +0 -223
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +0 -88
- solara/website/pages/documentation/getting_started/content/06-reference/00-overview.md +0 -3
- solara/website/pages/documentation/getting_started/content/06-reference/40-static_files.md +0 -31
- solara/website/pages/documentation/getting_started/content/06-reference/41-asset-files.md +0 -36
- solara/website/pages/documentation/getting_started/content/06-reference/60-static-site-generation.md +0 -59
- solara/website/pages/documentation/getting_started/content/06-reference/70-search.md +0 -34
- solara/website/pages/documentation/getting_started/content/06-reference/80-reloading.md +0 -34
- solara/website/pages/documentation/getting_started/content/06-reference/90-notebook-support.md +0 -7
- solara/website/pages/documentation/getting_started/content/06-reference/95-caching.md +0 -148
- solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +0 -7
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +0 -273
- solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +0 -80
- solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +0 -7
- solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +0 -26
- solara/website/pages/docutils.py +0 -38
- solara/website/pages/showcase/__init__.py +0 -105
- solara/website/pages/showcase/domino_code_assist.py +0 -60
- solara/website/pages/showcase/planeto_tessa.py +0 -19
- solara/website/pages/showcase/solara_dev.py +0 -54
- solara/website/pages/showcase/solarathon_2023_team_2.py +0 -22
- solara/website/pages/showcase/solarathon_2023_team_4.py +0 -22
- solara/website/pages/showcase/solarathon_2023_team_5.py +0 -23
- solara/website/pages/showcase/solarathon_2023_team_6.py +0 -34
- solara/website/pages/showcase/wanderlust.py +0 -27
- solara/website/public/beach.jpeg +0 -0
- solara/website/public/logo.svg +0 -6
- solara/website/public/social/discord.svg +0 -1
- solara/website/public/social/github.svg +0 -1
- solara/website/public/social/twitter.svg +0 -3
- solara/website/public/success.html +0 -25
- solara/website/templates/index.html.j2 +0 -117
- solara/website/utils.py +0 -51
- solara/widgets/__init__.py +0 -1
- solara/widgets/vue/gridlayout.vue +0 -110
- solara/widgets/vue/html.vue +0 -4
- solara/widgets/vue/navigator.vue +0 -104
- solara/widgets/vue/vegalite.vue +0 -115
- solara/widgets/widgets.py +0 -65
- solara-1.30.1.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -7
- solara-1.30.1.data/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -7
- solara-1.30.1.dist-info/RECORD +0 -437
- solara-1.30.1.dist-info/entry_points.txt +0 -5
- /solara-1.30.1.dist-info/licenses/LICENSE → /LICENSE +0 -0
solara/alias.py
DELETED
solara/autorouting.py
DELETED
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import difflib
|
|
3
|
-
import importlib
|
|
4
|
-
import inspect
|
|
5
|
-
import pkgutil
|
|
6
|
-
import re
|
|
7
|
-
import warnings
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from types import ModuleType
|
|
10
|
-
from typing import Any, Callable, Dict, List, Optional, cast
|
|
11
|
-
|
|
12
|
-
import ipywidgets
|
|
13
|
-
import reacton
|
|
14
|
-
import reacton.core
|
|
15
|
-
|
|
16
|
-
import solara
|
|
17
|
-
import solara.checks
|
|
18
|
-
from solara.alias import rv
|
|
19
|
-
from solara.util import cwd, nested_get
|
|
20
|
-
|
|
21
|
-
autoroute_level_context = solara.create_context(0)
|
|
22
|
-
DEBUG = False
|
|
23
|
-
|
|
24
|
-
solara_root = Path(solara.__file__).parent
|
|
25
|
-
|
|
26
|
-
DefaultLayout = solara.AppLayout
|
|
27
|
-
_redirects: Dict[str, str] = {}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def source_to_module(path: Path, initial_namespace={}) -> ModuleType:
|
|
31
|
-
fullname = path.stem
|
|
32
|
-
mod = ModuleType(fullname)
|
|
33
|
-
mod.__file__ = str(path)
|
|
34
|
-
mod.__dict__.update(initial_namespace)
|
|
35
|
-
if path.suffix == ".py":
|
|
36
|
-
with open(path, encoding="utf8") as f:
|
|
37
|
-
ast = compile(f.read(), path, "exec")
|
|
38
|
-
exec(ast, mod.__dict__)
|
|
39
|
-
elif path.suffix == ".ipynb":
|
|
40
|
-
import nbformat
|
|
41
|
-
|
|
42
|
-
nb: nbformat.NotebookNode = nbformat.read(path, 4)
|
|
43
|
-
with cwd(Path(path).parent):
|
|
44
|
-
for cell_index, cell in enumerate(nb.cells):
|
|
45
|
-
cell_index += 1 # used 1 based
|
|
46
|
-
if cell.cell_type == "code":
|
|
47
|
-
source = cell.source
|
|
48
|
-
cell_path = f"{path} input cell {cell_index}"
|
|
49
|
-
ast = compile(source, cell_path, "exec")
|
|
50
|
-
exec(ast, mod.__dict__)
|
|
51
|
-
else:
|
|
52
|
-
raise TypeError(f"Only .py and .ipynb supported (not {path})")
|
|
53
|
-
return mod
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def count_arguments(f: Callable):
|
|
57
|
-
if isinstance(f, reacton.core.ComponentFunction):
|
|
58
|
-
f = f.f
|
|
59
|
-
sig = inspect.signature(f)
|
|
60
|
-
return len([k for name, k in sig.parameters.items() if (k.default == k.empty) and (k.kind != k.VAR_POSITIONAL) and (k.kind != k.VAR_KEYWORD)])
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def arg_cast(args: List[str], f: Callable):
|
|
64
|
-
if isinstance(f, reacton.core.ComponentFunction):
|
|
65
|
-
f = f.f
|
|
66
|
-
sig = inspect.signature(f)
|
|
67
|
-
results = []
|
|
68
|
-
for i, (name, param) in enumerate(sig.parameters.items()):
|
|
69
|
-
if i >= len(args):
|
|
70
|
-
break
|
|
71
|
-
# TODO: can we give a better error message?
|
|
72
|
-
# raise TypeError(f"{f} expected positional argument {param}, but not enough argument supplied")
|
|
73
|
-
annotation = param.annotation
|
|
74
|
-
value = args[i]
|
|
75
|
-
check_optional_types = [str, int, float]
|
|
76
|
-
for check_type in check_optional_types:
|
|
77
|
-
if annotation == Optional[check_type]:
|
|
78
|
-
annotation = check_type
|
|
79
|
-
if annotation == param.empty:
|
|
80
|
-
results.append(value)
|
|
81
|
-
else:
|
|
82
|
-
try:
|
|
83
|
-
results.append(annotation(value))
|
|
84
|
-
except Exception as e:
|
|
85
|
-
raise ValueError(f"Cannot cast argument {name} of {f} to type {annotation} with value {value}") from e
|
|
86
|
-
return results
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@solara.component
|
|
90
|
-
def RoutingProvider(children: List[reacton.core.Element] = [], routes: List[solara.Route] = [], pathname: str = ""):
|
|
91
|
-
"""Wraps the app, adds extra context, like navigation/routing."""
|
|
92
|
-
path, set_path = solara.use_state(pathname, key="solara-context-path")
|
|
93
|
-
|
|
94
|
-
def set_path_with_redirect(path):
|
|
95
|
-
path = _redirects.get(path, path)
|
|
96
|
-
set_path(path)
|
|
97
|
-
|
|
98
|
-
# TODO: since we provide a cross filter context here, I don't think name `RoutingProvider` is a good name
|
|
99
|
-
# we might want to change/refactor this.
|
|
100
|
-
solara.provide_cross_filter()
|
|
101
|
-
nav = solara.Navigator(location=path, on_location=set_path_with_redirect)
|
|
102
|
-
solara.routing._location_context.provide(solara.routing._Location(path, set_path_with_redirect))
|
|
103
|
-
solara.routing.router_context.provide(solara.routing.Router(path, routes=routes, set_path=set_path_with_redirect))
|
|
104
|
-
|
|
105
|
-
def get_nav_widget():
|
|
106
|
-
# not sure why get_widget(nav) does not work
|
|
107
|
-
nav_widget.current = solara.get_widget(main).children[0] # type: ignore
|
|
108
|
-
|
|
109
|
-
import solara.widgets as w
|
|
110
|
-
|
|
111
|
-
nav_widget = solara.use_ref(cast(Optional[w.Navigator], None))
|
|
112
|
-
if nav_widget.current:
|
|
113
|
-
nav_widget.current.location = path
|
|
114
|
-
solara.use_effect(get_nav_widget)
|
|
115
|
-
|
|
116
|
-
if solara.checks.should_perform_solara_check():
|
|
117
|
-
children = [solara.checks.SolaraCheck(), *children]
|
|
118
|
-
|
|
119
|
-
main = solara.VBox(
|
|
120
|
-
children=[
|
|
121
|
-
nav,
|
|
122
|
-
*children,
|
|
123
|
-
]
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
return main
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@solara.component
|
|
130
|
-
def RenderPage(main_name: str = "Page"):
|
|
131
|
-
"""Renders the page that matches the route."""
|
|
132
|
-
router = solara.use_context(solara.routing.router_context)
|
|
133
|
-
# we use these to cache script runs that use regular ipywidgets
|
|
134
|
-
modules = cast(Dict[str, ModuleType], solara.use_memo(dict, dependencies=[]))
|
|
135
|
-
modules_modified_times = cast(Dict[str, float], solara.use_memo(dict, dependencies=[]))
|
|
136
|
-
|
|
137
|
-
if not router.path_routes:
|
|
138
|
-
with solara.VBox() as main:
|
|
139
|
-
solara.Error(f"Page not found: {router.path}")
|
|
140
|
-
parent = "/" + "/".join(router.parts[:-1])
|
|
141
|
-
with solara.Link(parent):
|
|
142
|
-
solara.Button(f"Go to parent: {parent}", text=True)
|
|
143
|
-
if DEBUG:
|
|
144
|
-
from reacton.core import pp
|
|
145
|
-
|
|
146
|
-
from solara.components.captureoutput import CaptureOutput
|
|
147
|
-
|
|
148
|
-
with CaptureOutput():
|
|
149
|
-
pp(router.routes)
|
|
150
|
-
return main
|
|
151
|
-
|
|
152
|
-
layouts = [] # nested layouts
|
|
153
|
-
level_max = len(router.path_routes) - 1
|
|
154
|
-
for level in range(len(router.path_routes)):
|
|
155
|
-
# we always level_start the 'package'/'root' layout
|
|
156
|
-
roots = [k for k in router.path_routes_siblings[level] if k.path == "/"]
|
|
157
|
-
if len(roots) == 1:
|
|
158
|
-
root = roots[0]
|
|
159
|
-
if root.layout:
|
|
160
|
-
layouts.append(root.layout)
|
|
161
|
-
route = router.path_routes[level]
|
|
162
|
-
# and, if not the root layout, include the layout for the current route
|
|
163
|
-
if route.path != "/" and route.layout:
|
|
164
|
-
layouts.append(route.layout)
|
|
165
|
-
# We found the leaf (or node) that defines a component or markdown file
|
|
166
|
-
if (route.file and route.file.suffix == ".md") or route.component:
|
|
167
|
-
level_max = level
|
|
168
|
-
break
|
|
169
|
-
|
|
170
|
-
route_current = router.path_routes[level_max]
|
|
171
|
-
routes_siblings = router.path_routes_siblings[level_max]
|
|
172
|
-
routes_siblings_index = routes_siblings.index(route_current)
|
|
173
|
-
|
|
174
|
-
# if no layouts are found, we use the default layout
|
|
175
|
-
if layouts == []:
|
|
176
|
-
layouts = [DefaultLayout]
|
|
177
|
-
|
|
178
|
-
if route_current.component is None and route_current.module is None and (route_current.file is None or route_current.file.suffix != ".md"):
|
|
179
|
-
return solara.Error(f"Page not found: {router.path}, route does not link to a (markdown) path or module or component")
|
|
180
|
-
|
|
181
|
-
def wrap_in_layouts(element: reacton.core.Element, layouts):
|
|
182
|
-
for Layout in reversed(layouts):
|
|
183
|
-
element = Layout(children=[element])
|
|
184
|
-
return element
|
|
185
|
-
|
|
186
|
-
def get_args(f):
|
|
187
|
-
if len(router.path_routes) < len(router.parts):
|
|
188
|
-
arg_strings = router.parts[len(router.path_routes) :]
|
|
189
|
-
args = arg_cast(arg_strings, f)
|
|
190
|
-
return args
|
|
191
|
-
else:
|
|
192
|
-
return []
|
|
193
|
-
|
|
194
|
-
if str(route_current.file).endswith(".md") or isinstance(route_current.data, Path):
|
|
195
|
-
path = cast(Path, route_current.data)
|
|
196
|
-
if path.suffix == ".md":
|
|
197
|
-
component = route_current.component or solara.Markdown
|
|
198
|
-
with solara.HBox() as navigation:
|
|
199
|
-
if routes_siblings_index > 0:
|
|
200
|
-
prev = routes_siblings[routes_siblings_index - 1]
|
|
201
|
-
with solara.Link(prev):
|
|
202
|
-
solara.Button(f"{prev.label}", text=True, icon_name="mdi-arrow-left")
|
|
203
|
-
rv.Spacer()
|
|
204
|
-
if routes_siblings_index < len(routes_siblings) - 1:
|
|
205
|
-
next = routes_siblings[routes_siblings_index + 1]
|
|
206
|
-
with solara.Link(next):
|
|
207
|
-
solara.Button(f"{next.label}", text=True, icon_name="mdi-arrow-right")
|
|
208
|
-
is_relative = str(path.resolve()).startswith(str(solara_root.resolve()))
|
|
209
|
-
if is_relative:
|
|
210
|
-
# this is now hardcoded to solara only
|
|
211
|
-
url = solara.util.github_edit_url(path)
|
|
212
|
-
with solara.Div(style={"position": "relative"}) as content:
|
|
213
|
-
with solara.Tooltip("Edit on GitHub"):
|
|
214
|
-
solara.Button(
|
|
215
|
-
icon_name="mdi-pencil", icon=True, href=url, target="_blank", style={"position": "absolute", "top": "0px", "right": "0px"}
|
|
216
|
-
)
|
|
217
|
-
# solara.Markdown(path.read_text(), unsafe_solara_execute=True)
|
|
218
|
-
component(path.read_text(), unsafe_solara_execute=True)
|
|
219
|
-
else:
|
|
220
|
-
# content = solara.Markdown(path.read_text(), unsafe_solara_execute=True)
|
|
221
|
-
content = component(path.read_text(), unsafe_solara_execute=True)
|
|
222
|
-
|
|
223
|
-
main = solara.Div(
|
|
224
|
-
classes=["solara-autorouter-content"],
|
|
225
|
-
children=[
|
|
226
|
-
solara.Title(route_current.label or "No title"),
|
|
227
|
-
content,
|
|
228
|
-
navigation,
|
|
229
|
-
],
|
|
230
|
-
)
|
|
231
|
-
main = wrap_in_layouts(main, layouts)
|
|
232
|
-
else:
|
|
233
|
-
main = solara.Error(f"Suffix {path.suffix} not supported")
|
|
234
|
-
else:
|
|
235
|
-
title = route_current.label or "No title"
|
|
236
|
-
title_element = solara.Title(title)
|
|
237
|
-
module = None
|
|
238
|
-
Page = route_current.component
|
|
239
|
-
if route_current.module is not None and (Page is None):
|
|
240
|
-
# if not a custom component is given, we try to find a Page component
|
|
241
|
-
# in the module
|
|
242
|
-
assert route_current.module is not None
|
|
243
|
-
module = route_current.module
|
|
244
|
-
namespace = module.__dict__
|
|
245
|
-
Page = nested_get(namespace, main_name, Page)
|
|
246
|
-
if Page is None:
|
|
247
|
-
# app is for backwards compatibility
|
|
248
|
-
Page = namespace.get("page", namespace.get("app", Page))
|
|
249
|
-
Page = nested_get(namespace, main_name, Page)
|
|
250
|
-
|
|
251
|
-
if isinstance(Page, ipywidgets.Widget):
|
|
252
|
-
# If we have a widget, we need to execute this again for each
|
|
253
|
-
# connection, since we cannot share widgets between connections/users.
|
|
254
|
-
# We also cannot tear them down, so we cache the widget based pages.
|
|
255
|
-
# To support hot reload, we manually need to check the mtimes
|
|
256
|
-
# because the reload support for modules in reloader.py only works
|
|
257
|
-
# for modules.
|
|
258
|
-
if route_current.file is None:
|
|
259
|
-
page = solara.Error(f"{route_current.path} is not associated with a file")
|
|
260
|
-
else:
|
|
261
|
-
assert route_current.file is not None
|
|
262
|
-
if route_current.path not in modules:
|
|
263
|
-
modules[route_current.path] = source_to_module(route_current.file)
|
|
264
|
-
modules_modified_times[route_current.path] = route_current.file.stat().st_mtime
|
|
265
|
-
else:
|
|
266
|
-
if modules_modified_times[route_current.path] != route_current.file.stat().st_mtime:
|
|
267
|
-
# out of date, 'reload'
|
|
268
|
-
modules[route_current.path] = source_to_module(route_current.file)
|
|
269
|
-
modules_modified_times[route_current.path] = route_current.file.stat().st_mtime
|
|
270
|
-
Page = nested_get(modules[route_current.path], main_name, None)
|
|
271
|
-
if Page is None:
|
|
272
|
-
Page = getattr(modules[route_current.path], "app", None)
|
|
273
|
-
Page = getattr(modules[route_current.path], "page", Page)
|
|
274
|
-
main = solara.Div(
|
|
275
|
-
classes=["solara-autorouter-content"],
|
|
276
|
-
children=[
|
|
277
|
-
title_element,
|
|
278
|
-
Page,
|
|
279
|
-
],
|
|
280
|
-
)
|
|
281
|
-
main = wrap_in_layouts(main, layouts)
|
|
282
|
-
elif Page is not None:
|
|
283
|
-
if isinstance(Page, reacton.core.ComponentFunction):
|
|
284
|
-
args = get_args(Page)
|
|
285
|
-
page = Page(*args)
|
|
286
|
-
elif isinstance(Page, solara.Element):
|
|
287
|
-
page = Page
|
|
288
|
-
else:
|
|
289
|
-
page = solara.Error(f"{Page} is not a component or element, but {type(Page)}")
|
|
290
|
-
main = solara.Div(
|
|
291
|
-
classes=["solara-autorouter-content"],
|
|
292
|
-
children=[
|
|
293
|
-
title_element,
|
|
294
|
-
page,
|
|
295
|
-
],
|
|
296
|
-
)
|
|
297
|
-
main = wrap_in_layouts(main, layouts)
|
|
298
|
-
else:
|
|
299
|
-
if route_current.module:
|
|
300
|
-
path_str = route_current.module.__file__
|
|
301
|
-
local_scope = route_current.module.__dict__
|
|
302
|
-
ignore = ["display"]
|
|
303
|
-
options = [k for k in list(local_scope) if k not in ignore and not k.startswith("_")]
|
|
304
|
-
matches = difflib.get_close_matches(main_name, options)
|
|
305
|
-
msg = f"No object with name {main_name} found for {path_str}"
|
|
306
|
-
if matches:
|
|
307
|
-
msg += " Did you mean: " + " or ".join(map(repr, matches))
|
|
308
|
-
else:
|
|
309
|
-
msg += " We did find: " + " or ".join(map(repr, options))
|
|
310
|
-
else:
|
|
311
|
-
msg = f"{module} does not have a Page component or an app element"
|
|
312
|
-
|
|
313
|
-
with DefaultLayout() as main:
|
|
314
|
-
solara.Error(msg)
|
|
315
|
-
return main
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
def get_page(module: ModuleType, required=True):
|
|
319
|
-
page = getattr(module, "Page", None)
|
|
320
|
-
if required and page is None:
|
|
321
|
-
raise NameError(f"No component names 'Page' in module {module}")
|
|
322
|
-
return page
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
def get_renderable(module: ModuleType, required=False):
|
|
326
|
-
var_names = "app Page page".split()
|
|
327
|
-
for var_name in var_names:
|
|
328
|
-
if not hasattr(module, var_name):
|
|
329
|
-
continue
|
|
330
|
-
entry = getattr(module, var_name)
|
|
331
|
-
return entry
|
|
332
|
-
if required:
|
|
333
|
-
raise NameError(f"No component, element or widget found in module {module} with names: {', '.join(var_names[:-1])} or {var_names[-1]}")
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def get_title(module: ModuleType, required=True):
|
|
337
|
-
assert module.__file__ is not None
|
|
338
|
-
name = Path(module.__file__).stem
|
|
339
|
-
if module.__file__.endswith("__init__.py"):
|
|
340
|
-
name = Path(module.__file__).parent.stem
|
|
341
|
-
# if title is a submodule it may shadown the variable in __init__
|
|
342
|
-
# in this case, _title is an escape hatch
|
|
343
|
-
if hasattr(module, "_title") and isinstance(module._title, str):
|
|
344
|
-
title = module._title
|
|
345
|
-
elif hasattr(module, "title") and isinstance(module.title, str):
|
|
346
|
-
title = module.title
|
|
347
|
-
else:
|
|
348
|
-
match = re.match("([0-9\\-_ ]*)(.*)", name)
|
|
349
|
-
if match:
|
|
350
|
-
_prefix, name = match.groups()
|
|
351
|
-
title_parts = re.split("[\\-_ ]+", name)
|
|
352
|
-
title = " ".join(k.title() for k in title_parts)
|
|
353
|
-
return title
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
def fix_route(route: solara.Route, new_file: Path, new_layout=None) -> solara.Route:
|
|
357
|
-
file = route.file or new_file
|
|
358
|
-
layout = route.layout or new_layout
|
|
359
|
-
children = fix_routes(route.children, new_file) if route.children else []
|
|
360
|
-
|
|
361
|
-
return dataclasses.replace(route, file=file, children=children, layout=layout)
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
def fix_routes(routes: List[solara.Route], new_file: Path, new_layout=None):
|
|
365
|
-
new_routes = []
|
|
366
|
-
for route in routes:
|
|
367
|
-
if route.path == "/":
|
|
368
|
-
route = fix_route(route, new_file, new_layout)
|
|
369
|
-
else:
|
|
370
|
-
route = fix_route(route, new_file)
|
|
371
|
-
new_routes.append(route)
|
|
372
|
-
return new_routes
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
def generate_routes(module: ModuleType) -> List[solara.Route]:
|
|
376
|
-
"""Generate routes from a module.
|
|
377
|
-
|
|
378
|
-
This is a recursive function that will generate routes for all submodules.
|
|
379
|
-
|
|
380
|
-
Note this only support .py files, since Markdown files and Jupyter notebook
|
|
381
|
-
files are not Python modules.
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
See [our multipage guide](/documentation/advanced/howto/multipage#as-a-package) for more details.
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
"""
|
|
388
|
-
from .server import reload
|
|
389
|
-
|
|
390
|
-
assert module.__file__ is not None
|
|
391
|
-
routes = []
|
|
392
|
-
children: List[solara.Route]
|
|
393
|
-
file = Path(module.__file__)
|
|
394
|
-
|
|
395
|
-
if module.__file__.endswith("__init__.py"):
|
|
396
|
-
if hasattr(module, "routes"):
|
|
397
|
-
# if routes if provided, use them instead of us generating them
|
|
398
|
-
children = getattr(module, "routes")
|
|
399
|
-
children = fix_routes(children, file)
|
|
400
|
-
return children
|
|
401
|
-
route_order = getattr(module, "route_order", None)
|
|
402
|
-
layout = getattr(module, "Layout", None)
|
|
403
|
-
title = get_title(module)
|
|
404
|
-
children = getattr(module, "routes", [])
|
|
405
|
-
if hasattr(module, "Page"):
|
|
406
|
-
routes.append(
|
|
407
|
-
solara.Route(path="/", component=get_page(module), data=module, module=module, layout=layout, children=children, label=title, file=file)
|
|
408
|
-
)
|
|
409
|
-
|
|
410
|
-
assert module.__file__ is not None
|
|
411
|
-
reload.reloader.watcher.add_file(module.__file__)
|
|
412
|
-
for info in pkgutil.iter_modules([str(Path(module.__file__).parent)]):
|
|
413
|
-
submod = importlib.import_module(module.__name__ + f".{info.name}")
|
|
414
|
-
title = get_title(submod)
|
|
415
|
-
|
|
416
|
-
name = info.name
|
|
417
|
-
# ideally, we do this similar to generate_routes_directory
|
|
418
|
-
# however, this may break things.
|
|
419
|
-
# name = name.replace("_", "-")
|
|
420
|
-
if info.ispkg:
|
|
421
|
-
# we are in a package, like 'portal/solara_portal/pages', not the module itself
|
|
422
|
-
# (e.g. portal/solara_portal/pages/__init__.py)
|
|
423
|
-
# so here name='pages', and the children will come from the submodules
|
|
424
|
-
children = generate_routes(submod)
|
|
425
|
-
route = solara.Route(name, component=None, children=children, module=submod, layout=None, label=title)
|
|
426
|
-
# skip empty subpackages
|
|
427
|
-
if len(route.children) == 0:
|
|
428
|
-
continue
|
|
429
|
-
else:
|
|
430
|
-
# skip empty modules
|
|
431
|
-
if get_renderable(submod) is None and not hasattr(submod, "routes"):
|
|
432
|
-
continue
|
|
433
|
-
route = _generate_route(name, submod)
|
|
434
|
-
routes.append(route)
|
|
435
|
-
if route_order:
|
|
436
|
-
lookup = {k.path: k for k in routes}
|
|
437
|
-
for k in route_order:
|
|
438
|
-
if k not in lookup:
|
|
439
|
-
raise KeyError(f"Route {k!r} listen in route_order not found in {module}")
|
|
440
|
-
routes = [lookup[k] for k in route_order]
|
|
441
|
-
if set(lookup) - set(route_order):
|
|
442
|
-
warnings.warn(f"Some routes are not in route_order: {set(lookup) - set(route_order)}")
|
|
443
|
-
|
|
444
|
-
else:
|
|
445
|
-
return [_generate_route("/", module)]
|
|
446
|
-
|
|
447
|
-
return routes
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
def generate_routes_directory(path: Path, markdown_component=None) -> List[solara.Route]:
|
|
451
|
-
"""Generate routes for a directory.
|
|
452
|
-
|
|
453
|
-
This is a recursive function that will generate routes for all
|
|
454
|
-
subdirectories and files in the directory. It will skip any
|
|
455
|
-
files or directories that start with an underscore or a dot.
|
|
456
|
-
|
|
457
|
-
Markdown files ending in .md will be rendered as markdown.
|
|
458
|
-
|
|
459
|
-
Python files ending in .py, or Jupyter notebooks ending in .ipynb
|
|
460
|
-
will be executed and its `Page` component will be rendered.
|
|
461
|
-
|
|
462
|
-
Automatic titles will be [generated as explained in the multipage guide](/documentation/advanced/howto/multipage).
|
|
463
|
-
|
|
464
|
-
"""
|
|
465
|
-
|
|
466
|
-
subpaths = list(sorted(path.iterdir()))
|
|
467
|
-
routes = []
|
|
468
|
-
first = True
|
|
469
|
-
has_index = len([k for k in subpaths if k.name == "__init__"]) > 0
|
|
470
|
-
init = path / "__init__.py"
|
|
471
|
-
layout = None
|
|
472
|
-
if init.exists():
|
|
473
|
-
init_module = source_to_module(init)
|
|
474
|
-
layout = getattr(init_module, "Layout", None)
|
|
475
|
-
|
|
476
|
-
suffixes = [".py", ".ipynb", ".md"]
|
|
477
|
-
for subpath in subpaths:
|
|
478
|
-
# only handle directories and recognized file types
|
|
479
|
-
if not (subpath.is_dir() or subpath.suffix in suffixes):
|
|
480
|
-
continue
|
|
481
|
-
if subpath.stem.startswith("_") or subpath.stem.startswith("."):
|
|
482
|
-
continue
|
|
483
|
-
route = _generate_route_path(subpath, layout=layout, first=first, has_index=has_index, markdown_component=markdown_component)
|
|
484
|
-
first = False
|
|
485
|
-
routes.append(route)
|
|
486
|
-
return routes
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
def _generate_route_path(subpath: Path, layout=None, first=False, has_index=False, initial_namespace={}, markdown_component=None) -> solara.Route:
|
|
490
|
-
from .server import reload
|
|
491
|
-
|
|
492
|
-
name = subpath.stem
|
|
493
|
-
match = re.match("([0-9\\-_ ]*)(.*)", name)
|
|
494
|
-
if match:
|
|
495
|
-
_prefix, name = match.groups()
|
|
496
|
-
title_parts = re.split("[\\-_ ]+", name)
|
|
497
|
-
title = " ".join(k.title() for k in title_parts)
|
|
498
|
-
if not has_index and first:
|
|
499
|
-
route_path = "/"
|
|
500
|
-
else:
|
|
501
|
-
route_path = "-".join([k.lower() for k in title_parts])
|
|
502
|
-
component = None
|
|
503
|
-
children: List[solara.Route] = []
|
|
504
|
-
module: Optional[ModuleType] = None
|
|
505
|
-
data: Any = None
|
|
506
|
-
module_layout = layout if first else None
|
|
507
|
-
if subpath.suffix == ".md":
|
|
508
|
-
data = subpath
|
|
509
|
-
component = markdown_component
|
|
510
|
-
reload.reloader.watcher.add_file(subpath)
|
|
511
|
-
elif subpath.is_dir():
|
|
512
|
-
children = generate_routes_directory(subpath, markdown_component=markdown_component)
|
|
513
|
-
else:
|
|
514
|
-
reload.reloader.watcher.add_file(subpath)
|
|
515
|
-
module = source_to_module(subpath, initial_namespace=initial_namespace)
|
|
516
|
-
return _generate_route(route_path, module, default_layout=module_layout)
|
|
517
|
-
route = solara.Route(route_path, component=component, module=module, label=title, children=children, data=data, layout=layout, file=subpath)
|
|
518
|
-
return route
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
def _generate_route(route_path: str, module: ModuleType, default_layout=None, data=None) -> solara.Route:
|
|
522
|
-
path = Path(module.__file__) if module.__file__ is not None else None
|
|
523
|
-
title = get_title(module)
|
|
524
|
-
layout = getattr(module, "Layout", default_layout)
|
|
525
|
-
if inspect.isclass(layout) and issubclass(layout, ipywidgets.Layout):
|
|
526
|
-
layout = None
|
|
527
|
-
component = None
|
|
528
|
-
children = getattr(module, "routes", [])
|
|
529
|
-
root_route = get_root(children)
|
|
530
|
-
# if we have no children or the children have no explicit root component (at '/')
|
|
531
|
-
if not children or (root_route and root_route.component is None):
|
|
532
|
-
component = get_page(module, required=False)
|
|
533
|
-
if root_route and component and root_route.component and component is not root_route.component:
|
|
534
|
-
warnings.warn(
|
|
535
|
-
f"In {path}, you defined a Page component, but also a component on the root route (with path='/') "
|
|
536
|
-
"which is not equal to the Page component at the module level. This is not recommended."
|
|
537
|
-
)
|
|
538
|
-
return solara.Route(route_path, component=component, module=module, label=title, children=children, data=data, layout=layout, file=path)
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
def get_root(routes: List[solara.Route]) -> Optional[solara.Route]:
|
|
542
|
-
for route in routes:
|
|
543
|
-
if route.path == "/":
|
|
544
|
-
return route
|
|
545
|
-
return None
|