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,296 @@
|
|
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
|
+
from typing import TYPE_CHECKING, Final
|
18
|
+
from weakref import WeakKeyDictionary
|
19
|
+
|
20
|
+
from streamlit import config, util
|
21
|
+
from streamlit.logger import get_logger
|
22
|
+
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
23
|
+
from streamlit.runtime.stats import CacheStat, CacheStatsProvider, group_stats
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from collections.abc import MutableMapping
|
27
|
+
|
28
|
+
from streamlit.runtime.app_session import AppSession
|
29
|
+
|
30
|
+
_LOGGER: Final = get_logger(__name__)
|
31
|
+
|
32
|
+
|
33
|
+
def populate_hash_if_needed(msg: ForwardMsg) -> str:
|
34
|
+
"""Computes and assigns the unique hash for a ForwardMsg.
|
35
|
+
|
36
|
+
If the ForwardMsg already has a hash, this is a no-op.
|
37
|
+
|
38
|
+
Parameters
|
39
|
+
----------
|
40
|
+
msg : ForwardMsg
|
41
|
+
|
42
|
+
Returns
|
43
|
+
-------
|
44
|
+
string
|
45
|
+
The message's hash, returned here for convenience. (The hash
|
46
|
+
will also be assigned to the ForwardMsg; callers do not need
|
47
|
+
to do this.)
|
48
|
+
|
49
|
+
"""
|
50
|
+
if msg.hash == "":
|
51
|
+
# Move the message's metadata aside. It's not part of the
|
52
|
+
# hash calculation.
|
53
|
+
metadata = msg.metadata
|
54
|
+
msg.ClearField("metadata")
|
55
|
+
|
56
|
+
# MD5 is good enough for what we need, which is uniqueness.
|
57
|
+
msg.hash = util.calc_md5(msg.SerializeToString())
|
58
|
+
|
59
|
+
# Restore metadata.
|
60
|
+
msg.metadata.CopyFrom(metadata)
|
61
|
+
|
62
|
+
return msg.hash
|
63
|
+
|
64
|
+
|
65
|
+
def create_reference_msg(msg: ForwardMsg) -> ForwardMsg:
|
66
|
+
"""Create a ForwardMsg that refers to the given message via its hash.
|
67
|
+
|
68
|
+
The reference message will also get a copy of the source message's
|
69
|
+
metadata.
|
70
|
+
|
71
|
+
Parameters
|
72
|
+
----------
|
73
|
+
msg : ForwardMsg
|
74
|
+
The ForwardMsg to create the reference to.
|
75
|
+
|
76
|
+
Returns
|
77
|
+
-------
|
78
|
+
ForwardMsg
|
79
|
+
A new ForwardMsg that "points" to the original message via the
|
80
|
+
ref_hash field.
|
81
|
+
|
82
|
+
"""
|
83
|
+
ref_msg = ForwardMsg()
|
84
|
+
ref_msg.ref_hash = populate_hash_if_needed(msg)
|
85
|
+
ref_msg.metadata.CopyFrom(msg.metadata)
|
86
|
+
return ref_msg
|
87
|
+
|
88
|
+
|
89
|
+
class ForwardMsgCache(CacheStatsProvider):
|
90
|
+
"""A cache of ForwardMsgs.
|
91
|
+
|
92
|
+
Large ForwardMsgs (e.g. those containing big DataFrame payloads) are
|
93
|
+
stored in this cache. The server can choose to send a ForwardMsg's hash,
|
94
|
+
rather than the message itself, to a client. Clients can then
|
95
|
+
request messages from this cache via another endpoint.
|
96
|
+
|
97
|
+
This cache is *not* thread safe. It's intended to only be accessed by
|
98
|
+
the server thread.
|
99
|
+
|
100
|
+
"""
|
101
|
+
|
102
|
+
class Entry:
|
103
|
+
"""Cache entry.
|
104
|
+
|
105
|
+
Stores the cached message, and the set of AppSessions
|
106
|
+
that we've sent the cached message to.
|
107
|
+
|
108
|
+
"""
|
109
|
+
|
110
|
+
def __init__(self, msg: ForwardMsg | None):
|
111
|
+
self.msg = msg
|
112
|
+
self._session_script_run_counts: MutableMapping[AppSession, int] = (
|
113
|
+
WeakKeyDictionary()
|
114
|
+
)
|
115
|
+
|
116
|
+
def __repr__(self) -> str:
|
117
|
+
return util.repr_(self)
|
118
|
+
|
119
|
+
def add_session_ref(self, session: AppSession, script_run_count: int) -> None:
|
120
|
+
"""Adds a reference to a AppSession that has referenced
|
121
|
+
this Entry's message.
|
122
|
+
|
123
|
+
Parameters
|
124
|
+
----------
|
125
|
+
session : AppSession
|
126
|
+
script_run_count : int
|
127
|
+
The session's run count at the time of the call
|
128
|
+
|
129
|
+
"""
|
130
|
+
prev_run_count = self._session_script_run_counts.get(session, 0)
|
131
|
+
if script_run_count < prev_run_count:
|
132
|
+
_LOGGER.error(
|
133
|
+
"New script_run_count (%s) is < prev_run_count (%s). "
|
134
|
+
"This should never happen!",
|
135
|
+
script_run_count,
|
136
|
+
prev_run_count,
|
137
|
+
)
|
138
|
+
script_run_count = prev_run_count
|
139
|
+
self._session_script_run_counts[session] = script_run_count
|
140
|
+
|
141
|
+
def has_session_ref(self, session: AppSession) -> bool:
|
142
|
+
return session in self._session_script_run_counts
|
143
|
+
|
144
|
+
def get_session_ref_age(
|
145
|
+
self, session: AppSession, script_run_count: int
|
146
|
+
) -> int:
|
147
|
+
"""The age of the given session's reference to the Entry,
|
148
|
+
given a new script_run_count.
|
149
|
+
|
150
|
+
"""
|
151
|
+
return script_run_count - self._session_script_run_counts[session]
|
152
|
+
|
153
|
+
def remove_session_ref(self, session: AppSession) -> None:
|
154
|
+
del self._session_script_run_counts[session]
|
155
|
+
|
156
|
+
def has_refs(self) -> bool:
|
157
|
+
"""True if this Entry has references from any AppSession.
|
158
|
+
|
159
|
+
If not, it can be removed from the cache.
|
160
|
+
"""
|
161
|
+
return len(self._session_script_run_counts) > 0
|
162
|
+
|
163
|
+
def __init__(self):
|
164
|
+
self._entries: dict[str, ForwardMsgCache.Entry] = {}
|
165
|
+
|
166
|
+
def __repr__(self) -> str:
|
167
|
+
return util.repr_(self)
|
168
|
+
|
169
|
+
def add_message(
|
170
|
+
self, msg: ForwardMsg, session: AppSession, script_run_count: int
|
171
|
+
) -> None:
|
172
|
+
"""Add a ForwardMsg to the cache.
|
173
|
+
|
174
|
+
The cache will also record a reference to the given AppSession,
|
175
|
+
so that it can track which sessions have already received
|
176
|
+
each given ForwardMsg.
|
177
|
+
|
178
|
+
Parameters
|
179
|
+
----------
|
180
|
+
msg : ForwardMsg
|
181
|
+
session : AppSession
|
182
|
+
script_run_count : int
|
183
|
+
The number of times the session's script has run
|
184
|
+
|
185
|
+
"""
|
186
|
+
populate_hash_if_needed(msg)
|
187
|
+
entry = self._entries.get(msg.hash, None)
|
188
|
+
if entry is None:
|
189
|
+
if config.get_option("global.storeCachedForwardMessagesInMemory"):
|
190
|
+
entry = ForwardMsgCache.Entry(msg)
|
191
|
+
else:
|
192
|
+
entry = ForwardMsgCache.Entry(None)
|
193
|
+
self._entries[msg.hash] = entry
|
194
|
+
entry.add_session_ref(session, script_run_count)
|
195
|
+
|
196
|
+
def get_message(self, hash: str) -> ForwardMsg | None:
|
197
|
+
"""Return the message with the given ID if it exists in the cache.
|
198
|
+
|
199
|
+
Parameters
|
200
|
+
----------
|
201
|
+
hash : str
|
202
|
+
The id of the message to retrieve.
|
203
|
+
|
204
|
+
Returns
|
205
|
+
-------
|
206
|
+
ForwardMsg | None
|
207
|
+
|
208
|
+
"""
|
209
|
+
entry = self._entries.get(hash, None)
|
210
|
+
return entry.msg if entry else None
|
211
|
+
|
212
|
+
def has_message_reference(
|
213
|
+
self, msg: ForwardMsg, session: AppSession, script_run_count: int
|
214
|
+
) -> bool:
|
215
|
+
"""Return True if a session has a reference to a message."""
|
216
|
+
populate_hash_if_needed(msg)
|
217
|
+
|
218
|
+
entry = self._entries.get(msg.hash, None)
|
219
|
+
if entry is None or not entry.has_session_ref(session):
|
220
|
+
return False
|
221
|
+
|
222
|
+
# Ensure we're not expired
|
223
|
+
age = entry.get_session_ref_age(session, script_run_count)
|
224
|
+
return age <= int(config.get_option("global.maxCachedMessageAge"))
|
225
|
+
|
226
|
+
def remove_refs_for_session(self, session: AppSession) -> None:
|
227
|
+
"""Remove refs for all entries for the given session.
|
228
|
+
|
229
|
+
This should be called when an AppSession is disconnected or closed.
|
230
|
+
|
231
|
+
Parameters
|
232
|
+
----------
|
233
|
+
session : AppSession
|
234
|
+
"""
|
235
|
+
|
236
|
+
# Operate on a copy of our entries dict.
|
237
|
+
# We may be deleting from it.
|
238
|
+
for msg_hash, entry in self._entries.copy().items():
|
239
|
+
if entry.has_session_ref(session):
|
240
|
+
entry.remove_session_ref(session)
|
241
|
+
|
242
|
+
if not entry.has_refs():
|
243
|
+
# The entry has no more references. Remove it from
|
244
|
+
# the cache completely.
|
245
|
+
del self._entries[msg_hash]
|
246
|
+
|
247
|
+
def remove_expired_entries_for_session(
|
248
|
+
self, session: AppSession, script_run_count: int
|
249
|
+
) -> None:
|
250
|
+
"""Remove any cached messages that have expired from the given session.
|
251
|
+
|
252
|
+
This should be called each time a AppSession finishes executing.
|
253
|
+
|
254
|
+
Parameters
|
255
|
+
----------
|
256
|
+
session : AppSession
|
257
|
+
script_run_count : int
|
258
|
+
The number of times the session's script has run
|
259
|
+
|
260
|
+
"""
|
261
|
+
max_age = config.get_option("global.maxCachedMessageAge")
|
262
|
+
|
263
|
+
# Operate on a copy of our entries dict.
|
264
|
+
# We may be deleting from it.
|
265
|
+
for msg_hash, entry in self._entries.copy().items():
|
266
|
+
if not entry.has_session_ref(session):
|
267
|
+
continue
|
268
|
+
|
269
|
+
age = entry.get_session_ref_age(session, script_run_count)
|
270
|
+
if age > max_age:
|
271
|
+
_LOGGER.debug(
|
272
|
+
"Removing expired entry [session=%s, hash=%s, age=%s]",
|
273
|
+
id(session),
|
274
|
+
msg_hash,
|
275
|
+
age,
|
276
|
+
)
|
277
|
+
entry.remove_session_ref(session)
|
278
|
+
if not entry.has_refs():
|
279
|
+
# The entry has no more references. Remove it from
|
280
|
+
# the cache completely.
|
281
|
+
del self._entries[msg_hash]
|
282
|
+
|
283
|
+
def clear(self) -> None:
|
284
|
+
"""Remove all entries from the cache"""
|
285
|
+
self._entries.clear()
|
286
|
+
|
287
|
+
def get_stats(self) -> list[CacheStat]:
|
288
|
+
stats: list[CacheStat] = [
|
289
|
+
CacheStat(
|
290
|
+
category_name="ForwardMessageCache",
|
291
|
+
cache_name="",
|
292
|
+
byte_length=entry.msg.ByteSize() if entry.msg is not None else 0,
|
293
|
+
)
|
294
|
+
for _, entry in self._entries.items()
|
295
|
+
]
|
296
|
+
return group_stats(stats)
|
@@ -0,0 +1,240 @@
|
|
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
|
+
from typing import TYPE_CHECKING, Any, Callable
|
18
|
+
|
19
|
+
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
20
|
+
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
from streamlit.proto.Delta_pb2 import Delta
|
23
|
+
|
24
|
+
|
25
|
+
class ForwardMsgQueue:
|
26
|
+
"""Accumulates a session's outgoing ForwardMsgs.
|
27
|
+
|
28
|
+
Each AppSession adds messages to its queue, and the Server periodically
|
29
|
+
flushes all session queues and delivers their messages to the appropriate
|
30
|
+
clients.
|
31
|
+
|
32
|
+
ForwardMsgQueue is not thread-safe - a queue should only be used from
|
33
|
+
a single thread.
|
34
|
+
"""
|
35
|
+
|
36
|
+
_before_enqueue_msg: Callable[[ForwardMsg], None] | None = None
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def on_before_enqueue_msg(
|
40
|
+
before_enqueue_msg: Callable[[ForwardMsg], None] | None,
|
41
|
+
) -> None:
|
42
|
+
"""Set a callback to be called before a message is enqueued.
|
43
|
+
Used in static streamlit app generation."""
|
44
|
+
ForwardMsgQueue._before_enqueue_msg = before_enqueue_msg
|
45
|
+
|
46
|
+
def __init__(self):
|
47
|
+
self._queue: list[ForwardMsg] = []
|
48
|
+
# A mapping of (delta_path -> _queue.indexof(msg)) for each
|
49
|
+
# Delta message in the queue. We use this for coalescing
|
50
|
+
# redundant outgoing Deltas (where a newer Delta supersedes
|
51
|
+
# an older Delta, with the same delta_path, that's still in the
|
52
|
+
# queue).
|
53
|
+
self._delta_index_map: dict[tuple[int, ...], int] = {}
|
54
|
+
|
55
|
+
def get_debug(self) -> dict[str, Any]:
|
56
|
+
from google.protobuf.json_format import MessageToDict
|
57
|
+
|
58
|
+
return {
|
59
|
+
"queue": [MessageToDict(m) for m in self._queue],
|
60
|
+
"ids": list(self._delta_index_map.keys()),
|
61
|
+
}
|
62
|
+
|
63
|
+
def is_empty(self) -> bool:
|
64
|
+
return len(self._queue) == 0
|
65
|
+
|
66
|
+
def enqueue(self, msg: ForwardMsg) -> None:
|
67
|
+
"""Add message into queue, possibly composing it with another message."""
|
68
|
+
|
69
|
+
if ForwardMsgQueue._before_enqueue_msg:
|
70
|
+
ForwardMsgQueue._before_enqueue_msg(msg)
|
71
|
+
|
72
|
+
if not _is_composable_message(msg):
|
73
|
+
self._queue.append(msg)
|
74
|
+
return
|
75
|
+
|
76
|
+
# If there's a Delta message with the same delta_path already in
|
77
|
+
# the queue - meaning that it refers to the same location in
|
78
|
+
# the app - we attempt to combine this new Delta into the old
|
79
|
+
# one. This is an optimization that prevents redundant Deltas
|
80
|
+
# from being sent to the frontend.
|
81
|
+
delta_key = tuple(msg.metadata.delta_path)
|
82
|
+
if delta_key in self._delta_index_map:
|
83
|
+
index = self._delta_index_map[delta_key]
|
84
|
+
old_msg = self._queue[index]
|
85
|
+
composed_delta = _maybe_compose_deltas(old_msg.delta, msg.delta)
|
86
|
+
if composed_delta is not None:
|
87
|
+
new_msg = ForwardMsg()
|
88
|
+
new_msg.delta.CopyFrom(composed_delta)
|
89
|
+
new_msg.metadata.CopyFrom(msg.metadata)
|
90
|
+
self._queue[index] = new_msg
|
91
|
+
return
|
92
|
+
|
93
|
+
# No composition occurred. Append this message to the queue, and
|
94
|
+
# store its index for potential future composition.
|
95
|
+
self._delta_index_map[delta_key] = len(self._queue)
|
96
|
+
self._queue.append(msg)
|
97
|
+
|
98
|
+
def clear(
|
99
|
+
self,
|
100
|
+
retain_lifecycle_msgs: bool = False,
|
101
|
+
fragment_ids_this_run: list[str] | None = None,
|
102
|
+
) -> None:
|
103
|
+
"""Clear the queue, potentially retaining lifecycle messages.
|
104
|
+
|
105
|
+
The retain_lifecycle_msgs argument exists because in some cases (in particular
|
106
|
+
when a currently running script is interrupted by a new BackMsg), we don't want
|
107
|
+
to remove certain messages from the queue as doing so may cause the client to
|
108
|
+
not hear about important script lifecycle events (such as the script being
|
109
|
+
stopped early in order to be rerun).
|
110
|
+
|
111
|
+
If fragment_ids_this_run is provided, delta messages not belonging to any
|
112
|
+
fragment or belonging to a fragment not in fragment_ids_this_run will be
|
113
|
+
preserved to prevent clearing messages unrelated to the running fragments.
|
114
|
+
"""
|
115
|
+
|
116
|
+
if not retain_lifecycle_msgs:
|
117
|
+
self._queue = []
|
118
|
+
else:
|
119
|
+
self._queue = [
|
120
|
+
_update_script_finished_message(msg, fragment_ids_this_run is not None)
|
121
|
+
for msg in self._queue
|
122
|
+
if msg.WhichOneof("type")
|
123
|
+
in {
|
124
|
+
"new_session",
|
125
|
+
"script_finished",
|
126
|
+
"session_status_changed",
|
127
|
+
"parent_message",
|
128
|
+
}
|
129
|
+
or (
|
130
|
+
# preserve all messages if this is a fragment rerun and...
|
131
|
+
fragment_ids_this_run is not None
|
132
|
+
and (
|
133
|
+
# the message is not a delta message
|
134
|
+
# (not associated with a fragment) or...
|
135
|
+
msg.delta is None
|
136
|
+
or (
|
137
|
+
# it is a delta but not associated with any of the passed
|
138
|
+
# fragments
|
139
|
+
msg.delta is not None
|
140
|
+
and (
|
141
|
+
msg.delta.fragment_id is None
|
142
|
+
or msg.delta.fragment_id not in fragment_ids_this_run
|
143
|
+
)
|
144
|
+
)
|
145
|
+
)
|
146
|
+
)
|
147
|
+
]
|
148
|
+
|
149
|
+
self._delta_index_map = {}
|
150
|
+
|
151
|
+
def flush(self) -> list[ForwardMsg]:
|
152
|
+
"""Clear the queue and return a list of the messages it contained
|
153
|
+
before being cleared.
|
154
|
+
"""
|
155
|
+
queue = self._queue
|
156
|
+
self.clear()
|
157
|
+
return queue
|
158
|
+
|
159
|
+
def __len__(self) -> int:
|
160
|
+
return len(self._queue)
|
161
|
+
|
162
|
+
|
163
|
+
def _is_composable_message(msg: ForwardMsg) -> bool:
|
164
|
+
"""True if the ForwardMsg is potentially composable with other ForwardMsgs."""
|
165
|
+
if not msg.HasField("delta"):
|
166
|
+
# Non-delta messages are never composable.
|
167
|
+
return False
|
168
|
+
|
169
|
+
# We never compose add_rows messages in Python, because the add_rows
|
170
|
+
# operation can raise errors, and we don't have a good way of handling
|
171
|
+
# those errors in the message queue.
|
172
|
+
delta_type = msg.delta.WhichOneof("type")
|
173
|
+
return delta_type != "add_rows" and delta_type != "arrow_add_rows"
|
174
|
+
|
175
|
+
|
176
|
+
def _maybe_compose_deltas(old_delta: Delta, new_delta: Delta) -> Delta | None:
|
177
|
+
"""Combines new_delta onto old_delta if possible.
|
178
|
+
|
179
|
+
If the combination takes place, the function returns a new Delta that
|
180
|
+
should replace old_delta in the queue.
|
181
|
+
|
182
|
+
If the new_delta is incompatible with old_delta, the function returns None.
|
183
|
+
In this case, the new_delta should just be appended to the queue as normal.
|
184
|
+
"""
|
185
|
+
old_delta_type = old_delta.WhichOneof("type")
|
186
|
+
if old_delta_type == "add_block":
|
187
|
+
# We never replace add_block deltas, because blocks can have
|
188
|
+
# other dependent deltas later in the queue. For example:
|
189
|
+
#
|
190
|
+
# placeholder = st.empty()
|
191
|
+
# placeholder.columns(1)
|
192
|
+
# placeholder.empty()
|
193
|
+
#
|
194
|
+
# The call to "placeholder.columns(1)" creates two blocks, a parent
|
195
|
+
# container with delta_path (0, 0), and a column child with
|
196
|
+
# delta_path (0, 0, 0). If the final "placeholder.empty()" Delta
|
197
|
+
# is composed with the parent container Delta, the frontend will
|
198
|
+
# throw an error when it tries to add that column child to what is
|
199
|
+
# now just an element, and not a block.
|
200
|
+
return None
|
201
|
+
|
202
|
+
new_delta_type = new_delta.WhichOneof("type")
|
203
|
+
if new_delta_type == "new_element":
|
204
|
+
return new_delta
|
205
|
+
|
206
|
+
if new_delta_type == "add_block":
|
207
|
+
return new_delta
|
208
|
+
|
209
|
+
return None
|
210
|
+
|
211
|
+
|
212
|
+
def _update_script_finished_message(
|
213
|
+
msg: ForwardMsg, is_fragment_run: bool
|
214
|
+
) -> ForwardMsg:
|
215
|
+
"""
|
216
|
+
When we are here, the message queue is cleared from non-lifecycle messages
|
217
|
+
before they were flushed to the browser.
|
218
|
+
|
219
|
+
If there were no non-lifecycle messages in the queue, changing the type here
|
220
|
+
should not matter for the frontend anyways, so we optimistically change the
|
221
|
+
`script_finished` message to `FINISHED_EARLY_FOR_RERUN`. This indicates to
|
222
|
+
the frontend that the previous run was interrupted by a new script start.
|
223
|
+
Otherwise, a `FINISHED_SUCCESSFULLY` message might trigger a reset of widget
|
224
|
+
states on the frontend.
|
225
|
+
"""
|
226
|
+
if msg.WhichOneof("type") == "script_finished" and (
|
227
|
+
# If this is not a fragment run (= full app run), its okay to change the
|
228
|
+
# script_finished type to FINISHED_EARLY_FOR_RERUN because another full app run
|
229
|
+
# is about to start.
|
230
|
+
# If this is a fragment run, it is allowed to change the state of
|
231
|
+
# all script_finished states except for FINISHED_SUCCESSFULLY, which we use to
|
232
|
+
# indicate that a full app run has finished successfully (in other words, a
|
233
|
+
# fragment should not modify the finished status of a full app run, because
|
234
|
+
# the fragment finished state is different and the frontend might not trigger
|
235
|
+
# cleanups etc. correctly).
|
236
|
+
is_fragment_run is False
|
237
|
+
or msg.script_finished != ForwardMsg.ScriptFinishedStatus.FINISHED_SUCCESSFULLY
|
238
|
+
):
|
239
|
+
msg.script_finished = ForwardMsg.ScriptFinishedStatus.FINISHED_EARLY_FOR_RERUN
|
240
|
+
return msg
|