streamlit 1.50.0__py3-none-any.whl → 1.52.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamlit/__init__.py +5 -1
- streamlit/commands/execution_control.py +89 -14
- streamlit/commands/navigation.py +4 -6
- streamlit/commands/page_config.py +4 -6
- streamlit/components/v1/component_arrow.py +7 -7
- streamlit/components/v2/__init__.py +514 -0
- streamlit/components/v2/bidi_component/__init__.py +20 -0
- streamlit/components/v2/bidi_component/constants.py +29 -0
- streamlit/components/v2/bidi_component/main.py +534 -0
- streamlit/components/v2/bidi_component/serialization.py +272 -0
- streamlit/components/v2/bidi_component/state.py +92 -0
- streamlit/components/v2/component_definition_resolver.py +143 -0
- streamlit/components/v2/component_file_watcher.py +403 -0
- streamlit/components/v2/component_manager.py +439 -0
- streamlit/components/v2/component_manifest_handler.py +122 -0
- streamlit/components/v2/component_path_utils.py +245 -0
- streamlit/components/v2/component_registry.py +426 -0
- streamlit/components/v2/get_bidi_component_manager.py +51 -0
- streamlit/components/v2/manifest_scanner.py +615 -0
- streamlit/components/v2/presentation.py +198 -0
- streamlit/components/v2/types.py +324 -0
- streamlit/config.py +456 -53
- streamlit/config_option.py +4 -1
- streamlit/config_util.py +650 -1
- streamlit/connections/snowflake_connection.py +1 -1
- streamlit/connections/snowpark_connection.py +1 -1
- streamlit/dataframe_util.py +33 -26
- streamlit/delta_generator.py +13 -4
- streamlit/delta_generator_singletons.py +11 -15
- streamlit/deprecation_util.py +17 -6
- streamlit/elements/alert.py +16 -0
- streamlit/elements/arrow.py +68 -10
- streamlit/elements/bokeh_chart.py +10 -78
- streamlit/elements/code.py +2 -2
- streamlit/elements/deck_gl_json_chart.py +98 -40
- streamlit/elements/dialog_decorator.py +2 -1
- streamlit/elements/exception.py +4 -2
- streamlit/elements/form.py +27 -0
- streamlit/elements/graphviz_chart.py +1 -3
- streamlit/elements/heading.py +63 -10
- streamlit/elements/html.py +13 -2
- streamlit/elements/image.py +3 -5
- streamlit/elements/layouts.py +59 -33
- streamlit/elements/lib/built_in_chart_utils.py +50 -19
- streamlit/elements/lib/color_util.py +9 -19
- streamlit/elements/lib/column_config_utils.py +9 -12
- streamlit/elements/lib/column_types.py +40 -12
- streamlit/elements/lib/dialog.py +2 -2
- streamlit/elements/lib/image_utils.py +3 -5
- streamlit/elements/lib/layout_utils.py +100 -13
- streamlit/elements/lib/mutable_status_container.py +2 -2
- streamlit/elements/lib/options_selector_utils.py +2 -2
- streamlit/elements/lib/pandas_styler_utils.py +17 -9
- streamlit/elements/lib/shortcut_utils.py +152 -0
- streamlit/elements/lib/utils.py +4 -4
- streamlit/elements/map.py +80 -37
- streamlit/elements/markdown.py +50 -3
- streamlit/elements/media.py +5 -7
- streamlit/elements/metric.py +34 -6
- streamlit/elements/pdf.py +2 -4
- streamlit/elements/plotly_chart.py +197 -20
- streamlit/elements/progress.py +2 -4
- streamlit/elements/space.py +113 -0
- streamlit/elements/spinner.py +1 -1
- streamlit/elements/text.py +20 -3
- streamlit/elements/toast.py +2 -0
- streamlit/elements/vega_charts.py +356 -149
- streamlit/elements/widgets/audio_input.py +12 -11
- streamlit/elements/widgets/button.py +280 -43
- streamlit/elements/widgets/button_group.py +60 -9
- streamlit/elements/widgets/camera_input.py +3 -5
- streamlit/elements/widgets/chat.py +307 -43
- streamlit/elements/widgets/color_picker.py +8 -1
- streamlit/elements/widgets/data_editor.py +88 -44
- streamlit/elements/widgets/file_uploader.py +9 -11
- streamlit/elements/widgets/multiselect.py +4 -3
- streamlit/elements/widgets/number_input.py +4 -4
- streamlit/elements/widgets/radio.py +10 -3
- streamlit/elements/widgets/select_slider.py +8 -5
- streamlit/elements/widgets/selectbox.py +6 -3
- streamlit/elements/widgets/slider.py +38 -42
- streamlit/elements/widgets/text_widgets.py +2 -0
- streamlit/elements/widgets/time_widgets.py +587 -21
- streamlit/elements/write.py +27 -6
- streamlit/emojis.py +1 -1
- streamlit/errors.py +137 -0
- streamlit/git_util.py +1 -1
- streamlit/hello/hello.py +8 -0
- streamlit/hello/utils.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/navigation/page.py +11 -1
- streamlit/net_util.py +2 -2
- streamlit/proto/Alert_pb2.pyi +3 -3
- streamlit/proto/AppPage_pb2.pyi +7 -1
- streamlit/proto/ArrowData_pb2.py +27 -0
- streamlit/proto/ArrowData_pb2.pyi +52 -0
- streamlit/proto/ArrowNamedDataSet_pb2.pyi +7 -1
- streamlit/proto/ArrowVegaLiteChart_pb2.pyi +7 -1
- streamlit/proto/Arrow_pb2.py +10 -10
- streamlit/proto/Arrow_pb2.pyi +19 -12
- streamlit/proto/AudioInput_pb2.pyi +7 -1
- streamlit/proto/Audio_pb2.pyi +7 -1
- streamlit/proto/AuthRedirect_pb2.pyi +7 -1
- streamlit/proto/AutoRerun_pb2.pyi +7 -1
- streamlit/proto/BackMsg_pb2.py +4 -2
- streamlit/proto/BackMsg_pb2.pyi +34 -4
- streamlit/proto/Balloons_pb2.pyi +7 -1
- streamlit/proto/BidiComponent_pb2.py +34 -0
- streamlit/proto/BidiComponent_pb2.pyi +159 -0
- streamlit/proto/Block_pb2.py +7 -7
- streamlit/proto/Block_pb2.pyi +39 -36
- streamlit/proto/BokehChart_pb2.pyi +7 -1
- streamlit/proto/ButtonGroup_pb2.pyi +9 -9
- streamlit/proto/Button_pb2.py +2 -2
- streamlit/proto/Button_pb2.pyi +11 -2
- streamlit/proto/CameraInput_pb2.pyi +7 -1
- streamlit/proto/ChatInput_pb2.py +6 -6
- streamlit/proto/ChatInput_pb2.pyi +18 -6
- streamlit/proto/Checkbox_pb2.pyi +3 -3
- streamlit/proto/ClientState_pb2.pyi +10 -4
- streamlit/proto/Code_pb2.pyi +7 -1
- streamlit/proto/ColorPicker_pb2.pyi +7 -1
- streamlit/proto/Common_pb2.py +3 -3
- streamlit/proto/Common_pb2.pyi +35 -23
- streamlit/proto/Components_pb2.pyi +19 -13
- streamlit/proto/DataFrame_pb2.pyi +55 -49
- streamlit/proto/DateInput_pb2.pyi +7 -1
- streamlit/proto/DateTimeInput_pb2.py +28 -0
- streamlit/proto/DateTimeInput_pb2.pyi +92 -0
- streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
- streamlit/proto/DeckGlJsonChart_pb2.pyi +12 -6
- streamlit/proto/Delta_pb2.pyi +7 -1
- streamlit/proto/DocString_pb2.pyi +10 -4
- streamlit/proto/DownloadButton_pb2.py +2 -2
- streamlit/proto/DownloadButton_pb2.pyi +16 -2
- streamlit/proto/Element_pb2.py +7 -3
- streamlit/proto/Element_pb2.pyi +33 -5
- streamlit/proto/Empty_pb2.pyi +7 -1
- streamlit/proto/Exception_pb2.pyi +7 -1
- streamlit/proto/Favicon_pb2.pyi +7 -1
- streamlit/proto/FileUploader_pb2.pyi +7 -1
- streamlit/proto/ForwardMsg_pb2.py +12 -10
- streamlit/proto/ForwardMsg_pb2.pyi +42 -15
- streamlit/proto/GapSize_pb2.pyi +4 -4
- streamlit/proto/GitInfo_pb2.pyi +3 -3
- streamlit/proto/GraphVizChart_pb2.pyi +7 -1
- streamlit/proto/Heading_pb2.pyi +7 -1
- streamlit/proto/HeightConfig_pb2.py +2 -2
- streamlit/proto/HeightConfig_pb2.pyi +13 -4
- streamlit/proto/Html_pb2.py +2 -2
- streamlit/proto/Html_pb2.pyi +11 -2
- streamlit/proto/IFrame_pb2.pyi +7 -1
- streamlit/proto/Image_pb2.pyi +10 -4
- streamlit/proto/Json_pb2.pyi +7 -1
- streamlit/proto/LabelVisibilityMessage_pb2.pyi +3 -3
- streamlit/proto/LinkButton_pb2.py +2 -2
- streamlit/proto/LinkButton_pb2.pyi +15 -2
- streamlit/proto/Logo_pb2.pyi +7 -1
- streamlit/proto/Markdown_pb2.pyi +3 -3
- streamlit/proto/Metric_pb2.pyi +7 -7
- streamlit/proto/MetricsEvent_pb2.pyi +10 -4
- streamlit/proto/MultiSelect_pb2.pyi +7 -1
- streamlit/proto/NamedDataSet_pb2.pyi +7 -1
- streamlit/proto/Navigation_pb2.pyi +3 -3
- streamlit/proto/NewSession_pb2.py +18 -18
- streamlit/proto/NewSession_pb2.pyi +59 -40
- streamlit/proto/NumberInput_pb2.pyi +3 -3
- streamlit/proto/PageConfig_pb2.pyi +7 -7
- streamlit/proto/PageInfo_pb2.pyi +7 -1
- streamlit/proto/PageLink_pb2.py +2 -2
- streamlit/proto/PageLink_pb2.pyi +11 -2
- streamlit/proto/PageNotFound_pb2.pyi +7 -1
- streamlit/proto/PageProfile_pb2.pyi +13 -7
- streamlit/proto/PagesChanged_pb2.pyi +7 -1
- streamlit/proto/ParentMessage_pb2.pyi +7 -1
- streamlit/proto/PlotlyChart_pb2.py +8 -6
- streamlit/proto/PlotlyChart_pb2.pyi +9 -7
- streamlit/proto/Progress_pb2.pyi +7 -1
- streamlit/proto/Radio_pb2.pyi +7 -1
- streamlit/proto/RootContainer_pb2.pyi +1 -1
- streamlit/proto/Selectbox_pb2.pyi +7 -1
- streamlit/proto/SessionEvent_pb2.pyi +7 -1
- streamlit/proto/SessionStatus_pb2.pyi +7 -1
- streamlit/proto/Skeleton_pb2.pyi +3 -3
- streamlit/proto/Slider_pb2.pyi +5 -5
- streamlit/proto/Snow_pb2.pyi +7 -1
- streamlit/proto/Space_pb2.py +27 -0
- streamlit/proto/Space_pb2.pyi +48 -0
- streamlit/proto/Spinner_pb2.pyi +7 -1
- streamlit/proto/TextAlignmentConfig_pb2.py +29 -0
- streamlit/proto/TextAlignmentConfig_pb2.pyi +68 -0
- streamlit/proto/TextArea_pb2.pyi +7 -1
- streamlit/proto/TextInput_pb2.pyi +3 -3
- streamlit/proto/Text_pb2.pyi +7 -1
- streamlit/proto/TimeInput_pb2.pyi +7 -1
- streamlit/proto/Toast_pb2.pyi +7 -1
- streamlit/proto/VegaLiteChart_pb2.pyi +7 -1
- streamlit/proto/Video_pb2.pyi +6 -6
- streamlit/proto/WidgetStates_pb2.py +2 -2
- streamlit/proto/WidgetStates_pb2.pyi +23 -7
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +13 -4
- streamlit/proto/openmetrics_data_model_pb2.pyi +52 -52
- streamlit/runtime/app_session.py +65 -2
- streamlit/runtime/caching/cache_data_api.py +5 -5
- streamlit/runtime/caching/cache_errors.py +4 -1
- streamlit/runtime/caching/cache_resource_api.py +5 -4
- streamlit/runtime/caching/cache_utils.py +3 -2
- streamlit/runtime/caching/cached_message_replay.py +3 -3
- streamlit/runtime/caching/hashing.py +4 -5
- streamlit/runtime/caching/legacy_cache_api.py +2 -1
- streamlit/runtime/connection_factory.py +1 -3
- streamlit/runtime/download_data_util.py +53 -0
- streamlit/runtime/forward_msg_queue.py +5 -1
- streamlit/runtime/fragment.py +2 -1
- streamlit/runtime/media_file_manager.py +178 -2
- streamlit/runtime/memory_media_file_storage.py +1 -1
- streamlit/runtime/metrics_util.py +91 -3
- streamlit/runtime/runtime.py +14 -0
- streamlit/runtime/scriptrunner/exec_code.py +2 -1
- streamlit/runtime/scriptrunner/script_runner.py +5 -3
- streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
- streamlit/runtime/secrets.py +2 -4
- streamlit/runtime/session_manager.py +3 -1
- streamlit/runtime/state/common.py +30 -5
- streamlit/runtime/state/presentation.py +85 -0
- streamlit/runtime/state/query_params.py +80 -29
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +221 -17
- streamlit/runtime/state/widgets.py +19 -3
- streamlit/runtime/websocket_session_manager.py +3 -1
- streamlit/source_util.py +2 -2
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +557 -239
- streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
- streamlit/static/static/css/index.DgR7E2CV.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.ZJDbmVTx.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Dx0vI3vH.js} +1 -1
- streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.B7Ero7qQ.js} +3 -3
- streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.CG2XN1_g.js} +1 -1
- streamlit/static/static/js/IFrameUtil.DefezniK.js +1 -0
- streamlit/static/static/js/InputInstructions.Cj5-1zf6.js +1 -0
- streamlit/static/static/js/Particles.BfWfv0Aw.js +1 -0
- streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.CGQ8OgfO.js} +2 -2
- streamlit/static/static/js/StreamlitSyntaxHighlighter.DTKLpwhl.js +20 -0
- streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.B2qFUmd9.js} +1 -1
- streamlit/static/static/js/_arrayIncludes.B19Iyn2B.js +1 -0
- streamlit/static/static/js/_baseIndexOf.BTknn6Gb.js +1 -0
- streamlit/static/static/js/{base-input.BQft14La.js → base-input.o9tL8MDP.js} +4 -4
- streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.0BeV1IBL.js} +1 -1
- streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.RBO59fEm.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.CiTkUy0t.js +1 -0
- streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.DwNZg3Mw.js} +1 -1
- streamlit/static/static/js/embed.XT9xNd3F.js +195 -0
- streamlit/static/static/js/{es6.VpBPGCnM.js → es6.x9KsYQg-.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.ZVXpMPi0.js} +1 -1
- streamlit/static/static/js/index.5VPOamri.js +1 -0
- streamlit/static/static/js/index.8HslT92O.js +14 -0
- streamlit/static/static/js/index.AnXMIBz3.js +7 -0
- streamlit/static/static/js/index.B0yp3bM1.js +6 -0
- streamlit/static/static/js/index.B1fRb5wF.js +1 -0
- streamlit/static/static/js/index.B527JZdO.js +3 -0
- streamlit/static/static/js/index.BHgV-yW4.js +1 -0
- streamlit/static/static/js/index.BQr-XwGV.js +1 -0
- streamlit/static/static/js/index.BTtmaLDB.js +1 -0
- streamlit/static/static/js/index.BWB_91TA.js +1 -0
- streamlit/static/static/js/index.BfEKaEmw.js +1 -0
- streamlit/static/static/js/index.BfXjTO8b.js +1 -0
- streamlit/static/static/js/index.Bjy4NRu9.js +3 -0
- streamlit/static/static/js/index.Bu5JWpT_.js +1 -0
- streamlit/static/static/js/index.BuCx76ZV.js +1 -0
- streamlit/static/static/js/index.BxjzhVUb.js +2 -0
- streamlit/static/static/js/index.By55VdPY.js +1 -0
- streamlit/static/static/js/index.CF5MxTbK.js +1 -0
- streamlit/static/static/js/index.CLmq_z9K.js +1 -0
- streamlit/static/static/js/index.CNH4rdSz.js +1 -0
- streamlit/static/static/js/{index.B0H9IXUJ.js → index.CTgm_-jO.js} +10 -41
- streamlit/static/static/js/index.C_rK-Swb.js +188 -0
- streamlit/static/static/js/index.CjozwSzS.js +1 -0
- streamlit/static/static/js/{index.CH1tqnSs.js → index.CkGVt6-G.js} +1 -1
- streamlit/static/static/js/index.CuvXOyER.js +2 -0
- streamlit/static/static/js/{index.FFOzOWzC.js → index.CyUHWoCC.js} +2 -2
- streamlit/static/static/js/index.CyroQtI4.js +2 -0
- streamlit/static/static/js/index.D6HmkoDm.js +263 -0
- streamlit/static/static/js/index.DAqCNvsO.js +1 -0
- streamlit/static/static/js/index.DB_w_CZQ.js +1 -0
- streamlit/static/static/js/index.DBalctjj.js +2 -0
- streamlit/static/static/js/index.DK0RFJUG.js +11 -0
- streamlit/static/static/js/index.DMxc2XFp.js +151 -0
- streamlit/static/static/js/index.DO5utP74.js +2 -0
- streamlit/static/static/js/index.DS7lf09n.js +1 -0
- streamlit/static/static/js/index.DWexTVLY.js +1 -0
- streamlit/static/static/js/index.DXxnU5ej.js +1 -0
- streamlit/static/static/js/index.DcU3uDvB.js +2 -0
- streamlit/static/static/js/index.DlltaH7J.js +1 -0
- streamlit/static/static/js/index.DpNTZz82.js +27 -0
- streamlit/static/static/js/index.Dr9HIhQw.js +1 -0
- streamlit/static/static/js/index.DsgAU5lc.js +1 -0
- streamlit/static/static/js/{index.64ejlaaT.js → index.KfXqjDYy.js} +1 -1
- streamlit/static/static/js/index.PaidgjCs.js +1 -0
- streamlit/static/static/js/index.RJZuWCGA.js +1 -0
- streamlit/static/static/js/{index.Ctn27_AE.js → index.hbeqcRTn.js} +53 -122
- streamlit/static/static/js/index.q5hIQwAY.js +1 -0
- streamlit/static/static/js/index.rORSX6IW.js +1 -0
- streamlit/static/static/js/index.uSX757_v.js +1 -0
- streamlit/static/static/js/index.x_QRaLMd.js +1 -0
- streamlit/static/static/js/{input.s6pjQ49A.js → input.D5oh9-aB.js} +2 -2
- streamlit/static/static/js/main.q9oGOg0H.js +13 -0
- streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.5kCSFUJS.js} +1 -1
- streamlit/static/static/js/moment.C3j7ZXd7.js +4 -0
- streamlit/static/static/js/number-overlay-editor.Cn_LsK8N.js +9 -0
- streamlit/static/static/js/pandasStylerUtils.BqhXt51_.js +1 -0
- streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.DD9NK1Z8.js} +1 -1
- streamlit/static/static/js/record.B-tDciZb.js +1 -0
- streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.DACSyz29.js} +1 -1
- streamlit/static/static/js/styled-components.C3R090At.js +1 -0
- streamlit/static/static/js/threshold.Q1mXg5rX.js +1 -0
- streamlit/static/static/js/throttle.B0GR3Iyz.js +1 -0
- streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.BdhzPxrv.js} +1 -1
- streamlit/static/static/js/timer.C2hYhUse.js +1 -0
- streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.Db2pdqM2.js} +1 -1
- streamlit/static/static/js/uniqueId.CtqIr-Yh.js +1 -0
- streamlit/static/static/js/urls.BwSlolu9.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.Bfp6TnSw.js} +1 -1
- streamlit/static/static/js/useIntlLocale.hRV75Xgj.js +12 -0
- streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.QepX7n8Y.js} +1 -1
- streamlit/static/static/js/useUpdateUiValue.DHx8TzX6.js +1 -0
- streamlit/static/static/js/useWaveformController.WxVzpzEX.js +1 -0
- streamlit/static/static/js/value.B4vHRSi7.js +1 -0
- streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
- streamlit/static/static/js/withCalculatedWidth.DcKeRSWJ.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.CrHddARq.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- streamlit/string_util.py +9 -4
- streamlit/testing/v1/app_test.py +17 -2
- streamlit/testing/v1/element_tree.py +85 -9
- streamlit/testing/v1/util.py +2 -2
- streamlit/type_util.py +3 -4
- streamlit/url_util.py +1 -3
- streamlit/user_info.py +1 -2
- streamlit/util.py +3 -1
- streamlit/watcher/event_based_path_watcher.py +23 -12
- streamlit/watcher/local_sources_watcher.py +11 -1
- streamlit/watcher/path_watcher.py +9 -6
- streamlit/watcher/polling_path_watcher.py +4 -1
- streamlit/watcher/util.py +2 -2
- streamlit/web/bootstrap.py +24 -0
- streamlit/web/cli.py +51 -22
- streamlit/web/server/bidi_component_request_handler.py +193 -0
- streamlit/web/server/component_file_utils.py +97 -0
- streamlit/web/server/component_request_handler.py +8 -21
- streamlit/web/server/oauth_authlib_routes.py +5 -2
- streamlit/web/server/oidc_mixin.py +3 -1
- streamlit/web/server/routes.py +2 -2
- streamlit/web/server/server.py +9 -0
- streamlit/web/server/server_util.py +3 -1
- streamlit/web/server/upload_file_request_handler.py +19 -1
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/METADATA +10 -7
- streamlit-1.52.0.dist-info/RECORD +620 -0
- streamlit/static/static/css/index.CHEnSPGk.css +0 -1
- streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
- streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
- streamlit/static/static/js/Particles.CElH0XX2.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.DcuHuCyW.js +0 -1
- streamlit/static/static/js/index.6xX1278W.js +0 -975
- streamlit/static/static/js/index.B-hiXRzw.js +0 -1
- streamlit/static/static/js/index.B4cAbHP6.js +0 -1
- streamlit/static/static/js/index.B4dUQfni.js +0 -1
- streamlit/static/static/js/index.BPQo7BKk.js +0 -1
- streamlit/static/static/js/index.Baqa90pe.js +0 -2
- streamlit/static/static/js/index.Bj9JgOEC.js +0 -1
- streamlit/static/static/js/index.BjCwMzj4.js +0 -3
- streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
- streamlit/static/static/js/index.Bxz2yX3P.js +0 -1
- streamlit/static/static/js/index.BycLveZ4.js +0 -1
- streamlit/static/static/js/index.C9BdUqTi.js +0 -1
- streamlit/static/static/js/index.CFMf5_ez.js +0 -197
- streamlit/static/static/js/index.CGYqqs6j.js +0 -1
- streamlit/static/static/js/index.CMItVsFA.js +0 -1
- streamlit/static/static/js/index.CTBk8Vk2.js +0 -1
- streamlit/static/static/js/index.CiAQIz1H.js +0 -7
- streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
- streamlit/static/static/js/index.Ck8rQ9OL.js +0 -1
- streamlit/static/static/js/index.ClELlchS.js +0 -1617
- streamlit/static/static/js/index.Cnpi3o3E.js +0 -1
- streamlit/static/static/js/index.D2QEXQq_.js +0 -1
- streamlit/static/static/js/index.DH71Ezyj.js +0 -1
- streamlit/static/static/js/index.DHh-U0dK.js +0 -3
- streamlit/static/static/js/index.DK7hD7_w.js +0 -1
- streamlit/static/static/js/index.DKv_lNO7.js +0 -2
- streamlit/static/static/js/index.DNLrMXgm.js +0 -12
- streamlit/static/static/js/index.DW0Grddz.js +0 -1
- streamlit/static/static/js/index.Dbe-Q3C-.js +0 -2
- streamlit/static/static/js/index.DcPNYEUo.js +0 -1
- streamlit/static/static/js/index.DuxqVQpd.js +0 -1
- streamlit/static/static/js/index.GRUzrudl.js +0 -1
- streamlit/static/static/js/number-overlay-editor.DdgVR5m3.js +0 -9
- streamlit/static/static/js/uniqueId.RI1LJdtz.js +0 -1
- streamlit/static/static/js/useUpdateUiValue.DeXelfRH.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.C3561XxJ.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
- streamlit-1.50.0.dist-info/RECORD +0 -557
- {streamlit-1.50.0.data → streamlit-1.52.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/WHEEL +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
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
|
+
|
|
16
|
+
"""Component file watching utilities.
|
|
17
|
+
|
|
18
|
+
This module provides the `ComponentFileWatcher`, a utility that watches
|
|
19
|
+
component asset directories for changes and notifies a caller-provided callback
|
|
20
|
+
with the affected component names. It abstracts the underlying path-watcher
|
|
21
|
+
implementation and ensures exception-safe startup and cleanup.
|
|
22
|
+
|
|
23
|
+
Why this exists
|
|
24
|
+
---------------
|
|
25
|
+
Streamlit supports advanced Custom Components that ship a package of static
|
|
26
|
+
assets (for example, a Vite/Webpack build output). While a user develops their
|
|
27
|
+
app, those frontend files may change. The component registry for Custom
|
|
28
|
+
Components v2 must stay synchronized with the on-disk assets so that the server
|
|
29
|
+
can resolve the up-to-date files.
|
|
30
|
+
|
|
31
|
+
This watcher exists to keep the registry in sync by listening for changes in
|
|
32
|
+
component asset roots and notifying a higher-level manager that can re-resolve
|
|
33
|
+
the affected component definitions.
|
|
34
|
+
|
|
35
|
+
Notes
|
|
36
|
+
-----
|
|
37
|
+
- Watching is directory-based with a recursive glob ("**/*").
|
|
38
|
+
- Common noisy directories (e.g., ``node_modules``) are ignored in callbacks.
|
|
39
|
+
- Startup is exception-safe and does not leak partially created watchers.
|
|
40
|
+
|
|
41
|
+
See Also
|
|
42
|
+
--------
|
|
43
|
+
- :class:`streamlit.watcher.local_sources_watcher.LocalSourcesWatcher` - watches
|
|
44
|
+
app source files per session to trigger reruns.
|
|
45
|
+
- :class:`streamlit.components.v2.component_registry.BidiComponentRegistry` -
|
|
46
|
+
the server-side store of Custom Component v2 definitions that reacts to
|
|
47
|
+
watcher notifications.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
from __future__ import annotations
|
|
51
|
+
|
|
52
|
+
import threading
|
|
53
|
+
from typing import TYPE_CHECKING, Final, Protocol, cast
|
|
54
|
+
|
|
55
|
+
from streamlit.logger import get_logger
|
|
56
|
+
|
|
57
|
+
if TYPE_CHECKING:
|
|
58
|
+
from collections.abc import Callable
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
_LOGGER: Final = get_logger(__name__)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class _HasClose(Protocol):
|
|
66
|
+
def close(self) -> None: ...
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ComponentFileWatcher:
|
|
70
|
+
"""Handle file watching for component asset directories.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
component_update_callback : Callable[[list[str]], None]
|
|
75
|
+
Callback invoked when files change under any watched directory. It
|
|
76
|
+
receives a list of component names affected by the change.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def __init__(self, component_update_callback: Callable[[list[str]], None]) -> None:
|
|
80
|
+
"""Initialize the file watcher.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
component_update_callback : Callable[[list[str]], None]
|
|
85
|
+
Callback function to call when components under watched roots change.
|
|
86
|
+
Signature: (affected_component_names)
|
|
87
|
+
"""
|
|
88
|
+
self._component_update_callback = component_update_callback
|
|
89
|
+
self._lock = threading.Lock()
|
|
90
|
+
|
|
91
|
+
# File watching state
|
|
92
|
+
self._watched_directories: dict[
|
|
93
|
+
str, list[str]
|
|
94
|
+
] = {} # directory -> component_names
|
|
95
|
+
self._path_watchers: list[_HasClose] = [] # Store actual watcher instances
|
|
96
|
+
self._watching_active = False
|
|
97
|
+
|
|
98
|
+
# Store asset roots to watch: component_name -> asset_root
|
|
99
|
+
self._asset_watch_roots: dict[str, Path] = {}
|
|
100
|
+
|
|
101
|
+
# Default noisy directories to ignore in callbacks
|
|
102
|
+
self._ignored_dirs: tuple[str, ...] = (
|
|
103
|
+
"__pycache__",
|
|
104
|
+
".cache",
|
|
105
|
+
".git",
|
|
106
|
+
".hg",
|
|
107
|
+
".mypy_cache",
|
|
108
|
+
".pytest_cache",
|
|
109
|
+
".ruff_cache",
|
|
110
|
+
".svn",
|
|
111
|
+
".swc",
|
|
112
|
+
".yarn",
|
|
113
|
+
"coverage",
|
|
114
|
+
"node_modules",
|
|
115
|
+
"venv",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def is_watching_active(self) -> bool:
|
|
120
|
+
"""Check if file watching is currently active.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
bool
|
|
125
|
+
True if file watching is active, False otherwise
|
|
126
|
+
"""
|
|
127
|
+
return self._watching_active
|
|
128
|
+
|
|
129
|
+
def start_file_watching(self, asset_watch_roots: dict[str, Path]) -> None:
|
|
130
|
+
"""Start file watching for asset roots.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
asset_watch_roots : dict[str, Path]
|
|
135
|
+
Mapping of component names to asset root directories to watch.
|
|
136
|
+
|
|
137
|
+
Notes
|
|
138
|
+
-----
|
|
139
|
+
The method is idempotent: it stops any active watchers first, then
|
|
140
|
+
re-initializes watchers for the provided ``asset_watch_roots``.
|
|
141
|
+
"""
|
|
142
|
+
# Always stop first to ensure a clean state, then start with the new roots.
|
|
143
|
+
# This sequencing avoids races between concurrent stop/start calls.
|
|
144
|
+
self.stop_file_watching()
|
|
145
|
+
self._start_file_watching(asset_watch_roots)
|
|
146
|
+
|
|
147
|
+
def stop_file_watching(self) -> None:
|
|
148
|
+
"""Stop file watching and clean up watchers.
|
|
149
|
+
|
|
150
|
+
Notes
|
|
151
|
+
-----
|
|
152
|
+
This method is safe to call multiple times and will no-op if
|
|
153
|
+
watching is not active.
|
|
154
|
+
"""
|
|
155
|
+
with self._lock:
|
|
156
|
+
if not self._watching_active:
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
# Close all path watchers
|
|
160
|
+
for watcher in self._path_watchers:
|
|
161
|
+
try:
|
|
162
|
+
watcher.close()
|
|
163
|
+
except Exception: # noqa: PERF203
|
|
164
|
+
_LOGGER.exception("Failed to close path watcher")
|
|
165
|
+
|
|
166
|
+
self._path_watchers.clear()
|
|
167
|
+
self._watched_directories.clear()
|
|
168
|
+
# Also clear asset root references to avoid stale state retention
|
|
169
|
+
self._asset_watch_roots.clear()
|
|
170
|
+
self._watching_active = False
|
|
171
|
+
_LOGGER.debug("Stopped file watching for component registry")
|
|
172
|
+
|
|
173
|
+
def _start_file_watching(self, asset_watch_roots: dict[str, Path]) -> None:
|
|
174
|
+
"""Internal method to start file watching with the given roots.
|
|
175
|
+
|
|
176
|
+
This method is exception-safe: in case of failures while creating
|
|
177
|
+
watchers, any previously created watcher instances are closed and no
|
|
178
|
+
internal state is committed.
|
|
179
|
+
"""
|
|
180
|
+
with self._lock:
|
|
181
|
+
if self._watching_active:
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
if not asset_watch_roots:
|
|
185
|
+
_LOGGER.debug("No asset roots to watch")
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
path_watcher_class = self._get_default_path_watcher_class()
|
|
190
|
+
if path_watcher_class is None:
|
|
191
|
+
# NoOp watcher; skip activation
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
directories_to_watch = self._prepare_directories_to_watch(
|
|
195
|
+
asset_watch_roots
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
new_watchers, new_watched_dirs = self._build_watchers_for_directories(
|
|
199
|
+
path_watcher_class, directories_to_watch
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Commit new watchers and state only after successful creation
|
|
203
|
+
if new_watchers:
|
|
204
|
+
self._commit_watch_state(
|
|
205
|
+
new_watchers, new_watched_dirs, asset_watch_roots
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
_LOGGER.debug("No directories were watched; staying inactive")
|
|
209
|
+
except Exception:
|
|
210
|
+
_LOGGER.exception("Failed to start file watching")
|
|
211
|
+
|
|
212
|
+
def _get_default_path_watcher_class(self) -> type | None:
|
|
213
|
+
"""Return the default path watcher class.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
type | None
|
|
218
|
+
The concrete path watcher class to instantiate, or ``None`` if
|
|
219
|
+
the NoOp watcher is configured and file watching should be
|
|
220
|
+
skipped.
|
|
221
|
+
"""
|
|
222
|
+
from streamlit.watcher.path_watcher import (
|
|
223
|
+
NoOpPathWatcher,
|
|
224
|
+
get_default_path_watcher_class,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
path_watcher_class = get_default_path_watcher_class()
|
|
228
|
+
if path_watcher_class is NoOpPathWatcher:
|
|
229
|
+
_LOGGER.debug("NoOpPathWatcher in use; skipping component file watching")
|
|
230
|
+
return None
|
|
231
|
+
return path_watcher_class
|
|
232
|
+
|
|
233
|
+
def _prepare_directories_to_watch(
|
|
234
|
+
self, asset_watch_roots: dict[str, Path]
|
|
235
|
+
) -> dict[str, list[str]]:
|
|
236
|
+
"""Build a mapping of directory to component names.
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
asset_watch_roots : dict[str, Path]
|
|
241
|
+
Mapping of component names to their asset root directories.
|
|
242
|
+
|
|
243
|
+
Returns
|
|
244
|
+
-------
|
|
245
|
+
dict[str, list[str]]
|
|
246
|
+
A map from absolute directory path to a deduplicated list of
|
|
247
|
+
component names contained in that directory.
|
|
248
|
+
"""
|
|
249
|
+
directories_to_watch: dict[str, list[str]] = {}
|
|
250
|
+
for comp_name, root in asset_watch_roots.items():
|
|
251
|
+
directory = str(root.resolve())
|
|
252
|
+
if directory not in directories_to_watch:
|
|
253
|
+
directories_to_watch[directory] = []
|
|
254
|
+
if comp_name not in directories_to_watch[directory]:
|
|
255
|
+
directories_to_watch[directory].append(comp_name)
|
|
256
|
+
return directories_to_watch
|
|
257
|
+
|
|
258
|
+
def _build_watchers_for_directories(
|
|
259
|
+
self, path_watcher_class: type, directories_to_watch: dict[str, list[str]]
|
|
260
|
+
) -> tuple[list[_HasClose], dict[str, list[str]]]:
|
|
261
|
+
"""Create watchers for directories with rollback on failure.
|
|
262
|
+
|
|
263
|
+
Parameters
|
|
264
|
+
----------
|
|
265
|
+
path_watcher_class : type
|
|
266
|
+
The path watcher class to instantiate for each directory.
|
|
267
|
+
directories_to_watch : dict[str, list[str]]
|
|
268
|
+
A map of directory to the associated component name list.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
tuple[list[_HasClose], dict[str, list[str]]]
|
|
273
|
+
The list of created watcher instances and the watched directory
|
|
274
|
+
mapping.
|
|
275
|
+
|
|
276
|
+
Raises
|
|
277
|
+
------
|
|
278
|
+
Exception
|
|
279
|
+
Propagates any exception during watcher creation after closing
|
|
280
|
+
already-created watchers.
|
|
281
|
+
"""
|
|
282
|
+
new_watchers: list[_HasClose] = []
|
|
283
|
+
new_watched_dirs: dict[str, list[str]] = {}
|
|
284
|
+
|
|
285
|
+
for directory, component_names in directories_to_watch.items():
|
|
286
|
+
try:
|
|
287
|
+
cb = self._make_directory_callback(tuple(component_names))
|
|
288
|
+
# Use a glob pattern that matches all files to let Streamlit's
|
|
289
|
+
# watcher handle MD5 calculation and change detection
|
|
290
|
+
watcher = path_watcher_class(
|
|
291
|
+
directory,
|
|
292
|
+
cb,
|
|
293
|
+
glob_pattern="**/*",
|
|
294
|
+
allow_nonexistent=False,
|
|
295
|
+
)
|
|
296
|
+
new_watchers.append(cast("_HasClose", watcher))
|
|
297
|
+
new_watched_dirs[directory] = component_names
|
|
298
|
+
_LOGGER.debug(
|
|
299
|
+
"Prepared watcher for directory %s (components: %s)",
|
|
300
|
+
directory,
|
|
301
|
+
component_names,
|
|
302
|
+
)
|
|
303
|
+
except Exception: # noqa: PERF203
|
|
304
|
+
# Roll back watchers created so far
|
|
305
|
+
self._rollback_watchers(new_watchers)
|
|
306
|
+
raise
|
|
307
|
+
|
|
308
|
+
return new_watchers, new_watched_dirs
|
|
309
|
+
|
|
310
|
+
def _commit_watch_state(
|
|
311
|
+
self,
|
|
312
|
+
new_watchers: list[_HasClose],
|
|
313
|
+
new_watched_dirs: dict[str, list[str]],
|
|
314
|
+
asset_watch_roots: dict[str, Path],
|
|
315
|
+
) -> None:
|
|
316
|
+
"""Commit created watchers and mark watching active.
|
|
317
|
+
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
new_watchers : list[_HasClose]
|
|
321
|
+
Fully initialized watcher instances.
|
|
322
|
+
new_watched_dirs : dict[str, list[str]]
|
|
323
|
+
Mapping from directory to component names.
|
|
324
|
+
asset_watch_roots : dict[str, Path]
|
|
325
|
+
The asset roots used to initialize watchers; stored for reference.
|
|
326
|
+
"""
|
|
327
|
+
self._path_watchers = new_watchers
|
|
328
|
+
self._watched_directories = new_watched_dirs
|
|
329
|
+
self._asset_watch_roots = dict(asset_watch_roots)
|
|
330
|
+
self._watching_active = True
|
|
331
|
+
_LOGGER.debug(
|
|
332
|
+
"Started file watching for %d directories", len(self._watched_directories)
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
def _rollback_watchers(self, watchers: list[_HasClose]) -> None:
|
|
336
|
+
"""Close any created watchers when setup fails.
|
|
337
|
+
|
|
338
|
+
Parameters
|
|
339
|
+
----------
|
|
340
|
+
watchers : list[_HasClose]
|
|
341
|
+
Watcher instances that were successfully created before a failure.
|
|
342
|
+
"""
|
|
343
|
+
for w in watchers:
|
|
344
|
+
try:
|
|
345
|
+
w.close()
|
|
346
|
+
except Exception: # noqa: PERF203
|
|
347
|
+
_LOGGER.exception("Failed to close path watcher during rollback")
|
|
348
|
+
|
|
349
|
+
def _make_directory_callback(self, comps: tuple[str, ...]) -> Callable[[str], None]:
|
|
350
|
+
"""Create a callback for a directory watcher that captures component names."""
|
|
351
|
+
|
|
352
|
+
def callback(changed_path: str) -> None:
|
|
353
|
+
if self._is_in_ignored_directory(changed_path):
|
|
354
|
+
_LOGGER.debug("Ignoring change in noisy directory: %s", changed_path)
|
|
355
|
+
return
|
|
356
|
+
_LOGGER.debug(
|
|
357
|
+
"Directory change detected: %s, checking components: %s",
|
|
358
|
+
changed_path,
|
|
359
|
+
comps,
|
|
360
|
+
)
|
|
361
|
+
self._handle_component_change(list(comps))
|
|
362
|
+
|
|
363
|
+
return callback
|
|
364
|
+
|
|
365
|
+
def _handle_component_change(self, affected_components: list[str]) -> None:
|
|
366
|
+
"""Handle component changes for both directory and file events.
|
|
367
|
+
|
|
368
|
+
Parameters
|
|
369
|
+
----------
|
|
370
|
+
affected_components : list[str]
|
|
371
|
+
List of component names affected by the change
|
|
372
|
+
"""
|
|
373
|
+
if not self._watching_active:
|
|
374
|
+
return
|
|
375
|
+
|
|
376
|
+
# Notify manager to handle re-resolution based on recorded API inputs
|
|
377
|
+
try:
|
|
378
|
+
self._component_update_callback(affected_components)
|
|
379
|
+
except Exception:
|
|
380
|
+
# Never allow exceptions from user callbacks to break watcher loops
|
|
381
|
+
_LOGGER.exception("Component update callback raised")
|
|
382
|
+
|
|
383
|
+
def _is_in_ignored_directory(self, changed_path: str) -> bool:
|
|
384
|
+
"""Return True if the changed path is inside an ignored directory.
|
|
385
|
+
|
|
386
|
+
Parameters
|
|
387
|
+
----------
|
|
388
|
+
changed_path : str
|
|
389
|
+
The filesystem path that triggered the change event.
|
|
390
|
+
|
|
391
|
+
Returns
|
|
392
|
+
-------
|
|
393
|
+
bool
|
|
394
|
+
True if the path is located inside one of the ignored directories,
|
|
395
|
+
False otherwise.
|
|
396
|
+
"""
|
|
397
|
+
try:
|
|
398
|
+
from pathlib import Path as _Path
|
|
399
|
+
|
|
400
|
+
parts = set(_Path(changed_path).resolve().parts)
|
|
401
|
+
return any(ignored in parts for ignored in self._ignored_dirs)
|
|
402
|
+
except Exception:
|
|
403
|
+
return False
|