streamlit-nightly 1.43.2.dev20250307__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.
- streamlit/__init__.py +306 -0
- streamlit/__main__.py +20 -0
- streamlit/auth_util.py +218 -0
- streamlit/cli_util.py +105 -0
- streamlit/column_config.py +56 -0
- streamlit/commands/__init__.py +13 -0
- streamlit/commands/echo.py +126 -0
- streamlit/commands/execution_control.py +238 -0
- streamlit/commands/experimental_query_params.py +169 -0
- streamlit/commands/logo.py +189 -0
- streamlit/commands/navigation.py +385 -0
- streamlit/commands/page_config.py +311 -0
- streamlit/components/__init__.py +13 -0
- streamlit/components/lib/__init__.py +13 -0
- streamlit/components/lib/local_component_registry.py +84 -0
- streamlit/components/types/__init__.py +13 -0
- streamlit/components/types/base_component_registry.py +99 -0
- streamlit/components/types/base_custom_component.py +150 -0
- streamlit/components/v1/__init__.py +31 -0
- streamlit/components/v1/component_arrow.py +141 -0
- streamlit/components/v1/component_registry.py +130 -0
- streamlit/components/v1/components.py +38 -0
- streamlit/components/v1/custom_component.py +243 -0
- streamlit/config.py +1513 -0
- streamlit/config_option.py +311 -0
- streamlit/config_util.py +177 -0
- streamlit/connections/__init__.py +28 -0
- streamlit/connections/base_connection.py +174 -0
- streamlit/connections/snowflake_connection.py +562 -0
- streamlit/connections/snowpark_connection.py +213 -0
- streamlit/connections/sql_connection.py +425 -0
- streamlit/connections/util.py +97 -0
- streamlit/cursor.py +210 -0
- streamlit/dataframe_util.py +1416 -0
- streamlit/delta_generator.py +602 -0
- streamlit/delta_generator_singletons.py +204 -0
- streamlit/deprecation_util.py +209 -0
- streamlit/development.py +21 -0
- streamlit/elements/__init__.py +13 -0
- streamlit/elements/alert.py +234 -0
- streamlit/elements/arrow.py +962 -0
- streamlit/elements/balloons.py +47 -0
- streamlit/elements/bokeh_chart.py +133 -0
- streamlit/elements/code.py +114 -0
- streamlit/elements/deck_gl_json_chart.py +546 -0
- streamlit/elements/dialog_decorator.py +267 -0
- streamlit/elements/doc_string.py +558 -0
- streamlit/elements/empty.py +130 -0
- streamlit/elements/exception.py +331 -0
- streamlit/elements/form.py +354 -0
- streamlit/elements/graphviz_chart.py +150 -0
- streamlit/elements/heading.py +302 -0
- streamlit/elements/html.py +105 -0
- streamlit/elements/iframe.py +191 -0
- streamlit/elements/image.py +196 -0
- streamlit/elements/json.py +139 -0
- streamlit/elements/layouts.py +879 -0
- streamlit/elements/lib/__init__.py +13 -0
- streamlit/elements/lib/built_in_chart_utils.py +1157 -0
- streamlit/elements/lib/color_util.py +263 -0
- streamlit/elements/lib/column_config_utils.py +542 -0
- streamlit/elements/lib/column_types.py +2188 -0
- streamlit/elements/lib/dialog.py +147 -0
- streamlit/elements/lib/dicttools.py +154 -0
- streamlit/elements/lib/event_utils.py +37 -0
- streamlit/elements/lib/file_uploader_utils.py +66 -0
- streamlit/elements/lib/form_utils.py +77 -0
- streamlit/elements/lib/image_utils.py +441 -0
- streamlit/elements/lib/js_number.py +105 -0
- streamlit/elements/lib/mutable_status_container.py +183 -0
- streamlit/elements/lib/options_selector_utils.py +250 -0
- streamlit/elements/lib/pandas_styler_utils.py +274 -0
- streamlit/elements/lib/policies.py +194 -0
- streamlit/elements/lib/streamlit_plotly_theme.py +207 -0
- streamlit/elements/lib/subtitle_utils.py +176 -0
- streamlit/elements/lib/utils.py +250 -0
- streamlit/elements/map.py +508 -0
- streamlit/elements/markdown.py +277 -0
- streamlit/elements/media.py +793 -0
- streamlit/elements/metric.py +301 -0
- streamlit/elements/plotly_chart.py +546 -0
- streamlit/elements/progress.py +156 -0
- streamlit/elements/pyplot.py +194 -0
- streamlit/elements/snow.py +47 -0
- streamlit/elements/spinner.py +113 -0
- streamlit/elements/text.py +76 -0
- streamlit/elements/toast.py +98 -0
- streamlit/elements/vega_charts.py +1984 -0
- streamlit/elements/widgets/__init__.py +13 -0
- streamlit/elements/widgets/audio_input.py +310 -0
- streamlit/elements/widgets/button.py +1123 -0
- streamlit/elements/widgets/button_group.py +1008 -0
- streamlit/elements/widgets/camera_input.py +263 -0
- streamlit/elements/widgets/chat.py +647 -0
- streamlit/elements/widgets/checkbox.py +352 -0
- streamlit/elements/widgets/color_picker.py +265 -0
- streamlit/elements/widgets/data_editor.py +983 -0
- streamlit/elements/widgets/file_uploader.py +486 -0
- streamlit/elements/widgets/multiselect.py +338 -0
- streamlit/elements/widgets/number_input.py +545 -0
- streamlit/elements/widgets/radio.py +407 -0
- streamlit/elements/widgets/select_slider.py +437 -0
- streamlit/elements/widgets/selectbox.py +366 -0
- streamlit/elements/widgets/slider.py +880 -0
- streamlit/elements/widgets/text_widgets.py +628 -0
- streamlit/elements/widgets/time_widgets.py +970 -0
- streamlit/elements/write.py +574 -0
- streamlit/emojis.py +34 -0
- streamlit/env_util.py +61 -0
- streamlit/error_util.py +105 -0
- streamlit/errors.py +452 -0
- streamlit/external/__init__.py +13 -0
- streamlit/external/langchain/__init__.py +23 -0
- streamlit/external/langchain/streamlit_callback_handler.py +406 -0
- streamlit/file_util.py +247 -0
- streamlit/git_util.py +173 -0
- streamlit/hello/__init__.py +13 -0
- streamlit/hello/animation_demo.py +82 -0
- streamlit/hello/dataframe_demo.py +71 -0
- streamlit/hello/hello.py +37 -0
- streamlit/hello/mapping_demo.py +114 -0
- streamlit/hello/plotting_demo.py +55 -0
- streamlit/hello/streamlit_app.py +55 -0
- streamlit/hello/utils.py +28 -0
- streamlit/logger.py +130 -0
- streamlit/material_icon_names.py +25 -0
- streamlit/navigation/__init__.py +13 -0
- streamlit/navigation/page.py +302 -0
- streamlit/net_util.py +125 -0
- streamlit/platform.py +33 -0
- streamlit/proto/Alert_pb2.py +29 -0
- streamlit/proto/Alert_pb2.pyi +90 -0
- streamlit/proto/AppPage_pb2.py +27 -0
- streamlit/proto/AppPage_pb2.pyi +64 -0
- streamlit/proto/ArrowNamedDataSet_pb2.py +28 -0
- streamlit/proto/ArrowNamedDataSet_pb2.pyi +57 -0
- streamlit/proto/ArrowVegaLiteChart_pb2.py +29 -0
- streamlit/proto/ArrowVegaLiteChart_pb2.pyi +84 -0
- streamlit/proto/Arrow_pb2.py +33 -0
- streamlit/proto/Arrow_pb2.pyi +188 -0
- streamlit/proto/AudioInput_pb2.py +28 -0
- streamlit/proto/AudioInput_pb2.pyi +58 -0
- streamlit/proto/Audio_pb2.py +27 -0
- streamlit/proto/Audio_pb2.pyi +58 -0
- streamlit/proto/AuthRedirect_pb2.py +27 -0
- streamlit/proto/AuthRedirect_pb2.pyi +41 -0
- streamlit/proto/AutoRerun_pb2.py +27 -0
- streamlit/proto/AutoRerun_pb2.pyi +45 -0
- streamlit/proto/BackMsg_pb2.py +29 -0
- streamlit/proto/BackMsg_pb2.pyi +105 -0
- streamlit/proto/Balloons_pb2.py +27 -0
- streamlit/proto/Balloons_pb2.pyi +43 -0
- streamlit/proto/Block_pb2.py +53 -0
- streamlit/proto/Block_pb2.pyi +322 -0
- streamlit/proto/BokehChart_pb2.py +27 -0
- streamlit/proto/BokehChart_pb2.pyi +49 -0
- streamlit/proto/ButtonGroup_pb2.py +36 -0
- streamlit/proto/ButtonGroup_pb2.pyi +169 -0
- streamlit/proto/Button_pb2.py +27 -0
- streamlit/proto/Button_pb2.pyi +71 -0
- streamlit/proto/CameraInput_pb2.py +28 -0
- streamlit/proto/CameraInput_pb2.pyi +58 -0
- streamlit/proto/ChatInput_pb2.py +31 -0
- streamlit/proto/ChatInput_pb2.pyi +111 -0
- streamlit/proto/Checkbox_pb2.py +30 -0
- streamlit/proto/Checkbox_pb2.pyi +90 -0
- streamlit/proto/ClientState_pb2.py +30 -0
- streamlit/proto/ClientState_pb2.pyi +90 -0
- streamlit/proto/Code_pb2.py +27 -0
- streamlit/proto/Code_pb2.pyi +55 -0
- streamlit/proto/ColorPicker_pb2.py +28 -0
- streamlit/proto/ColorPicker_pb2.pyi +67 -0
- streamlit/proto/Common_pb2.py +51 -0
- streamlit/proto/Common_pb2.pyi +293 -0
- streamlit/proto/Components_pb2.py +35 -0
- streamlit/proto/Components_pb2.pyi +172 -0
- streamlit/proto/DataFrame_pb2.py +56 -0
- streamlit/proto/DataFrame_pb2.pyi +397 -0
- streamlit/proto/DateInput_pb2.py +28 -0
- streamlit/proto/DateInput_pb2.pyi +83 -0
- streamlit/proto/DeckGlJsonChart_pb2.py +29 -0
- streamlit/proto/DeckGlJsonChart_pb2.pyi +102 -0
- streamlit/proto/Delta_pb2.py +31 -0
- streamlit/proto/Delta_pb2.pyi +74 -0
- streamlit/proto/DocString_pb2.py +29 -0
- streamlit/proto/DocString_pb2.pyi +93 -0
- streamlit/proto/DownloadButton_pb2.py +27 -0
- streamlit/proto/DownloadButton_pb2.pyi +70 -0
- streamlit/proto/Element_pb2.py +78 -0
- streamlit/proto/Element_pb2.pyi +312 -0
- streamlit/proto/Empty_pb2.py +27 -0
- streamlit/proto/Empty_pb2.pyi +36 -0
- streamlit/proto/Exception_pb2.py +27 -0
- streamlit/proto/Exception_pb2.pyi +72 -0
- streamlit/proto/Favicon_pb2.py +27 -0
- streamlit/proto/Favicon_pb2.pyi +40 -0
- streamlit/proto/FileUploader_pb2.py +28 -0
- streamlit/proto/FileUploader_pb2.pyi +78 -0
- streamlit/proto/ForwardMsg_pb2.py +53 -0
- streamlit/proto/ForwardMsg_pb2.pyi +293 -0
- streamlit/proto/GitInfo_pb2.py +29 -0
- streamlit/proto/GitInfo_pb2.pyi +83 -0
- streamlit/proto/GraphVizChart_pb2.py +27 -0
- streamlit/proto/GraphVizChart_pb2.pyi +53 -0
- streamlit/proto/Heading_pb2.py +27 -0
- streamlit/proto/Heading_pb2.pyi +56 -0
- streamlit/proto/Html_pb2.py +27 -0
- streamlit/proto/Html_pb2.pyi +42 -0
- streamlit/proto/IFrame_pb2.py +27 -0
- streamlit/proto/IFrame_pb2.pyi +59 -0
- streamlit/proto/Image_pb2.py +29 -0
- streamlit/proto/Image_pb2.pyi +84 -0
- streamlit/proto/Json_pb2.py +27 -0
- streamlit/proto/Json_pb2.pyi +53 -0
- streamlit/proto/LabelVisibilityMessage_pb2.py +29 -0
- streamlit/proto/LabelVisibilityMessage_pb2.pyi +68 -0
- streamlit/proto/LinkButton_pb2.py +27 -0
- streamlit/proto/LinkButton_pb2.pyi +58 -0
- streamlit/proto/Logo_pb2.py +27 -0
- streamlit/proto/Logo_pb2.pyi +51 -0
- streamlit/proto/Markdown_pb2.py +29 -0
- streamlit/proto/Markdown_pb2.pyi +86 -0
- streamlit/proto/Metric_pb2.py +32 -0
- streamlit/proto/Metric_pb2.pyi +101 -0
- streamlit/proto/MetricsEvent_pb2.py +30 -0
- streamlit/proto/MetricsEvent_pb2.pyi +200 -0
- streamlit/proto/MultiSelect_pb2.py +28 -0
- streamlit/proto/MultiSelect_pb2.pyi +81 -0
- streamlit/proto/NamedDataSet_pb2.py +28 -0
- streamlit/proto/NamedDataSet_pb2.pyi +59 -0
- streamlit/proto/Navigation_pb2.py +30 -0
- streamlit/proto/Navigation_pb2.pyi +84 -0
- streamlit/proto/NewSession_pb2.py +51 -0
- streamlit/proto/NewSession_pb2.pyi +481 -0
- streamlit/proto/NumberInput_pb2.py +30 -0
- streamlit/proto/NumberInput_pb2.pyi +121 -0
- streamlit/proto/PageConfig_pb2.py +33 -0
- streamlit/proto/PageConfig_pb2.pyi +126 -0
- streamlit/proto/PageInfo_pb2.py +27 -0
- streamlit/proto/PageInfo_pb2.pyi +43 -0
- streamlit/proto/PageLink_pb2.py +27 -0
- streamlit/proto/PageLink_pb2.pyi +63 -0
- streamlit/proto/PageNotFound_pb2.py +27 -0
- streamlit/proto/PageNotFound_pb2.pyi +42 -0
- streamlit/proto/PageProfile_pb2.py +31 -0
- streamlit/proto/PageProfile_pb2.pyi +127 -0
- streamlit/proto/PagesChanged_pb2.py +28 -0
- streamlit/proto/PagesChanged_pb2.pyi +48 -0
- streamlit/proto/ParentMessage_pb2.py +27 -0
- streamlit/proto/ParentMessage_pb2.pyi +46 -0
- streamlit/proto/PlotlyChart_pb2.py +31 -0
- streamlit/proto/PlotlyChart_pb2.pyi +131 -0
- streamlit/proto/Progress_pb2.py +27 -0
- streamlit/proto/Progress_pb2.pyi +43 -0
- streamlit/proto/Radio_pb2.py +28 -0
- streamlit/proto/Radio_pb2.pyi +84 -0
- streamlit/proto/RootContainer_pb2.py +27 -0
- streamlit/proto/RootContainer_pb2.pyi +56 -0
- streamlit/proto/Selectbox_pb2.py +28 -0
- streamlit/proto/Selectbox_pb2.pyi +80 -0
- streamlit/proto/SessionEvent_pb2.py +28 -0
- streamlit/proto/SessionEvent_pb2.pyi +62 -0
- streamlit/proto/SessionStatus_pb2.py +27 -0
- streamlit/proto/SessionStatus_pb2.pyi +57 -0
- streamlit/proto/Skeleton_pb2.py +29 -0
- streamlit/proto/Skeleton_pb2.pyi +71 -0
- streamlit/proto/Slider_pb2.py +32 -0
- streamlit/proto/Slider_pb2.pyi +142 -0
- streamlit/proto/Snow_pb2.py +27 -0
- streamlit/proto/Snow_pb2.pyi +43 -0
- streamlit/proto/Spinner_pb2.py +27 -0
- streamlit/proto/Spinner_pb2.pyi +49 -0
- streamlit/proto/TextArea_pb2.py +28 -0
- streamlit/proto/TextArea_pb2.pyi +80 -0
- streamlit/proto/TextInput_pb2.py +30 -0
- streamlit/proto/TextInput_pb2.pyi +107 -0
- streamlit/proto/Text_pb2.py +27 -0
- streamlit/proto/Text_pb2.pyi +46 -0
- streamlit/proto/TimeInput_pb2.py +28 -0
- streamlit/proto/TimeInput_pb2.pyi +74 -0
- streamlit/proto/Toast_pb2.py +27 -0
- streamlit/proto/Toast_pb2.pyi +45 -0
- streamlit/proto/VegaLiteChart_pb2.py +29 -0
- streamlit/proto/VegaLiteChart_pb2.pyi +71 -0
- streamlit/proto/Video_pb2.py +31 -0
- streamlit/proto/Video_pb2.pyi +117 -0
- streamlit/proto/WidgetStates_pb2.py +31 -0
- streamlit/proto/WidgetStates_pb2.pyi +126 -0
- streamlit/proto/__init__.py +15 -0
- streamlit/proto/openmetrics_data_model_pb2.py +60 -0
- streamlit/proto/openmetrics_data_model_pb2.pyi +522 -0
- streamlit/py.typed +0 -0
- streamlit/runtime/__init__.py +50 -0
- streamlit/runtime/app_session.py +982 -0
- streamlit/runtime/caching/__init__.py +98 -0
- streamlit/runtime/caching/cache_data_api.py +665 -0
- streamlit/runtime/caching/cache_errors.py +142 -0
- streamlit/runtime/caching/cache_resource_api.py +527 -0
- streamlit/runtime/caching/cache_type.py +33 -0
- streamlit/runtime/caching/cache_utils.py +523 -0
- streamlit/runtime/caching/cached_message_replay.py +290 -0
- streamlit/runtime/caching/hashing.py +637 -0
- streamlit/runtime/caching/legacy_cache_api.py +169 -0
- streamlit/runtime/caching/storage/__init__.py +29 -0
- streamlit/runtime/caching/storage/cache_storage_protocol.py +239 -0
- streamlit/runtime/caching/storage/dummy_cache_storage.py +60 -0
- streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +145 -0
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +223 -0
- streamlit/runtime/connection_factory.py +436 -0
- streamlit/runtime/context.py +280 -0
- streamlit/runtime/credentials.py +364 -0
- streamlit/runtime/forward_msg_cache.py +296 -0
- streamlit/runtime/forward_msg_queue.py +240 -0
- streamlit/runtime/fragment.py +477 -0
- streamlit/runtime/media_file_manager.py +234 -0
- streamlit/runtime/media_file_storage.py +143 -0
- streamlit/runtime/memory_media_file_storage.py +181 -0
- streamlit/runtime/memory_session_storage.py +77 -0
- streamlit/runtime/memory_uploaded_file_manager.py +138 -0
- streamlit/runtime/metrics_util.py +486 -0
- streamlit/runtime/pages_manager.py +165 -0
- streamlit/runtime/runtime.py +792 -0
- streamlit/runtime/runtime_util.py +106 -0
- streamlit/runtime/script_data.py +46 -0
- streamlit/runtime/scriptrunner/__init__.py +38 -0
- streamlit/runtime/scriptrunner/exec_code.py +159 -0
- streamlit/runtime/scriptrunner/magic.py +273 -0
- streamlit/runtime/scriptrunner/magic_funcs.py +32 -0
- streamlit/runtime/scriptrunner/script_cache.py +89 -0
- streamlit/runtime/scriptrunner/script_runner.py +756 -0
- streamlit/runtime/scriptrunner_utils/__init__.py +19 -0
- streamlit/runtime/scriptrunner_utils/exceptions.py +48 -0
- streamlit/runtime/scriptrunner_utils/script_requests.py +307 -0
- streamlit/runtime/scriptrunner_utils/script_run_context.py +287 -0
- streamlit/runtime/secrets.py +534 -0
- streamlit/runtime/session_manager.py +394 -0
- streamlit/runtime/state/__init__.py +41 -0
- streamlit/runtime/state/common.py +191 -0
- streamlit/runtime/state/query_params.py +205 -0
- streamlit/runtime/state/query_params_proxy.py +218 -0
- streamlit/runtime/state/safe_session_state.py +138 -0
- streamlit/runtime/state/session_state.py +772 -0
- streamlit/runtime/state/session_state_proxy.py +153 -0
- streamlit/runtime/state/widgets.py +135 -0
- streamlit/runtime/stats.py +109 -0
- streamlit/runtime/uploaded_file_manager.py +148 -0
- streamlit/runtime/websocket_session_manager.py +167 -0
- streamlit/source_util.py +98 -0
- streamlit/static/favicon.png +0 -0
- streamlit/static/index.html +61 -0
- streamlit/static/static/css/index.Bmkmz40k.css +1 -0
- streamlit/static/static/css/index.DpJG_94W.css +1 -0
- streamlit/static/static/css/index.DzuxGC_t.css +1 -0
- streamlit/static/static/js/FileDownload.esm.Bp9m5jrx.js +1 -0
- streamlit/static/static/js/FileHelper.D_3pbilj.js +5 -0
- streamlit/static/static/js/FormClearHelper.Ct2rwLXo.js +1 -0
- streamlit/static/static/js/Hooks.BKdzj5MJ.js +1 -0
- streamlit/static/static/js/InputInstructions.DB3QGNJP.js +1 -0
- streamlit/static/static/js/ProgressBar.D40A5xc2.js +2 -0
- streamlit/static/static/js/RenderInPortalIfExists.DLUCooTN.js +1 -0
- streamlit/static/static/js/Toolbar.BiGGIQun.js +1 -0
- streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +1 -0
- streamlit/static/static/js/base-input.CQBQT24M.js +4 -0
- streamlit/static/static/js/checkbox.Buj8gd_M.js +9 -0
- streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +1 -0
- streamlit/static/static/js/createSuper.CesK3I23.js +1 -0
- streamlit/static/static/js/data-grid-overlay-editor.B69OOFM4.js +1 -0
- streamlit/static/static/js/downloader.BZQhlBNT.js +1 -0
- streamlit/static/static/js/es6.D9Zhqujy.js +2 -0
- streamlit/static/static/js/iframeResizer.contentWindow.CAzcBpCC.js +1 -0
- streamlit/static/static/js/index.08vcOOvb.js +1 -0
- streamlit/static/static/js/index.0uqKfJUS.js +1 -0
- streamlit/static/static/js/index.B02M5u69.js +203 -0
- streamlit/static/static/js/index.B7mcZKMx.js +1 -0
- streamlit/static/static/js/index.BAQDHFA_.js +1 -0
- streamlit/static/static/js/index.BI60cMVr.js +2 -0
- streamlit/static/static/js/index.BLug2inK.js +1 -0
- streamlit/static/static/js/index.BM6TMY8g.js +2 -0
- streamlit/static/static/js/index.BZ9p1t7G.js +1 -0
- streamlit/static/static/js/index.BZqa87a1.js +2 -0
- streamlit/static/static/js/index.BcsRUzZZ.js +1 -0
- streamlit/static/static/js/index.BgVMiY_P.js +197 -0
- streamlit/static/static/js/index.BtuGy7By.js +6 -0
- streamlit/static/static/js/index.BuDuBmrs.js +1 -0
- streamlit/static/static/js/index.BvXU2oKV.js +1 -0
- streamlit/static/static/js/index.BxcwPacT.js +73 -0
- streamlit/static/static/js/index.CWX8KB81.js +1 -0
- streamlit/static/static/js/index.CXzZTo_q.js +1 -0
- streamlit/static/static/js/index.CcRWp_KL.js +1 -0
- streamlit/static/static/js/index.Cd-_xe55.js +3 -0
- streamlit/static/static/js/index.CdG2PXln.js +4537 -0
- streamlit/static/static/js/index.CjXvXmcP.js +1 -0
- streamlit/static/static/js/index.D1HZENZx.js +776 -0
- streamlit/static/static/js/index.D21Efo64.js +1617 -0
- streamlit/static/static/js/index.D9WgGVBx.js +7 -0
- streamlit/static/static/js/index.DEcsHtvb.js +12 -0
- streamlit/static/static/js/index.DFeMfr_K.js +1 -0
- streamlit/static/static/js/index.DHFBoItz.js +1 -0
- streamlit/static/static/js/index.D_PrBKnJ.js +3 -0
- streamlit/static/static/js/index.DmuRkekN.js +3855 -0
- streamlit/static/static/js/index.Do6eY8sf.js +1 -0
- streamlit/static/static/js/index.Dz3lP2P-.js +1 -0
- streamlit/static/static/js/index.Dz_UqF-s.js +1 -0
- streamlit/static/static/js/index.GkSUsPhJ.js +1 -0
- streamlit/static/static/js/index.H1U1IC_d.js +3 -0
- streamlit/static/static/js/index.g6p_4DPr.js +1 -0
- streamlit/static/static/js/index.g9x_GKss.js +1 -0
- streamlit/static/static/js/index.zo9jm08y.js +1 -0
- streamlit/static/static/js/input.DnaFglHq.js +2 -0
- streamlit/static/static/js/inputUtils.CQWz5UKz.js +1 -0
- streamlit/static/static/js/memory.Crb9x4-F.js +1 -0
- streamlit/static/static/js/mergeWith.ouAz0sK3.js +1 -0
- streamlit/static/static/js/number-overlay-editor._UaN-O48.js +9 -0
- streamlit/static/static/js/possibleConstructorReturn.CtGjGFHz.js +1 -0
- streamlit/static/static/js/sandbox.CBybYOhV.js +1 -0
- streamlit/static/static/js/sprintf.D7DtBTRn.js +1 -0
- streamlit/static/static/js/textarea.Cb_uJt5U.js +2 -0
- streamlit/static/static/js/threshold.DjX0wlsa.js +1 -0
- streamlit/static/static/js/timepicker.DKT7pfoF.js +4 -0
- streamlit/static/static/js/timer.CAwTRJ_g.js +1 -0
- streamlit/static/static/js/toConsumableArray.05Ikp13-.js +3 -0
- streamlit/static/static/js/uniqueId.D2FMWUEI.js +1 -0
- streamlit/static/static/js/useBasicWidgetState.urnZLANY.js +1 -0
- streamlit/static/static/js/useOnInputChange.BOKIIdJ1.js +1 -0
- streamlit/static/static/js/value.CgPGBV_l.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.C_N8J0Xx.js +1 -0
- streamlit/static/static/media/KaTeX_AMS-Regular.BQhdFMY1.woff2 +0 -0
- streamlit/static/static/media/KaTeX_AMS-Regular.DMm9YOAa.woff +0 -0
- streamlit/static/static/media/KaTeX_AMS-Regular.DRggAlZN.ttf +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Bold.ATXxdsX0.ttf +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Bold.BEiXGLvX.woff +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Bold.Dq_IR9rO.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Regular.CTRA-rTL.woff +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Regular.Di6jR-x-.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Caligraphic-Regular.wX97UBjC.ttf +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Bold.BdnERNNW.ttf +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Bold.BsDP51OF.woff +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Bold.CL6g_b3V.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Regular.CB_wures.ttf +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Regular.CTYiF6lA.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Fraktur-Regular.Dxdc4cR9.woff +0 -0
- streamlit/static/static/media/KaTeX_Main-Bold.Cx986IdX.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Main-Bold.Jm3AIy58.woff +0 -0
- streamlit/static/static/media/KaTeX_Main-Bold.waoOVXN0.ttf +0 -0
- streamlit/static/static/media/KaTeX_Main-BoldItalic.DxDJ3AOS.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Main-BoldItalic.DzxPMmG6.ttf +0 -0
- streamlit/static/static/media/KaTeX_Main-BoldItalic.SpSLRI95.woff +0 -0
- streamlit/static/static/media/KaTeX_Main-Italic.3WenGoN9.ttf +0 -0
- streamlit/static/static/media/KaTeX_Main-Italic.BMLOBm91.woff +0 -0
- streamlit/static/static/media/KaTeX_Main-Italic.NWA7e6Wa.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Main-Regular.B22Nviop.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Main-Regular.Dr94JaBh.woff +0 -0
- streamlit/static/static/media/KaTeX_Main-Regular.ypZvNtVU.ttf +0 -0
- streamlit/static/static/media/KaTeX_Math-BoldItalic.B3XSjfu4.ttf +0 -0
- streamlit/static/static/media/KaTeX_Math-BoldItalic.CZnvNsCZ.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Math-BoldItalic.iY-2wyZ7.woff +0 -0
- streamlit/static/static/media/KaTeX_Math-Italic.DA0__PXp.woff +0 -0
- streamlit/static/static/media/KaTeX_Math-Italic.flOr_0UB.ttf +0 -0
- streamlit/static/static/media/KaTeX_Math-Italic.t53AETM-.woff2 +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Bold.CFMepnvq.ttf +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Bold.D1sUS0GD.woff2 +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Bold.DbIhKOiC.woff +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Italic.C3H0VqGB.woff2 +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Italic.DN2j7dab.woff +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Italic.YYjJ1zSn.ttf +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Regular.BNo7hRIc.ttf +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Regular.CS6fqUqJ.woff +0 -0
- streamlit/static/static/media/KaTeX_SansSerif-Regular.DDBCnlJ7.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Script-Regular.C5JkGWo-.ttf +0 -0
- streamlit/static/static/media/KaTeX_Script-Regular.D3wIWfF6.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Script-Regular.D5yQViql.woff +0 -0
- streamlit/static/static/media/KaTeX_Size1-Regular.C195tn64.woff +0 -0
- streamlit/static/static/media/KaTeX_Size1-Regular.Dbsnue_I.ttf +0 -0
- streamlit/static/static/media/KaTeX_Size1-Regular.mCD8mA8B.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Size2-Regular.B7gKUWhC.ttf +0 -0
- streamlit/static/static/media/KaTeX_Size2-Regular.Dy4dx90m.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Size2-Regular.oD1tc_U0.woff +0 -0
- streamlit/static/static/media/KaTeX_Size3-Regular.CTq5MqoE.woff +0 -0
- streamlit/static/static/media/KaTeX_Size3-Regular.DgpXs0kz.ttf +0 -0
- streamlit/static/static/media/KaTeX_Size4-Regular.BF-4gkZK.woff +0 -0
- streamlit/static/static/media/KaTeX_Size4-Regular.DWFBv043.ttf +0 -0
- streamlit/static/static/media/KaTeX_Size4-Regular.Dl5lxZxV.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Typewriter-Regular.C0xS9mPB.woff +0 -0
- streamlit/static/static/media/KaTeX_Typewriter-Regular.CO6r4hn1.woff2 +0 -0
- streamlit/static/static/media/KaTeX_Typewriter-Regular.D3Ib7_Hf.ttf +0 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.DcZbplWk.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
- streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
- streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
- streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
- streamlit/static/static/media/balloon-0.Czj7AKwE.png +0 -0
- streamlit/static/static/media/balloon-1.CNvFFrND.png +0 -0
- streamlit/static/static/media/balloon-2.DTvC6B1t.png +0 -0
- streamlit/static/static/media/balloon-3.CgSk4tbL.png +0 -0
- streamlit/static/static/media/balloon-4.mbtFrzxf.png +0 -0
- streamlit/static/static/media/balloon-5.CSwkUfRA.png +0 -0
- streamlit/static/static/media/fireworks.B4d-_KUe.gif +0 -0
- streamlit/static/static/media/flake-0.DgWaVvm5.png +0 -0
- streamlit/static/static/media/flake-1.B2r5AHMK.png +0 -0
- streamlit/static/static/media/flake-2.BnWSExPC.png +0 -0
- streamlit/static/static/media/snowflake.JU2jBHL8.svg +11 -0
- streamlit/string_util.py +203 -0
- streamlit/temporary_directory.py +56 -0
- streamlit/testing/__init__.py +13 -0
- streamlit/testing/v1/__init__.py +17 -0
- streamlit/testing/v1/app_test.py +1050 -0
- streamlit/testing/v1/element_tree.py +2083 -0
- streamlit/testing/v1/local_script_runner.py +180 -0
- streamlit/testing/v1/util.py +53 -0
- streamlit/time_util.py +75 -0
- streamlit/type_util.py +460 -0
- streamlit/url_util.py +122 -0
- streamlit/user_info.py +519 -0
- streamlit/util.py +72 -0
- streamlit/vendor/__init__.py +0 -0
- streamlit/vendor/pympler/__init__.py +0 -0
- streamlit/vendor/pympler/asizeof.py +2869 -0
- streamlit/version.py +18 -0
- streamlit/watcher/__init__.py +28 -0
- streamlit/watcher/event_based_path_watcher.py +406 -0
- streamlit/watcher/folder_black_list.py +82 -0
- streamlit/watcher/local_sources_watcher.py +233 -0
- streamlit/watcher/path_watcher.py +185 -0
- streamlit/watcher/polling_path_watcher.py +124 -0
- streamlit/watcher/util.py +207 -0
- streamlit/web/__init__.py +13 -0
- streamlit/web/bootstrap.py +353 -0
- streamlit/web/cache_storage_manager_config.py +38 -0
- streamlit/web/cli.py +369 -0
- streamlit/web/server/__init__.py +26 -0
- streamlit/web/server/app_static_file_handler.py +93 -0
- streamlit/web/server/authlib_tornado_integration.py +60 -0
- streamlit/web/server/browser_websocket_handler.py +246 -0
- streamlit/web/server/component_request_handler.py +116 -0
- streamlit/web/server/media_file_handler.py +141 -0
- streamlit/web/server/oauth_authlib_routes.py +176 -0
- streamlit/web/server/oidc_mixin.py +108 -0
- streamlit/web/server/routes.py +295 -0
- streamlit/web/server/server.py +479 -0
- streamlit/web/server/server_util.py +161 -0
- streamlit/web/server/stats_request_handler.py +95 -0
- streamlit/web/server/upload_file_request_handler.py +137 -0
- streamlit/web/server/websocket_headers.py +56 -0
- streamlit_nightly-1.43.2.dev20250307.data/scripts/streamlit.cmd +16 -0
- streamlit_nightly-1.43.2.dev20250307.dist-info/METADATA +207 -0
- streamlit_nightly-1.43.2.dev20250307.dist-info/RECORD +563 -0
- streamlit_nightly-1.43.2.dev20250307.dist-info/WHEEL +5 -0
- streamlit_nightly-1.43.2.dev20250307.dist-info/entry_points.txt +2 -0
- streamlit_nightly-1.43.2.dev20250307.dist-info/top_level.txt +1 -0
@@ -0,0 +1,756 @@
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
import gc
|
18
|
+
import sys
|
19
|
+
import threading
|
20
|
+
import types
|
21
|
+
from contextlib import contextmanager
|
22
|
+
from enum import Enum
|
23
|
+
from timeit import default_timer as timer
|
24
|
+
from typing import TYPE_CHECKING, Callable, Final, Literal, cast
|
25
|
+
|
26
|
+
from blinker import Signal
|
27
|
+
|
28
|
+
from streamlit import config, runtime, util
|
29
|
+
from streamlit.errors import FragmentStorageKeyError
|
30
|
+
from streamlit.logger import get_logger
|
31
|
+
from streamlit.proto.ClientState_pb2 import ClientState
|
32
|
+
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
33
|
+
from streamlit.runtime.metrics_util import (
|
34
|
+
create_page_profile_message,
|
35
|
+
to_microseconds,
|
36
|
+
)
|
37
|
+
from streamlit.runtime.pages_manager import PagesManager
|
38
|
+
from streamlit.runtime.scriptrunner.exec_code import (
|
39
|
+
exec_func_with_error_handling,
|
40
|
+
modified_sys_path,
|
41
|
+
)
|
42
|
+
from streamlit.runtime.scriptrunner.script_cache import ScriptCache
|
43
|
+
from streamlit.runtime.scriptrunner_utils.exceptions import (
|
44
|
+
RerunException,
|
45
|
+
StopException,
|
46
|
+
)
|
47
|
+
from streamlit.runtime.scriptrunner_utils.script_requests import (
|
48
|
+
RerunData,
|
49
|
+
ScriptRequests,
|
50
|
+
ScriptRequestType,
|
51
|
+
)
|
52
|
+
from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
53
|
+
ScriptRunContext,
|
54
|
+
add_script_run_ctx,
|
55
|
+
get_script_run_ctx,
|
56
|
+
)
|
57
|
+
from streamlit.runtime.state import (
|
58
|
+
SCRIPT_RUN_WITHOUT_ERRORS_KEY,
|
59
|
+
SafeSessionState,
|
60
|
+
SessionState,
|
61
|
+
)
|
62
|
+
from streamlit.source_util import page_sort_key
|
63
|
+
|
64
|
+
if TYPE_CHECKING:
|
65
|
+
from streamlit.runtime.fragment import FragmentStorage
|
66
|
+
from streamlit.runtime.scriptrunner.script_cache import ScriptCache
|
67
|
+
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
68
|
+
|
69
|
+
_LOGGER: Final = get_logger(__name__)
|
70
|
+
|
71
|
+
|
72
|
+
class ScriptRunnerEvent(Enum):
|
73
|
+
# "Control" events. These are emitted when the ScriptRunner's state changes.
|
74
|
+
|
75
|
+
# The script started running.
|
76
|
+
SCRIPT_STARTED = "SCRIPT_STARTED"
|
77
|
+
|
78
|
+
# The script run stopped because of a compile error.
|
79
|
+
SCRIPT_STOPPED_WITH_COMPILE_ERROR = "SCRIPT_STOPPED_WITH_COMPILE_ERROR"
|
80
|
+
|
81
|
+
# The script run stopped because it ran to completion, or was
|
82
|
+
# interrupted by the user.
|
83
|
+
SCRIPT_STOPPED_WITH_SUCCESS = "SCRIPT_STOPPED_WITH_SUCCESS"
|
84
|
+
|
85
|
+
# The script run stopped in order to start a script run with newer widget state.
|
86
|
+
SCRIPT_STOPPED_FOR_RERUN = "SCRIPT_STOPPED_FOR_RERUN"
|
87
|
+
|
88
|
+
# The script run corresponding to a fragment ran to completion, or was interrupted
|
89
|
+
# by the user.
|
90
|
+
FRAGMENT_STOPPED_WITH_SUCCESS = "FRAGMENT_STOPPED_WITH_SUCCESS"
|
91
|
+
|
92
|
+
# The ScriptRunner is done processing the ScriptEventQueue and
|
93
|
+
# is shut down.
|
94
|
+
SHUTDOWN = "SHUTDOWN"
|
95
|
+
|
96
|
+
# "Data" events. These are emitted when the ScriptRunner's script has
|
97
|
+
# data to send to the frontend.
|
98
|
+
|
99
|
+
# The script has a ForwardMsg to send to the frontend.
|
100
|
+
ENQUEUE_FORWARD_MSG = "ENQUEUE_FORWARD_MSG"
|
101
|
+
|
102
|
+
|
103
|
+
"""
|
104
|
+
Note [Threading]
|
105
|
+
There are two kinds of threads in Streamlit, the main thread and script threads.
|
106
|
+
The main thread is started by invoking the Streamlit CLI, and bootstraps the
|
107
|
+
framework and runs the Tornado webserver.
|
108
|
+
A script thread is created by a ScriptRunner when it starts. The script thread
|
109
|
+
is where the ScriptRunner executes, including running the user script itself,
|
110
|
+
processing messages to/from the frontend, and all the Streamlit library function
|
111
|
+
calls in the user script.
|
112
|
+
It is possible for the user script to spawn its own threads, which could call
|
113
|
+
Streamlit functions. We restrict the ScriptRunner's execution control to the
|
114
|
+
script thread. Calling Streamlit functions from other threads is unlikely to
|
115
|
+
work correctly due to lack of ScriptRunContext, so we may add a guard against
|
116
|
+
it in the future.
|
117
|
+
"""
|
118
|
+
|
119
|
+
|
120
|
+
# For projects that have a pages folder, we assume that this is a script that
|
121
|
+
# is designed to leverage our original v1 version of multi-page apps. This
|
122
|
+
# function will be called to run the script in lieu of the main script. This
|
123
|
+
# function simulates the v1 setup using the modern v2 commands (st.navigation)
|
124
|
+
def _mpa_v1(main_script_path: str):
|
125
|
+
from pathlib import Path
|
126
|
+
|
127
|
+
from streamlit.commands.navigation import PageType, _navigation
|
128
|
+
from streamlit.navigation.page import StreamlitPage
|
129
|
+
|
130
|
+
# Select the folder that should be used for the pages:
|
131
|
+
MAIN_SCRIPT_PATH = Path(main_script_path).resolve()
|
132
|
+
PAGES_FOLDER = MAIN_SCRIPT_PATH.parent / "pages"
|
133
|
+
|
134
|
+
# Read out the my_pages folder and create a page for every script:
|
135
|
+
pages = PAGES_FOLDER.glob("*.py")
|
136
|
+
pages = sorted(
|
137
|
+
[page for page in pages if page.name.endswith(".py")], key=page_sort_key
|
138
|
+
)
|
139
|
+
|
140
|
+
# Use this script as the main page and
|
141
|
+
main_page = StreamlitPage(MAIN_SCRIPT_PATH, default=True)
|
142
|
+
all_pages = [main_page] + [
|
143
|
+
StreamlitPage(PAGES_FOLDER / page.name) for page in pages
|
144
|
+
]
|
145
|
+
# Initialize the navigation with all the pages:
|
146
|
+
position: Literal["sidebar", "hidden"] = (
|
147
|
+
"hidden"
|
148
|
+
if config.get_option("client.showSidebarNavigation") is False
|
149
|
+
else "sidebar"
|
150
|
+
)
|
151
|
+
page = _navigation(
|
152
|
+
cast(list[PageType], all_pages),
|
153
|
+
position=position,
|
154
|
+
expanded=False,
|
155
|
+
)
|
156
|
+
|
157
|
+
if page._page != main_page._page:
|
158
|
+
# Only run the page if it is not pointing to this script:
|
159
|
+
page.run()
|
160
|
+
# Finish the script execution here to only run the selected page
|
161
|
+
raise StopException()
|
162
|
+
|
163
|
+
|
164
|
+
class ScriptRunner:
|
165
|
+
def __init__(
|
166
|
+
self,
|
167
|
+
session_id: str,
|
168
|
+
main_script_path: str,
|
169
|
+
session_state: SessionState,
|
170
|
+
uploaded_file_mgr: UploadedFileManager,
|
171
|
+
script_cache: ScriptCache,
|
172
|
+
initial_rerun_data: RerunData,
|
173
|
+
user_info: dict[str, str | bool | None],
|
174
|
+
fragment_storage: FragmentStorage,
|
175
|
+
pages_manager: PagesManager,
|
176
|
+
):
|
177
|
+
"""Initialize the ScriptRunner.
|
178
|
+
|
179
|
+
(The ScriptRunner won't start executing until start() is called.)
|
180
|
+
|
181
|
+
Parameters
|
182
|
+
----------
|
183
|
+
session_id
|
184
|
+
The AppSession's id.
|
185
|
+
|
186
|
+
main_script_path
|
187
|
+
Path to our main app script.
|
188
|
+
|
189
|
+
session_state
|
190
|
+
The AppSession's SessionState instance.
|
191
|
+
|
192
|
+
uploaded_file_mgr
|
193
|
+
The File manager to store the data uploaded by the file_uploader widget.
|
194
|
+
|
195
|
+
script_cache
|
196
|
+
A ScriptCache instance.
|
197
|
+
|
198
|
+
initial_rerun_data
|
199
|
+
RerunData to initialize this ScriptRunner with.
|
200
|
+
|
201
|
+
user_info
|
202
|
+
A dict that contains information about the current user. For now,
|
203
|
+
it only contains the user's email address.
|
204
|
+
|
205
|
+
{
|
206
|
+
"email": "example@example.com"
|
207
|
+
}
|
208
|
+
|
209
|
+
Information about the current user is optionally provided when a
|
210
|
+
websocket connection is initialized via the "X-Streamlit-User" header.
|
211
|
+
|
212
|
+
fragment_storage
|
213
|
+
The AppSession's FragmentStorage instance.
|
214
|
+
"""
|
215
|
+
self._session_id = session_id
|
216
|
+
self._main_script_path = main_script_path
|
217
|
+
self._session_state = SafeSessionState(
|
218
|
+
session_state, yield_callback=self._maybe_handle_execution_control_request
|
219
|
+
)
|
220
|
+
self._uploaded_file_mgr = uploaded_file_mgr
|
221
|
+
self._script_cache = script_cache
|
222
|
+
self._user_info = user_info
|
223
|
+
self._fragment_storage = fragment_storage
|
224
|
+
|
225
|
+
self._pages_manager = pages_manager
|
226
|
+
self._requests = ScriptRequests()
|
227
|
+
self._requests.request_rerun(initial_rerun_data)
|
228
|
+
|
229
|
+
self.on_event = Signal(
|
230
|
+
doc="""Emitted when a ScriptRunnerEvent occurs.
|
231
|
+
|
232
|
+
This signal is generally emitted on the ScriptRunner's script
|
233
|
+
thread (which is *not* the same thread that the ScriptRunner was
|
234
|
+
created on).
|
235
|
+
|
236
|
+
Parameters
|
237
|
+
----------
|
238
|
+
sender: ScriptRunner
|
239
|
+
The sender of the event (this ScriptRunner).
|
240
|
+
|
241
|
+
event : ScriptRunnerEvent
|
242
|
+
|
243
|
+
forward_msg : ForwardMsg | None
|
244
|
+
The ForwardMsg to send to the frontend. Set only for the
|
245
|
+
ENQUEUE_FORWARD_MSG event.
|
246
|
+
|
247
|
+
exception : BaseException | None
|
248
|
+
Our compile error. Set only for the
|
249
|
+
SCRIPT_STOPPED_WITH_COMPILE_ERROR event.
|
250
|
+
|
251
|
+
widget_states : streamlit.proto.WidgetStates_pb2.WidgetStates | None
|
252
|
+
The ScriptRunner's final WidgetStates. Set only for the
|
253
|
+
SHUTDOWN event.
|
254
|
+
"""
|
255
|
+
)
|
256
|
+
|
257
|
+
# Set to true while we're executing. Used by
|
258
|
+
# _maybe_handle_execution_control_request.
|
259
|
+
self._execing = False
|
260
|
+
|
261
|
+
# This is initialized in start()
|
262
|
+
self._script_thread: threading.Thread | None = None
|
263
|
+
|
264
|
+
def __repr__(self) -> str:
|
265
|
+
return util.repr_(self)
|
266
|
+
|
267
|
+
def request_stop(self) -> None:
|
268
|
+
"""Request that the ScriptRunner stop running its script and
|
269
|
+
shut down. The ScriptRunner will handle this request when it reaches
|
270
|
+
an interrupt point.
|
271
|
+
|
272
|
+
Safe to call from any thread.
|
273
|
+
"""
|
274
|
+
self._requests.request_stop()
|
275
|
+
|
276
|
+
def request_rerun(self, rerun_data: RerunData) -> bool:
|
277
|
+
"""Request that the ScriptRunner interrupt its currently-running
|
278
|
+
script and restart it.
|
279
|
+
|
280
|
+
If the ScriptRunner has been stopped, this request can't be honored:
|
281
|
+
return False.
|
282
|
+
|
283
|
+
Otherwise, record the request and return True. The ScriptRunner will
|
284
|
+
handle the rerun request as soon as it reaches an interrupt point.
|
285
|
+
|
286
|
+
Safe to call from any thread.
|
287
|
+
"""
|
288
|
+
return self._requests.request_rerun(rerun_data)
|
289
|
+
|
290
|
+
def start(self) -> None:
|
291
|
+
"""Start a new thread to process the ScriptEventQueue.
|
292
|
+
|
293
|
+
This must be called only once.
|
294
|
+
|
295
|
+
"""
|
296
|
+
if self._script_thread is not None:
|
297
|
+
raise Exception("ScriptRunner was already started")
|
298
|
+
|
299
|
+
self._script_thread = threading.Thread(
|
300
|
+
target=self._run_script_thread,
|
301
|
+
name="ScriptRunner.scriptThread",
|
302
|
+
)
|
303
|
+
self._script_thread.start()
|
304
|
+
|
305
|
+
def _get_script_run_ctx(self) -> ScriptRunContext:
|
306
|
+
"""Get the ScriptRunContext for the current thread.
|
307
|
+
|
308
|
+
Returns
|
309
|
+
-------
|
310
|
+
ScriptRunContext
|
311
|
+
The ScriptRunContext for the current thread.
|
312
|
+
|
313
|
+
Raises
|
314
|
+
------
|
315
|
+
AssertionError
|
316
|
+
If called outside of a ScriptRunner thread.
|
317
|
+
RuntimeError
|
318
|
+
If there is no ScriptRunContext for the current thread.
|
319
|
+
|
320
|
+
"""
|
321
|
+
assert self._is_in_script_thread()
|
322
|
+
|
323
|
+
ctx = get_script_run_ctx()
|
324
|
+
if ctx is None:
|
325
|
+
# This should never be possible on the script_runner thread.
|
326
|
+
raise RuntimeError(
|
327
|
+
"ScriptRunner thread has a null ScriptRunContext. "
|
328
|
+
"Something has gone very wrong!"
|
329
|
+
)
|
330
|
+
return ctx
|
331
|
+
|
332
|
+
def _run_script_thread(self) -> None:
|
333
|
+
"""The entry point for the script thread.
|
334
|
+
|
335
|
+
Processes the ScriptRequestQueue, which will at least contain the RERUN
|
336
|
+
request that will trigger the first script-run.
|
337
|
+
|
338
|
+
When the ScriptRequestQueue is empty, or when a SHUTDOWN request is
|
339
|
+
dequeued, this function will exit and its thread will terminate.
|
340
|
+
"""
|
341
|
+
assert self._is_in_script_thread()
|
342
|
+
|
343
|
+
_LOGGER.debug("Beginning script thread")
|
344
|
+
|
345
|
+
# Create and attach the thread's ScriptRunContext
|
346
|
+
ctx = ScriptRunContext(
|
347
|
+
session_id=self._session_id,
|
348
|
+
_enqueue=self._enqueue_forward_msg,
|
349
|
+
script_requests=self._requests,
|
350
|
+
query_string="",
|
351
|
+
session_state=self._session_state,
|
352
|
+
uploaded_file_mgr=self._uploaded_file_mgr,
|
353
|
+
main_script_path=self._main_script_path,
|
354
|
+
user_info=self._user_info,
|
355
|
+
gather_usage_stats=bool(config.get_option("browser.gatherUsageStats")),
|
356
|
+
fragment_storage=self._fragment_storage,
|
357
|
+
pages_manager=self._pages_manager,
|
358
|
+
context_info=None,
|
359
|
+
)
|
360
|
+
add_script_run_ctx(threading.current_thread(), ctx)
|
361
|
+
|
362
|
+
request = self._requests.on_scriptrunner_ready()
|
363
|
+
while request.type == ScriptRequestType.RERUN:
|
364
|
+
# When the script thread starts, we'll have a pending rerun
|
365
|
+
# request that we'll handle immediately. When the script finishes,
|
366
|
+
# it's possible that another request has come in that we need to
|
367
|
+
# handle, which is why we call _run_script in a loop.
|
368
|
+
self._run_script(request.rerun_data)
|
369
|
+
request = self._requests.on_scriptrunner_ready()
|
370
|
+
|
371
|
+
assert request.type == ScriptRequestType.STOP
|
372
|
+
|
373
|
+
# Send a SHUTDOWN event before exiting, so some state can be saved
|
374
|
+
# for use in a future script run when not triggered by the client.
|
375
|
+
client_state = ClientState()
|
376
|
+
client_state.query_string = ctx.query_string
|
377
|
+
client_state.page_script_hash = ctx.page_script_hash
|
378
|
+
self.on_event.send(
|
379
|
+
self, event=ScriptRunnerEvent.SHUTDOWN, client_state=client_state
|
380
|
+
)
|
381
|
+
|
382
|
+
def _is_in_script_thread(self) -> bool:
|
383
|
+
"""True if the calling function is running in the script thread"""
|
384
|
+
return self._script_thread == threading.current_thread()
|
385
|
+
|
386
|
+
def _enqueue_forward_msg(self, msg: ForwardMsg) -> None:
|
387
|
+
"""Enqueue a ForwardMsg to our browser queue.
|
388
|
+
This private function is called by ScriptRunContext only.
|
389
|
+
|
390
|
+
It may be called from the script thread OR the main thread.
|
391
|
+
"""
|
392
|
+
# Whenever we enqueue a ForwardMsg, we also handle any pending
|
393
|
+
# execution control request. This means that a script can be
|
394
|
+
# cleanly interrupted and stopped inside most `st.foo` calls.
|
395
|
+
self._maybe_handle_execution_control_request()
|
396
|
+
|
397
|
+
# Pass the message to our associated AppSession.
|
398
|
+
self.on_event.send(
|
399
|
+
self, event=ScriptRunnerEvent.ENQUEUE_FORWARD_MSG, forward_msg=msg
|
400
|
+
)
|
401
|
+
|
402
|
+
def _maybe_handle_execution_control_request(self) -> None:
|
403
|
+
"""Check our current ScriptRequestState to see if we have a
|
404
|
+
pending STOP or RERUN request.
|
405
|
+
|
406
|
+
This function is called every time the app script enqueues a
|
407
|
+
ForwardMsg, which means that most `st.foo` commands - which generally
|
408
|
+
involve sending a ForwardMsg to the frontend - act as implicit
|
409
|
+
yield points in the script's execution.
|
410
|
+
"""
|
411
|
+
if not self._is_in_script_thread():
|
412
|
+
# We can only handle execution_control_request if we're on the
|
413
|
+
# script execution thread. However, it's possible for deltas to
|
414
|
+
# be enqueued (and, therefore, for this function to be called)
|
415
|
+
# in separate threads, so we check for that here.
|
416
|
+
return
|
417
|
+
|
418
|
+
if not self._execing:
|
419
|
+
# If the _execing flag is not set, we're not actually inside
|
420
|
+
# an exec() call. This happens when our script exec() completes,
|
421
|
+
# we change our state to STOPPED, and a statechange-listener
|
422
|
+
# enqueues a new ForwardEvent
|
423
|
+
return
|
424
|
+
|
425
|
+
request = self._requests.on_scriptrunner_yield()
|
426
|
+
if request is None:
|
427
|
+
# No RERUN or STOP request.
|
428
|
+
return
|
429
|
+
|
430
|
+
if request.type == ScriptRequestType.RERUN:
|
431
|
+
raise RerunException(request.rerun_data)
|
432
|
+
|
433
|
+
assert request.type == ScriptRequestType.STOP
|
434
|
+
raise StopException()
|
435
|
+
|
436
|
+
@contextmanager
|
437
|
+
def _set_execing_flag(self):
|
438
|
+
"""A context for setting the ScriptRunner._execing flag.
|
439
|
+
|
440
|
+
Used by _maybe_handle_execution_control_request to ensure that
|
441
|
+
we only handle requests while we're inside an exec() call
|
442
|
+
"""
|
443
|
+
if self._execing:
|
444
|
+
raise RuntimeError("Nested set_execing_flag call")
|
445
|
+
self._execing = True
|
446
|
+
try:
|
447
|
+
yield
|
448
|
+
finally:
|
449
|
+
self._execing = False
|
450
|
+
|
451
|
+
def _run_script(self, rerun_data: RerunData) -> None:
|
452
|
+
"""Run our script.
|
453
|
+
|
454
|
+
Parameters
|
455
|
+
----------
|
456
|
+
rerun_data: RerunData
|
457
|
+
The RerunData to use.
|
458
|
+
|
459
|
+
"""
|
460
|
+
|
461
|
+
assert self._is_in_script_thread()
|
462
|
+
|
463
|
+
# An explicit loop instead of recursion to avoid stack overflows
|
464
|
+
while True:
|
465
|
+
_LOGGER.debug("Running script %s", rerun_data)
|
466
|
+
start_time: float = timer()
|
467
|
+
prep_time: float = 0 # This will be overwritten once preparations are done.
|
468
|
+
|
469
|
+
if not rerun_data.fragment_id_queue:
|
470
|
+
# Don't clear session refs for media files if we're running a fragment.
|
471
|
+
# Otherwise, we're likely to remove files that still have corresponding
|
472
|
+
# download buttons/links to them present in the app, which will result
|
473
|
+
# in a 404 should the user click on them.
|
474
|
+
runtime.get_instance().media_file_mgr.clear_session_refs()
|
475
|
+
|
476
|
+
self._pages_manager.set_script_intent(
|
477
|
+
rerun_data.page_script_hash, rerun_data.page_name
|
478
|
+
)
|
479
|
+
active_script = self._pages_manager.get_initial_active_script(
|
480
|
+
rerun_data.page_script_hash, rerun_data.page_name
|
481
|
+
)
|
482
|
+
main_page_info = self._pages_manager.get_main_page()
|
483
|
+
|
484
|
+
page_script_hash = (
|
485
|
+
active_script["page_script_hash"]
|
486
|
+
if active_script is not None
|
487
|
+
else main_page_info["page_script_hash"]
|
488
|
+
)
|
489
|
+
|
490
|
+
ctx = self._get_script_run_ctx()
|
491
|
+
# Clear widget state on page change. This normally happens implicitly
|
492
|
+
# in the script run cleanup steps, but doing it explicitly ensures
|
493
|
+
# it happens even if a script run was interrupted.
|
494
|
+
previous_page_script_hash = ctx.page_script_hash
|
495
|
+
if previous_page_script_hash != page_script_hash:
|
496
|
+
# Page changed, enforce reset widget state where possible.
|
497
|
+
# This enforcement matters when a new script thread is started
|
498
|
+
# before the previous script run is completed (from user
|
499
|
+
# interaction). Use the widget ids from the rerun data to
|
500
|
+
# maintain some widget state, as the rerun data should
|
501
|
+
# contain the latest widget ids from the frontend.
|
502
|
+
widget_ids: set[str] = set()
|
503
|
+
|
504
|
+
if (
|
505
|
+
rerun_data.widget_states is not None
|
506
|
+
and rerun_data.widget_states.widgets is not None
|
507
|
+
):
|
508
|
+
widget_ids = {w.id for w in rerun_data.widget_states.widgets}
|
509
|
+
self._session_state.on_script_finished(widget_ids)
|
510
|
+
|
511
|
+
fragment_ids_this_run = list(rerun_data.fragment_id_queue)
|
512
|
+
|
513
|
+
ctx.reset(
|
514
|
+
query_string=rerun_data.query_string,
|
515
|
+
page_script_hash=page_script_hash,
|
516
|
+
fragment_ids_this_run=fragment_ids_this_run,
|
517
|
+
context_info=rerun_data.context_info,
|
518
|
+
)
|
519
|
+
|
520
|
+
self.on_event.send(
|
521
|
+
self,
|
522
|
+
event=ScriptRunnerEvent.SCRIPT_STARTED,
|
523
|
+
page_script_hash=page_script_hash,
|
524
|
+
fragment_ids_this_run=fragment_ids_this_run,
|
525
|
+
pages=self._pages_manager.get_pages(),
|
526
|
+
)
|
527
|
+
|
528
|
+
# Compile the script. Any errors thrown here will be surfaced
|
529
|
+
# to the user via a modal dialog in the frontend, and won't result
|
530
|
+
# in their previous script elements disappearing.
|
531
|
+
try:
|
532
|
+
if active_script is not None:
|
533
|
+
script_path = active_script["script_path"]
|
534
|
+
else:
|
535
|
+
# page must not be found
|
536
|
+
script_path = main_page_info["script_path"]
|
537
|
+
|
538
|
+
# At this point, we know that either
|
539
|
+
# * the script corresponding to the hash requested no longer
|
540
|
+
# exists, or
|
541
|
+
# * we were not able to find a script with the requested page
|
542
|
+
# name.
|
543
|
+
# In both of these cases, we want to send a page_not_found
|
544
|
+
# message to the frontend.
|
545
|
+
msg = ForwardMsg()
|
546
|
+
msg.page_not_found.page_name = rerun_data.page_name
|
547
|
+
ctx.enqueue(msg)
|
548
|
+
|
549
|
+
code = self._script_cache.get_bytecode(script_path)
|
550
|
+
|
551
|
+
except Exception as ex:
|
552
|
+
# We got a compile error. Send an error event and bail immediately.
|
553
|
+
_LOGGER.debug("Fatal script error", exc_info=ex)
|
554
|
+
self._session_state[SCRIPT_RUN_WITHOUT_ERRORS_KEY] = False
|
555
|
+
self.on_event.send(
|
556
|
+
self,
|
557
|
+
event=ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR,
|
558
|
+
exception=ex,
|
559
|
+
)
|
560
|
+
return
|
561
|
+
|
562
|
+
# If we get here, we've successfully compiled our script. The next step
|
563
|
+
# is to run it. Errors thrown during execution will be shown to the
|
564
|
+
# user as ExceptionElements.
|
565
|
+
|
566
|
+
# Create fake module. This gives us a name global namespace to
|
567
|
+
# execute the code in.
|
568
|
+
module = self._new_module("__main__")
|
569
|
+
|
570
|
+
# Install the fake module as the __main__ module. This allows
|
571
|
+
# the pickle module to work inside the user's code, since it now
|
572
|
+
# can know the module where the pickled objects stem from.
|
573
|
+
# IMPORTANT: This means we can't use "if __name__ == '__main__'" in
|
574
|
+
# our code, as it will point to the wrong module!!!
|
575
|
+
sys.modules["__main__"] = module
|
576
|
+
|
577
|
+
# Add special variables to the module's globals dict.
|
578
|
+
# Note: The following is a requirement for the CodeHasher to
|
579
|
+
# work correctly. The CodeHasher is scoped to
|
580
|
+
# files contained in the directory of __main__.__file__, which we
|
581
|
+
# assume is the main script directory.
|
582
|
+
module.__dict__["__file__"] = script_path
|
583
|
+
|
584
|
+
def code_to_exec(code=code, module=module, ctx=ctx, rerun_data=rerun_data):
|
585
|
+
with (
|
586
|
+
modified_sys_path(self._main_script_path),
|
587
|
+
self._set_execing_flag(),
|
588
|
+
):
|
589
|
+
# Run callbacks for widgets whose values have changed.
|
590
|
+
if rerun_data.widget_states is not None:
|
591
|
+
self._session_state.on_script_will_rerun(
|
592
|
+
rerun_data.widget_states
|
593
|
+
)
|
594
|
+
|
595
|
+
ctx.on_script_start()
|
596
|
+
|
597
|
+
if rerun_data.fragment_id_queue:
|
598
|
+
for fragment_id in rerun_data.fragment_id_queue:
|
599
|
+
try:
|
600
|
+
wrapped_fragment = self._fragment_storage.get(
|
601
|
+
fragment_id
|
602
|
+
)
|
603
|
+
wrapped_fragment()
|
604
|
+
|
605
|
+
except FragmentStorageKeyError:
|
606
|
+
# This can happen if the fragment_id is removed from the
|
607
|
+
# storage before the script runner gets to it. In this
|
608
|
+
# case, the fragment is simply skipped.
|
609
|
+
# Also, only log an error if the fragment is not an
|
610
|
+
# auto_rerun to avoid noise. If it is an auto_rerun, we
|
611
|
+
# might have a race condition where the fragment_id is
|
612
|
+
# removed but the webapp sends a rerun request before
|
613
|
+
# the removal information has reached the web app
|
614
|
+
# (see https://github.com/streamlit/streamlit/issues/9080).
|
615
|
+
if not rerun_data.is_auto_rerun:
|
616
|
+
_LOGGER.warning(
|
617
|
+
f"Couldn't find fragment with id {fragment_id}."
|
618
|
+
" This can happen if the fragment does not"
|
619
|
+
" exist anymore when this request is processed,"
|
620
|
+
" for example because a full app rerun happened"
|
621
|
+
" that did not register the fragment."
|
622
|
+
" Usually this doesn't happen or no action is"
|
623
|
+
" required, so its mainly for debugging."
|
624
|
+
)
|
625
|
+
except (RerunException, StopException) as e:
|
626
|
+
# The wrapped_fragment function is executed
|
627
|
+
# inside of a exec_func_with_error_handling call, so
|
628
|
+
# there is a correct handler for these exceptions.
|
629
|
+
raise e
|
630
|
+
except Exception:
|
631
|
+
# Ignore exceptions raised by fragments here as we don't
|
632
|
+
# want to stop the execution of other fragments. The
|
633
|
+
# error itself is already rendered within the wrapped
|
634
|
+
# fragment.
|
635
|
+
pass
|
636
|
+
|
637
|
+
else:
|
638
|
+
if PagesManager.uses_pages_directory:
|
639
|
+
_mpa_v1(self._main_script_path)
|
640
|
+
exec(code, module.__dict__)
|
641
|
+
self._fragment_storage.clear(
|
642
|
+
new_fragment_ids=ctx.new_fragment_ids
|
643
|
+
)
|
644
|
+
|
645
|
+
self._session_state.maybe_check_serializable()
|
646
|
+
# check for control requests, e.g. rerun requests have arrived
|
647
|
+
self._maybe_handle_execution_control_request()
|
648
|
+
|
649
|
+
prep_time = timer() - start_time
|
650
|
+
(
|
651
|
+
_,
|
652
|
+
run_without_errors,
|
653
|
+
rerun_exception_data,
|
654
|
+
premature_stop,
|
655
|
+
uncaught_exception,
|
656
|
+
) = exec_func_with_error_handling(code_to_exec, ctx)
|
657
|
+
# setting the session state here triggers a yield-callback call
|
658
|
+
# which reads self._requests and checks for rerun data
|
659
|
+
self._session_state[SCRIPT_RUN_WITHOUT_ERRORS_KEY] = run_without_errors
|
660
|
+
|
661
|
+
if rerun_exception_data:
|
662
|
+
# The handling for when a full script run or a fragment is stopped early
|
663
|
+
# is the same, so we only have one ScriptRunnerEvent for this scenario.
|
664
|
+
finished_event = ScriptRunnerEvent.SCRIPT_STOPPED_FOR_RERUN
|
665
|
+
elif rerun_data.fragment_id_queue:
|
666
|
+
finished_event = ScriptRunnerEvent.FRAGMENT_STOPPED_WITH_SUCCESS
|
667
|
+
else:
|
668
|
+
finished_event = ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
|
669
|
+
|
670
|
+
if ctx.gather_usage_stats:
|
671
|
+
try:
|
672
|
+
# Create and send page profile information
|
673
|
+
ctx.enqueue(
|
674
|
+
create_page_profile_message(
|
675
|
+
commands=ctx.tracked_commands,
|
676
|
+
exec_time=to_microseconds(timer() - start_time),
|
677
|
+
prep_time=to_microseconds(prep_time),
|
678
|
+
uncaught_exception=(
|
679
|
+
type(uncaught_exception).__name__
|
680
|
+
if uncaught_exception
|
681
|
+
else None
|
682
|
+
),
|
683
|
+
)
|
684
|
+
)
|
685
|
+
except Exception as ex:
|
686
|
+
# Always capture all exceptions since we want to make sure that
|
687
|
+
# the telemetry never causes any issues.
|
688
|
+
_LOGGER.debug("Failed to create page profile", exc_info=ex)
|
689
|
+
self._on_script_finished(ctx, finished_event, premature_stop)
|
690
|
+
|
691
|
+
# # Use _log_if_error() to make sure we never ever ever stop running the
|
692
|
+
# # script without meaning to.
|
693
|
+
_log_if_error(_clean_problem_modules)
|
694
|
+
|
695
|
+
if rerun_exception_data is not None:
|
696
|
+
rerun_data = rerun_exception_data
|
697
|
+
else:
|
698
|
+
break
|
699
|
+
|
700
|
+
def _on_script_finished(
|
701
|
+
self, ctx: ScriptRunContext, event: ScriptRunnerEvent, premature_stop: bool
|
702
|
+
) -> None:
|
703
|
+
"""Called when our script finishes executing, even if it finished
|
704
|
+
early with an exception. We perform post-run cleanup here.
|
705
|
+
"""
|
706
|
+
# Tell session_state to update itself in response
|
707
|
+
if not premature_stop:
|
708
|
+
self._session_state.on_script_finished(ctx.widget_ids_this_run)
|
709
|
+
|
710
|
+
# Signal that the script has finished. (We use SCRIPT_STOPPED_WITH_SUCCESS
|
711
|
+
# even if we were stopped with an exception.)
|
712
|
+
self.on_event.send(self, event=event)
|
713
|
+
|
714
|
+
# Remove orphaned files now that the script has run and files in use
|
715
|
+
# are marked as active.
|
716
|
+
runtime.get_instance().media_file_mgr.remove_orphaned_files()
|
717
|
+
|
718
|
+
# Force garbage collection to run, to help avoid memory use building up
|
719
|
+
# This is usually not an issue, but sometimes GC takes time to kick in and
|
720
|
+
# causes apps to go over resource limits, and forcing it to run between
|
721
|
+
# script runs is low cost, since we aren't doing much work anyway.
|
722
|
+
if config.get_option("runner.postScriptGC"):
|
723
|
+
gc.collect(2)
|
724
|
+
|
725
|
+
def _new_module(self, name: str) -> types.ModuleType:
|
726
|
+
"""Create a new module with the given name."""
|
727
|
+
return types.ModuleType(name)
|
728
|
+
|
729
|
+
|
730
|
+
def _clean_problem_modules() -> None:
|
731
|
+
"""Some modules are stateful, so we have to clear their state."""
|
732
|
+
|
733
|
+
if "keras" in sys.modules:
|
734
|
+
try:
|
735
|
+
keras = sys.modules["keras"]
|
736
|
+
keras.backend.clear_session()
|
737
|
+
except Exception:
|
738
|
+
# We don't want to crash the app if we can't clear the Keras session.
|
739
|
+
pass
|
740
|
+
|
741
|
+
if "matplotlib.pyplot" in sys.modules:
|
742
|
+
try:
|
743
|
+
plt = sys.modules["matplotlib.pyplot"]
|
744
|
+
plt.close("all")
|
745
|
+
except Exception:
|
746
|
+
# We don't want to crash the app if we can't close matplotlib
|
747
|
+
pass
|
748
|
+
|
749
|
+
|
750
|
+
# The reason this is not a decorator is because we want to make it clear at the
|
751
|
+
# calling location that this function is being used.
|
752
|
+
def _log_if_error(fn: Callable[[], None]) -> None:
|
753
|
+
try:
|
754
|
+
fn()
|
755
|
+
except Exception as e:
|
756
|
+
_LOGGER.warning(e)
|