streamlit 1.45.1__py3-none-any.whl → 1.46.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/auth_util.py +12 -12
- streamlit/cli_util.py +4 -3
- streamlit/column_config.py +11 -9
- streamlit/commands/echo.py +6 -4
- streamlit/commands/execution_control.py +33 -32
- streamlit/commands/experimental_query_params.py +2 -2
- streamlit/commands/logo.py +9 -4
- streamlit/commands/navigation.py +61 -18
- streamlit/commands/page_config.py +57 -47
- streamlit/components/types/base_custom_component.py +7 -7
- streamlit/components/v1/component_registry.py +7 -3
- streamlit/components/v1/components.py +1 -1
- streamlit/components/v1/custom_component.py +8 -8
- streamlit/config.py +289 -144
- streamlit/config_option.py +19 -15
- streamlit/config_util.py +29 -23
- streamlit/connections/__init__.py +2 -2
- streamlit/connections/base_connection.py +5 -5
- streamlit/connections/snowflake_connection.py +13 -11
- streamlit/connections/snowpark_connection.py +3 -3
- streamlit/connections/sql_connection.py +20 -18
- streamlit/connections/util.py +2 -2
- streamlit/cursor.py +6 -6
- streamlit/dataframe_util.py +52 -52
- streamlit/delta_generator.py +46 -48
- streamlit/delta_generator_singletons.py +3 -3
- streamlit/deprecation_util.py +6 -6
- streamlit/elements/alert.py +37 -29
- streamlit/elements/arrow.py +40 -22
- streamlit/elements/code.py +46 -13
- streamlit/elements/deck_gl_json_chart.py +38 -27
- streamlit/elements/dialog_decorator.py +3 -4
- streamlit/elements/doc_string.py +64 -58
- streamlit/elements/exception.py +23 -27
- streamlit/elements/form.py +41 -0
- streamlit/elements/graphviz_chart.py +1 -1
- streamlit/elements/heading.py +60 -9
- streamlit/elements/html.py +3 -4
- streamlit/elements/image.py +8 -9
- streamlit/elements/json.py +21 -2
- streamlit/elements/layouts.py +120 -31
- streamlit/elements/lib/built_in_chart_utils.py +96 -73
- streamlit/elements/lib/color_util.py +3 -3
- streamlit/elements/lib/column_config_utils.py +2 -4
- streamlit/elements/lib/column_types.py +14 -8
- streamlit/elements/lib/dialog.py +9 -5
- streamlit/elements/lib/image_utils.py +39 -40
- streamlit/elements/lib/js_number.py +4 -4
- streamlit/elements/lib/layout_utils.py +65 -1
- streamlit/elements/lib/mutable_status_container.py +14 -3
- streamlit/elements/lib/options_selector_utils.py +22 -12
- streamlit/elements/lib/pandas_styler_utils.py +25 -21
- streamlit/elements/lib/policies.py +6 -5
- streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
- streamlit/elements/lib/subtitle_utils.py +6 -9
- streamlit/elements/lib/utils.py +20 -5
- streamlit/elements/map.py +32 -56
- streamlit/elements/markdown.py +101 -12
- streamlit/elements/media.py +78 -21
- streamlit/elements/metric.py +32 -16
- streamlit/elements/plotly_chart.py +15 -15
- streamlit/elements/progress.py +33 -15
- streamlit/elements/spinner.py +31 -6
- streamlit/elements/text.py +21 -1
- streamlit/elements/toast.py +1 -2
- streamlit/elements/vega_charts.py +54 -23
- streamlit/elements/widgets/audio_input.py +24 -7
- streamlit/elements/widgets/button.py +26 -19
- streamlit/elements/widgets/button_group.py +10 -15
- streamlit/elements/widgets/camera_input.py +27 -7
- streamlit/elements/widgets/chat.py +91 -38
- streamlit/elements/widgets/checkbox.py +45 -4
- streamlit/elements/widgets/color_picker.py +40 -17
- streamlit/elements/widgets/data_editor.py +76 -37
- streamlit/elements/widgets/file_uploader.py +42 -13
- streamlit/elements/widgets/multiselect.py +7 -10
- streamlit/elements/widgets/number_input.py +123 -47
- streamlit/elements/widgets/radio.py +59 -13
- streamlit/elements/widgets/select_slider.py +35 -30
- streamlit/elements/widgets/selectbox.py +56 -9
- streamlit/elements/widgets/slider.py +190 -99
- streamlit/elements/widgets/text_widgets.py +54 -8
- streamlit/elements/widgets/time_widgets.py +53 -14
- streamlit/elements/write.py +5 -8
- streamlit/env_util.py +2 -7
- streamlit/error_util.py +16 -9
- streamlit/errors.py +69 -48
- streamlit/external/langchain/streamlit_callback_handler.py +10 -5
- streamlit/file_util.py +27 -10
- streamlit/git_util.py +29 -24
- streamlit/hello/animation_demo.py +9 -9
- streamlit/hello/dataframe_demo.py +5 -5
- streamlit/hello/hello.py +1 -0
- streamlit/hello/mapping_demo.py +7 -8
- streamlit/hello/plotting_demo.py +3 -3
- streamlit/hello/streamlit_app.py +28 -26
- streamlit/hello/utils.py +2 -1
- streamlit/logger.py +10 -11
- streamlit/navigation/page.py +11 -8
- streamlit/proto/Audio_pb2.py +4 -3
- streamlit/proto/Audio_pb2.pyi +8 -1
- streamlit/proto/Block_pb2.py +38 -29
- streamlit/proto/Block_pb2.pyi +72 -4
- streamlit/proto/ClientState_pb2.py +4 -4
- streamlit/proto/ClientState_pb2.pyi +7 -2
- streamlit/proto/Code_pb2.py +4 -2
- streamlit/proto/Code_pb2.pyi +1 -0
- streamlit/proto/DataFrame_pb2.pyi +1 -1
- streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
- streamlit/proto/Element_pb2.py +5 -3
- streamlit/proto/Element_pb2.pyi +20 -3
- streamlit/proto/GapSize_pb2.py +29 -0
- streamlit/proto/GapSize_pb2.pyi +70 -0
- streamlit/proto/HeightConfig_pb2.py +27 -0
- streamlit/proto/HeightConfig_pb2.pyi +48 -0
- streamlit/proto/NamedDataSet_pb2.pyi +1 -1
- streamlit/proto/Navigation_pb2.py +3 -3
- streamlit/proto/Navigation_pb2.pyi +4 -0
- streamlit/proto/NewSession_pb2.py +18 -16
- streamlit/proto/NewSession_pb2.pyi +29 -3
- streamlit/proto/PageConfig_pb2.py +7 -7
- streamlit/proto/PageConfig_pb2.pyi +21 -1
- streamlit/proto/Video_pb2.py +8 -7
- streamlit/proto/Video_pb2.pyi +8 -1
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +15 -1
- streamlit/runtime/__init__.py +1 -1
- streamlit/runtime/app_session.py +53 -40
- streamlit/runtime/caching/__init__.py +9 -9
- streamlit/runtime/caching/cache_data_api.py +36 -30
- streamlit/runtime/caching/cache_errors.py +4 -4
- streamlit/runtime/caching/cache_resource_api.py +8 -8
- streamlit/runtime/caching/cache_utils.py +15 -14
- streamlit/runtime/caching/cached_message_replay.py +14 -8
- streamlit/runtime/caching/hashing.py +91 -97
- streamlit/runtime/caching/legacy_cache_api.py +2 -2
- streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
- streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
- streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +12 -14
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -6
- streamlit/runtime/connection_factory.py +36 -36
- streamlit/runtime/context.py +58 -9
- streamlit/runtime/credentials.py +29 -40
- streamlit/runtime/forward_msg_queue.py +11 -11
- streamlit/runtime/fragment.py +7 -7
- streamlit/runtime/media_file_manager.py +3 -4
- streamlit/runtime/memory_media_file_storage.py +6 -5
- streamlit/runtime/memory_uploaded_file_manager.py +2 -2
- streamlit/runtime/metrics_util.py +11 -12
- streamlit/runtime/pages_manager.py +4 -6
- streamlit/runtime/runtime.py +8 -6
- streamlit/runtime/runtime_util.py +7 -6
- streamlit/runtime/scriptrunner/__init__.py +4 -4
- streamlit/runtime/scriptrunner/exec_code.py +12 -5
- streamlit/runtime/scriptrunner/magic.py +16 -12
- streamlit/runtime/scriptrunner/script_cache.py +1 -1
- streamlit/runtime/scriptrunner/script_runner.py +53 -29
- streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
- streamlit/runtime/scriptrunner_utils/script_requests.py +7 -4
- streamlit/runtime/scriptrunner_utils/script_run_context.py +10 -23
- streamlit/runtime/secrets.py +40 -35
- streamlit/runtime/session_manager.py +2 -1
- streamlit/runtime/state/__init__.py +5 -5
- streamlit/runtime/state/common.py +2 -2
- streamlit/runtime/state/query_params.py +13 -15
- streamlit/runtime/state/query_params_proxy.py +17 -13
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +52 -34
- streamlit/runtime/stats.py +2 -2
- streamlit/runtime/uploaded_file_manager.py +1 -1
- streamlit/runtime/websocket_session_manager.py +10 -6
- streamlit/source_util.py +8 -6
- streamlit/static/index.html +3 -17
- streamlit/static/manifest.json +1180 -0
- streamlit/static/static/css/{index.DqDwtg6_.css → index.CJVRHjQZ.css} +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.DU9IrB3M.js → ErrorOutline.esm.6PVAQvlT.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.P9rKwKo8.js → FileDownload.esm.BZQHC61b.js} +1 -1
- streamlit/static/static/js/{FileHelper.D7RMkx0e.js → FileHelper.Bn1VShMJ.js} +5 -5
- streamlit/static/static/js/{FormClearHelper.B67tgll0.js → FormClearHelper.CsFEiTNN.js} +1 -1
- streamlit/static/static/js/{Hooks.ncTJktu9.js → Hooks.DguOHQL1.js} +1 -1
- streamlit/static/static/js/{InputInstructions.D-Y8geDN.js → InputInstructions.CTYn2BJQ.js} +1 -1
- streamlit/static/static/js/{ProgressBar.B-kexwwD.js → ProgressBar.CPOGBKCi.js} +2 -2
- streamlit/static/static/js/{RenderInPortalIfExists.BgaoZgep.js → RenderInPortalIfExists.BYu_CZaF.js} +1 -1
- streamlit/static/static/js/Toolbar.gXKw7ANv.js +1 -0
- streamlit/static/static/js/UploadFileInfo.0DCkpDDf.js +6 -0
- streamlit/static/static/js/{base-input.BoAa1U94.js → base-input.DBYPj91R.js} +4 -4
- streamlit/static/static/js/{checkbox.Z6iSfe5F.js → checkbox.BUm2vnNv.js} +2 -2
- streamlit/static/static/js/{createSuper.B4oGDYRm.js → createSuper.KD4RuZ-W.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.msYws2Ou.js → data-grid-overlay-editor.CUwpDfvI.js} +1 -1
- streamlit/static/static/js/{downloader.kc14n2Hv.js → downloader.CkDtclup.js} +1 -1
- streamlit/static/static/js/{es6.CxQz807-.js → es6.Dlcvh_r0.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.B19u0ONI.js → iframeResizer.contentWindow.DOXlFfve.js} +1 -1
- streamlit/static/static/js/{index.BGga-hcS.js → index.B0cuGMAB.js} +25 -25
- streamlit/static/static/js/index.BCWTclSV.js +73 -0
- streamlit/static/static/js/index.BJY_fap7.js +1 -0
- streamlit/static/static/js/index.BL3l6dnk.js +1 -0
- streamlit/static/static/js/{index.BFz9U2y0.js → index.BMZzRZjB.js} +1 -1
- streamlit/static/static/js/{index.-5ruC9At.js → index.BOzUTGDe.js} +1 -1
- streamlit/static/static/js/index.BYI5iO-o.js +1 -0
- streamlit/static/static/js/index.BYo0ywlm.js +783 -0
- streamlit/static/static/js/{index.CmTAF0dM.js → index.BYz9btsY.js} +1 -1
- streamlit/static/static/js/{index.BHGGDa8K.js → index.CCVzQz0Z.js} +2 -2
- streamlit/static/static/js/index.CD6FydK9.js +1 -0
- streamlit/static/static/js/index.CDYEqgC8.js +2 -0
- streamlit/static/static/js/{index.BRXmLIsC.js → index.CMP9c4xA.js} +1 -1
- streamlit/static/static/js/index.CN30QAPD.js +1 -0
- streamlit/static/static/js/{index.LaIasviC.js → index.CNqWQkTe.js} +1 -1
- streamlit/static/static/js/index.CaxS67Xz.js +1 -0
- streamlit/static/static/js/{index.xNQq3Ei5.js → index.CbsT4sGW.js} +1 -1
- streamlit/static/static/js/index.ChAVlxpQ.js +1 -0
- streamlit/static/static/js/{index.BqfdT8-Q.js → index.ClLMMmDd.js} +1 -1
- streamlit/static/static/js/{index.BHXxWdde.js → index.D-O9rQmV.js} +1 -1
- streamlit/static/static/js/{index.9V1KdxfP.js → index.D4k7VZZL.js} +1 -1
- streamlit/static/static/js/index.DLBi0Ar1.js +1 -0
- streamlit/static/static/js/index.DVq5XmJo.js +197 -0
- streamlit/static/static/js/{index.BoigZiu7.js → index.DZKmKXWw.js} +1 -1
- streamlit/static/static/js/index.DkaVx80F.js +1 -0
- streamlit/static/static/js/index.Dr968Klx.js +1 -0
- streamlit/static/static/js/{index.BpILzHf_.js → index.DtUYLn9j.js} +20 -20
- streamlit/static/static/js/index.DwjYSyhs.js +1 -0
- streamlit/static/static/js/index.DzrImxu4.js +1 -0
- streamlit/static/static/js/index.HyGsn4VM.js +1 -0
- streamlit/static/static/js/index.OwxC65od.js +12 -0
- streamlit/static/static/js/index.PZs7VZkC.js +1 -0
- streamlit/static/static/js/index.Voiqpj4q.js +1 -0
- streamlit/static/static/js/index.bSROvR-J.js +3 -0
- streamlit/static/static/js/index.oT9GD3l4.js +1 -0
- streamlit/static/static/js/{index.DeB9iKFW.js → index.qb-yAPH6.js} +255 -255
- streamlit/static/static/js/index.rJFy_Ygy.js +2 -0
- streamlit/static/static/js/{input.DsCfafm0.js → input.CwQtEnFN.js} +2 -2
- streamlit/static/static/js/{memory.nY_lMTtu.js → memory.C5XaFIjR.js} +1 -1
- streamlit/static/static/js/{mergeWith.B_7zmsM4.js → mergeWith.DzwwH6AG.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.CSeVhHRU.js → number-overlay-editor.Dx0XqCkD.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.nNhsvgRd.js → possibleConstructorReturn.CVfSu9Ws.js} +1 -1
- streamlit/static/static/js/{sandbox.Cgm3iuL6.js → sandbox.BT0gdMXk.js} +1 -1
- streamlit/static/static/js/{textarea.BR8rlyih.js → textarea.DNCbrtbM.js} +2 -2
- streamlit/static/static/js/{timepicker.w4XhAenH.js → timepicker.4UYJD9Ts.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CgkEPBwD.js → toConsumableArray.DUmnaVWV.js} +1 -1
- streamlit/static/static/js/{uniqueId.j-1rlNNH.js → uniqueId.DUvh-GL8.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.zXY9CjFS.js → useBasicWidgetState.Cwd7-jJa.js} +1 -1
- streamlit/static/static/js/useOnInputChange.DvemQrOM.js +1 -0
- streamlit/static/static/js/{withFullScreenWrapper.Ov13692o.js → withFullScreenWrapper.CiQ10ByU.js} +1 -1
- streamlit/static/static/media/SourceCodeVF-Italic.ttf.Ba1oaZG1.woff2 +0 -0
- streamlit/static/static/media/SourceCodeVF-Upright.ttf.BjWn63N-.woff2 +0 -0
- streamlit/static/static/media/SourceSansVF-Italic.ttf.Bt9VkdQ3.woff2 +0 -0
- streamlit/static/static/media/SourceSansVF-Upright.ttf.BsWL4Kly.woff2 +0 -0
- streamlit/static/static/media/SourceSerifVariable-Italic.ttf.CVdzAtxO.woff2 +0 -0
- streamlit/static/static/media/SourceSerifVariable-Roman.ttf.mdpVL9bi.woff2 +0 -0
- streamlit/string_util.py +14 -19
- streamlit/temporary_directory.py +13 -4
- streamlit/testing/v1/app_test.py +15 -10
- streamlit/testing/v1/element_tree.py +157 -178
- streamlit/testing/v1/local_script_runner.py +11 -15
- streamlit/testing/v1/util.py +11 -4
- streamlit/type_util.py +8 -12
- streamlit/url_util.py +1 -1
- streamlit/user_info.py +6 -5
- streamlit/util.py +25 -1
- streamlit/vendor/pympler/asizeof.py +3 -2
- streamlit/watcher/event_based_path_watcher.py +15 -1
- streamlit/watcher/folder_black_list.py +2 -2
- streamlit/watcher/local_sources_watcher.py +64 -18
- streamlit/watcher/path_watcher.py +6 -10
- streamlit/watcher/polling_path_watcher.py +8 -7
- streamlit/watcher/util.py +7 -6
- streamlit/web/bootstrap.py +16 -14
- streamlit/web/cli.py +52 -45
- streamlit/web/server/__init__.py +7 -3
- streamlit/web/server/app_static_file_handler.py +1 -1
- streamlit/web/server/authlib_tornado_integration.py +9 -4
- streamlit/web/server/browser_websocket_handler.py +8 -2
- streamlit/web/server/component_request_handler.py +14 -10
- streamlit/web/server/media_file_handler.py +14 -7
- streamlit/web/server/oauth_authlib_routes.py +41 -9
- streamlit/web/server/oidc_mixin.py +35 -17
- streamlit/web/server/routes.py +32 -22
- streamlit/web/server/server.py +6 -18
- streamlit/web/server/server_util.py +19 -9
- streamlit/web/server/stats_request_handler.py +7 -5
- streamlit/web/server/upload_file_request_handler.py +22 -19
- streamlit/web/server/websocket_headers.py +1 -1
- {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/METADATA +4 -4
- streamlit-1.46.0.dist-info/RECORD +559 -0
- {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/WHEEL +1 -1
- streamlit/elements/lib/event_utils.py +0 -39
- streamlit/static/static/js/Toolbar.D9RUZv9G.js +0 -1
- streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
- streamlit/static/static/js/index.8jhZBWF2.js +0 -3
- streamlit/static/static/js/index.BCx3C6e_.js +0 -1
- streamlit/static/static/js/index.BRuTz_S4.js +0 -1
- streamlit/static/static/js/index.Bcru_ti-.js +0 -1
- streamlit/static/static/js/index.Bl1FMJRd.js +0 -1
- streamlit/static/static/js/index.C1z8KpLA.js +0 -779
- streamlit/static/static/js/index.C32I2PUe.js +0 -2
- streamlit/static/static/js/index.C5GnDRB7.js +0 -1
- streamlit/static/static/js/index.CG4qPaaW.js +0 -2
- streamlit/static/static/js/index.C_msmT1u.js +0 -1
- streamlit/static/static/js/index.CbeNTdd6.js +0 -1
- streamlit/static/static/js/index.CnGQVJcw.js +0 -12
- streamlit/static/static/js/index.CopVVq4l.js +0 -1
- streamlit/static/static/js/index.CtXupx4d.js +0 -197
- streamlit/static/static/js/index.DGmCchO7.js +0 -1
- streamlit/static/static/js/index.DH6zBk0e.js +0 -1
- streamlit/static/static/js/index.DHVlVWsm.js +0 -1
- streamlit/static/static/js/index.DRKIVBoi.js +0 -1
- streamlit/static/static/js/index.DUd-lFXx.js +0 -73
- streamlit/static/static/js/index.D_uRBA4B.js +0 -1
- streamlit/static/static/js/index.QHNfgPJd.js +0 -1
- streamlit/static/static/js/index.a-RJocYL.js +0 -1
- streamlit/static/static/js/index.cvz4B1gy.js +0 -1
- streamlit/static/static/js/index.t--hEgTQ.js +0 -6
- streamlit/static/static/js/useOnInputChange.z04u96A8.js +0 -1
- 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-1.45.1.dist-info/RECORD +0 -568
- {streamlit-1.45.1.data → streamlit-1.46.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/top_level.txt +0 -0
|
@@ -20,6 +20,11 @@ from textwrap import dedent
|
|
|
20
20
|
from typing import TYPE_CHECKING, cast
|
|
21
21
|
|
|
22
22
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
23
|
+
from streamlit.elements.lib.layout_utils import (
|
|
24
|
+
LayoutConfig,
|
|
25
|
+
Width,
|
|
26
|
+
validate_width,
|
|
27
|
+
)
|
|
23
28
|
from streamlit.elements.lib.policies import (
|
|
24
29
|
check_widget_policies,
|
|
25
30
|
maybe_raise_label_warnings,
|
|
@@ -53,7 +58,7 @@ class ColorPickerSerde:
|
|
|
53
58
|
def serialize(self, v: str) -> str:
|
|
54
59
|
return str(v)
|
|
55
60
|
|
|
56
|
-
def deserialize(self, ui_value: str | None
|
|
61
|
+
def deserialize(self, ui_value: str | None) -> str:
|
|
57
62
|
return str(ui_value if ui_value is not None else self.value)
|
|
58
63
|
|
|
59
64
|
|
|
@@ -71,6 +76,7 @@ class ColorPickerMixin:
|
|
|
71
76
|
*, # keyword-only arguments:
|
|
72
77
|
disabled: bool = False,
|
|
73
78
|
label_visibility: LabelVisibility = "visible",
|
|
79
|
+
width: Width = "content",
|
|
74
80
|
) -> str:
|
|
75
81
|
r"""Display a color picker widget.
|
|
76
82
|
|
|
@@ -133,9 +139,23 @@ class ColorPickerMixin:
|
|
|
133
139
|
label_visibility : "visible", "hidden", or "collapsed"
|
|
134
140
|
The visibility of the label. The default is ``"visible"``. If this
|
|
135
141
|
is ``"hidden"``, Streamlit displays an empty spacer instead of the
|
|
136
|
-
label, which can help keep the widget
|
|
142
|
+
label, which can help keep the widget aligned with other widgets.
|
|
137
143
|
If this is ``"collapsed"``, Streamlit displays no label or spacer.
|
|
138
144
|
|
|
145
|
+
width : "content", "stretch", or int
|
|
146
|
+
The width of the color picker widget. This can be one of the
|
|
147
|
+
following:
|
|
148
|
+
|
|
149
|
+
- ``"content"`` (default): The width of the widget matches the
|
|
150
|
+
width of its content, but doesn't exceed the width of the parent
|
|
151
|
+
container.
|
|
152
|
+
- ``"stretch"``: The width of the widget matches the width of the
|
|
153
|
+
parent container.
|
|
154
|
+
- An integer specifying the width in pixels: The widget has a
|
|
155
|
+
fixed width. If the specified width is greater than the width of
|
|
156
|
+
the parent container, the width of the widget matches the width
|
|
157
|
+
of the parent container.
|
|
158
|
+
|
|
139
159
|
Returns
|
|
140
160
|
-------
|
|
141
161
|
str
|
|
@@ -164,6 +184,7 @@ class ColorPickerMixin:
|
|
|
164
184
|
kwargs=kwargs,
|
|
165
185
|
disabled=disabled,
|
|
166
186
|
label_visibility=label_visibility,
|
|
187
|
+
width=width,
|
|
167
188
|
ctx=ctx,
|
|
168
189
|
)
|
|
169
190
|
|
|
@@ -179,6 +200,7 @@ class ColorPickerMixin:
|
|
|
179
200
|
*, # keyword-only arguments:
|
|
180
201
|
disabled: bool = False,
|
|
181
202
|
label_visibility: LabelVisibility = "visible",
|
|
203
|
+
width: Width = "content",
|
|
182
204
|
ctx: ScriptRunContext | None = None,
|
|
183
205
|
) -> str:
|
|
184
206
|
key = to_key(key)
|
|
@@ -191,13 +213,18 @@ class ColorPickerMixin:
|
|
|
191
213
|
)
|
|
192
214
|
maybe_raise_label_warnings(label, label_visibility)
|
|
193
215
|
|
|
216
|
+
validate_width(width, allow_content=True)
|
|
217
|
+
layout_config = LayoutConfig(width=width)
|
|
218
|
+
|
|
194
219
|
element_id = compute_and_register_element_id(
|
|
195
220
|
"color_picker",
|
|
196
221
|
user_key=key,
|
|
197
222
|
form_id=current_form_id(self.dg),
|
|
223
|
+
dg=self.dg,
|
|
198
224
|
label=label,
|
|
199
225
|
value=str(value),
|
|
200
226
|
help=help,
|
|
227
|
+
width=width,
|
|
201
228
|
)
|
|
202
229
|
|
|
203
230
|
# set value default
|
|
@@ -206,25 +233,19 @@ class ColorPickerMixin:
|
|
|
206
233
|
|
|
207
234
|
# make sure the value is a string
|
|
208
235
|
if not isinstance(value, str):
|
|
209
|
-
raise StreamlitAPIException(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
"""
|
|
214
|
-
% type(value).__name__
|
|
215
|
-
)
|
|
236
|
+
raise StreamlitAPIException(f"""
|
|
237
|
+
Color Picker Value has invalid type: {type(value).__name__}. Expects a hex string
|
|
238
|
+
like '#00FFAA' or '#000'.
|
|
239
|
+
""")
|
|
216
240
|
|
|
217
241
|
# validate the value and expects a hex string
|
|
218
242
|
match = re.match(r"^#(?:[0-9a-fA-F]{3}){1,2}$", value)
|
|
219
243
|
|
|
220
244
|
if not match:
|
|
221
|
-
raise StreamlitAPIException(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
"""
|
|
226
|
-
% value
|
|
227
|
-
)
|
|
245
|
+
raise StreamlitAPIException(f"""
|
|
246
|
+
'{value}' is not a valid hex code for colors. Valid ones are like
|
|
247
|
+
'#00FFAA' or '#000'.
|
|
248
|
+
""")
|
|
228
249
|
|
|
229
250
|
color_picker_proto = ColorPickerProto()
|
|
230
251
|
color_picker_proto.id = element_id
|
|
@@ -256,7 +277,9 @@ class ColorPickerMixin:
|
|
|
256
277
|
color_picker_proto.value = widget_state.value
|
|
257
278
|
color_picker_proto.set_value = True
|
|
258
279
|
|
|
259
|
-
self.dg._enqueue(
|
|
280
|
+
self.dg._enqueue(
|
|
281
|
+
"color_picker", color_picker_proto, layout_config=layout_config
|
|
282
|
+
)
|
|
260
283
|
return widget_state.value
|
|
261
284
|
|
|
262
285
|
@property
|
|
@@ -137,7 +137,7 @@ class EditingState(TypedDict, total=False):
|
|
|
137
137
|
class DataEditorSerde:
|
|
138
138
|
"""DataEditorSerde is used to serialize and deserialize the data editor state."""
|
|
139
139
|
|
|
140
|
-
def deserialize(self, ui_value: str | None
|
|
140
|
+
def deserialize(self, ui_value: str | None) -> EditingState:
|
|
141
141
|
data_editor_state: EditingState = (
|
|
142
142
|
{
|
|
143
143
|
"edited_rows": {},
|
|
@@ -270,8 +270,11 @@ def _apply_cell_edits(
|
|
|
270
270
|
# The edited cell is part of the index
|
|
271
271
|
# TODO(lukasmasuch): To support multi-index in the future:
|
|
272
272
|
# use a tuple of values here instead of a single value
|
|
273
|
-
df.index
|
|
274
|
-
|
|
273
|
+
old_idx_value = df.index[row_pos]
|
|
274
|
+
new_idx_value = _parse_value(value, dataframe_schema[INDEX_IDENTIFIER])
|
|
275
|
+
df.rename(
|
|
276
|
+
index={old_idx_value: new_idx_value},
|
|
277
|
+
inplace=True, # noqa: PD002
|
|
275
278
|
)
|
|
276
279
|
else:
|
|
277
280
|
col_pos = df.columns.get_loc(col_name)
|
|
@@ -280,6 +283,26 @@ def _apply_cell_edits(
|
|
|
280
283
|
)
|
|
281
284
|
|
|
282
285
|
|
|
286
|
+
def _parse_added_row(
|
|
287
|
+
df: pd.DataFrame,
|
|
288
|
+
added_row: dict[str, Any],
|
|
289
|
+
dataframe_schema: DataframeSchema,
|
|
290
|
+
) -> tuple[Any, list[Any]]:
|
|
291
|
+
"""Parse the added row into an optional index value and a list of row values."""
|
|
292
|
+
index_value = None
|
|
293
|
+
new_row: list[Any] = [None for _ in range(df.shape[1])]
|
|
294
|
+
for col_name, value in added_row.items():
|
|
295
|
+
if col_name == INDEX_IDENTIFIER:
|
|
296
|
+
# TODO(lukasmasuch): To support multi-index in the future:
|
|
297
|
+
# use a tuple of values here instead of a single value
|
|
298
|
+
index_value = _parse_value(value, dataframe_schema[INDEX_IDENTIFIER])
|
|
299
|
+
else:
|
|
300
|
+
col_pos = cast("int", df.columns.get_loc(col_name))
|
|
301
|
+
new_row[col_pos] = _parse_value(value, dataframe_schema[col_name])
|
|
302
|
+
|
|
303
|
+
return index_value, new_row
|
|
304
|
+
|
|
305
|
+
|
|
283
306
|
def _apply_row_additions(
|
|
284
307
|
df: pd.DataFrame,
|
|
285
308
|
added_rows: list[dict[str, Any]],
|
|
@@ -305,39 +328,54 @@ def _apply_row_additions(
|
|
|
305
328
|
|
|
306
329
|
import pandas as pd
|
|
307
330
|
|
|
308
|
-
|
|
309
|
-
#
|
|
310
|
-
#
|
|
311
|
-
|
|
312
|
-
|
|
331
|
+
index_type: Literal["range", "integer", "other"] = "other"
|
|
332
|
+
# This is only used if the dataframe has a range or integer index that can be
|
|
333
|
+
# auto incremented:
|
|
334
|
+
index_stop: int | None = None
|
|
335
|
+
index_step: int | None = None
|
|
336
|
+
|
|
313
337
|
if isinstance(df.index, pd.RangeIndex):
|
|
314
|
-
|
|
315
|
-
|
|
338
|
+
# Extract metadata from the range index:
|
|
339
|
+
index_type = "range"
|
|
340
|
+
index_stop = cast("int", df.index.stop)
|
|
341
|
+
index_step = cast("int", df.index.step)
|
|
342
|
+
elif isinstance(df.index, pd.Index) and pd.api.types.is_integer_dtype(
|
|
343
|
+
df.index.dtype
|
|
344
|
+
):
|
|
345
|
+
# Get highest integer value and increment it by 1 to get unique index value.
|
|
346
|
+
index_type = "integer"
|
|
347
|
+
index_stop = 0 if df.index.empty else df.index.max() + 1
|
|
348
|
+
index_step = 1
|
|
316
349
|
|
|
317
350
|
for added_row in added_rows:
|
|
318
|
-
index_value =
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
# Append the new row to the dataframe
|
|
330
|
-
if range_index_stop is not None:
|
|
331
|
-
df.loc[range_index_stop, :] = new_row
|
|
332
|
-
# Increment to the next range index value
|
|
333
|
-
range_index_stop += range_index_step
|
|
334
|
-
elif index_value is not None:
|
|
335
|
-
# TODO(lukasmasuch): we are only adding rows that have a non-None index
|
|
336
|
-
# value to prevent issues in the frontend component. Also, it just overwrites
|
|
337
|
-
# the row in case the index value already exists in the dataframe.
|
|
338
|
-
# In the future, it would be better to require users to provide unique
|
|
339
|
-
# non-None values for the index with some kind of visual indications.
|
|
351
|
+
index_value, new_row = _parse_added_row(df, added_row, dataframe_schema)
|
|
352
|
+
|
|
353
|
+
if index_value is not None and index_type != "range":
|
|
354
|
+
# Case 1: Non-range index with an explicitly provided index value
|
|
355
|
+
# Add row using the user-provided index value.
|
|
356
|
+
# This handles any type of index that cannot be auto incremented.
|
|
357
|
+
|
|
358
|
+
# Note: this just overwrites the row in case the index value
|
|
359
|
+
# already exists. In the future, it would be better to
|
|
360
|
+
# require users to provide unique non-None values for the index with
|
|
361
|
+
# some kind of visual indications.
|
|
340
362
|
df.loc[index_value, :] = new_row
|
|
363
|
+
continue
|
|
364
|
+
|
|
365
|
+
if index_stop is not None and index_step is not None:
|
|
366
|
+
# Case 2: Range or integer index that can be auto incremented.
|
|
367
|
+
# Add row using the next value in the sequence
|
|
368
|
+
df.loc[index_stop, :] = new_row
|
|
369
|
+
# Increment to the next range index value
|
|
370
|
+
index_stop += index_step
|
|
371
|
+
continue
|
|
372
|
+
|
|
373
|
+
# Row cannot be added -> skip it and log a warning.
|
|
374
|
+
_LOGGER.warning(
|
|
375
|
+
"Cannot automatically add row for the index "
|
|
376
|
+
"of type %s without an explicit index value. Row addition skipped.",
|
|
377
|
+
type(df.index).__name__,
|
|
378
|
+
)
|
|
341
379
|
|
|
342
380
|
|
|
343
381
|
def _apply_row_deletions(df: pd.DataFrame, deleted_rows: list[int]) -> None:
|
|
@@ -442,7 +480,7 @@ def _fix_column_headers(data_df: pd.DataFrame) -> None:
|
|
|
442
480
|
)
|
|
443
481
|
|
|
444
482
|
|
|
445
|
-
def _check_column_names(data_df: pd.DataFrame):
|
|
483
|
+
def _check_column_names(data_df: pd.DataFrame) -> None:
|
|
446
484
|
"""Check if the column names in the provided dataframe are valid.
|
|
447
485
|
|
|
448
486
|
It's not allowed to have duplicate column names or column names that are
|
|
@@ -476,7 +514,7 @@ def _check_type_compatibilities(
|
|
|
476
514
|
data_df: pd.DataFrame,
|
|
477
515
|
columns_config: ColumnConfigMapping,
|
|
478
516
|
dataframe_schema: DataframeSchema,
|
|
479
|
-
):
|
|
517
|
+
) -> None:
|
|
480
518
|
"""Check column type to data type compatibility.
|
|
481
519
|
|
|
482
520
|
Iterates the index and all columns of the dataframe to check if
|
|
@@ -631,7 +669,7 @@ class DataEditorMixin:
|
|
|
631
669
|
Desired height of the data editor expressed in pixels. If ``height``
|
|
632
670
|
is ``None`` (default), Streamlit sets the height to show at most
|
|
633
671
|
ten rows. Vertical scrolling within the data editor element is
|
|
634
|
-
enabled when the height does not
|
|
672
|
+
enabled when the height does not accommodate all rows.
|
|
635
673
|
|
|
636
674
|
use_container_width : bool
|
|
637
675
|
Whether to override ``width`` with the width of the parent
|
|
@@ -662,7 +700,7 @@ class DataEditorMixin:
|
|
|
662
700
|
- A string to set the display label of the column.
|
|
663
701
|
|
|
664
702
|
- One of the column types defined under ``st.column_config``, e.g.
|
|
665
|
-
``st.column_config.NumberColumn("Dollar values
|
|
703
|
+
``st.column_config.NumberColumn("Dollar values", format="$ %d")`` to show
|
|
666
704
|
a column as dollar amounts. See more info on the available column types
|
|
667
705
|
and config options `here <https://docs.streamlit.io/develop/api-reference/data/st.column_config>`_.
|
|
668
706
|
|
|
@@ -898,6 +936,7 @@ class DataEditorMixin:
|
|
|
898
936
|
"data_editor",
|
|
899
937
|
user_key=key,
|
|
900
938
|
form_id=current_form_id(self.dg),
|
|
939
|
+
dg=self.dg,
|
|
901
940
|
data=arrow_bytes,
|
|
902
941
|
width=width,
|
|
903
942
|
height=height,
|
|
@@ -914,7 +953,7 @@ class DataEditorMixin:
|
|
|
914
953
|
if use_container_width is None:
|
|
915
954
|
# If use_container_width was not explicitly set by the user, we set
|
|
916
955
|
# it to True if width was not set explicitly, and False otherwise.
|
|
917
|
-
use_container_width =
|
|
956
|
+
use_container_width = width is None
|
|
918
957
|
|
|
919
958
|
proto.use_container_width = use_container_width
|
|
920
959
|
|
|
@@ -26,6 +26,11 @@ from streamlit.elements.lib.file_uploader_utils import (
|
|
|
26
26
|
normalize_upload_file_type,
|
|
27
27
|
)
|
|
28
28
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
29
|
+
from streamlit.elements.lib.layout_utils import (
|
|
30
|
+
LayoutConfig,
|
|
31
|
+
WidthWithoutContent,
|
|
32
|
+
validate_width,
|
|
33
|
+
)
|
|
29
34
|
from streamlit.elements.lib.policies import (
|
|
30
35
|
check_widget_policies,
|
|
31
36
|
maybe_raise_label_warnings,
|
|
@@ -102,9 +107,7 @@ class FileUploaderSerde:
|
|
|
102
107
|
accept_multiple_files: bool
|
|
103
108
|
allowed_types: Sequence[str] | None = None
|
|
104
109
|
|
|
105
|
-
def deserialize(
|
|
106
|
-
self, ui_value: FileUploaderStateProto | None, widget_id: str
|
|
107
|
-
) -> SomeUploadedFiles:
|
|
110
|
+
def deserialize(self, ui_value: FileUploaderStateProto | None) -> SomeUploadedFiles:
|
|
108
111
|
upload_files = _get_upload_files(ui_value)
|
|
109
112
|
|
|
110
113
|
for file in upload_files:
|
|
@@ -127,7 +130,7 @@ class FileUploaderSerde:
|
|
|
127
130
|
|
|
128
131
|
if not files:
|
|
129
132
|
return state_proto
|
|
130
|
-
|
|
133
|
+
if not isinstance(files, list):
|
|
131
134
|
files = [files]
|
|
132
135
|
|
|
133
136
|
for f in files:
|
|
@@ -169,7 +172,8 @@ class FileUploaderMixin:
|
|
|
169
172
|
*,
|
|
170
173
|
disabled: bool = False,
|
|
171
174
|
label_visibility: LabelVisibility = "visible",
|
|
172
|
-
|
|
175
|
+
width: WidthWithoutContent = "stretch",
|
|
176
|
+
) -> list[UploadedFile]: ...
|
|
173
177
|
|
|
174
178
|
# 1. type is given as not a keyword-only argument
|
|
175
179
|
# 2. accept_multiple_files = False or omitted
|
|
@@ -187,6 +191,7 @@ class FileUploaderMixin:
|
|
|
187
191
|
*,
|
|
188
192
|
disabled: bool = False,
|
|
189
193
|
label_visibility: LabelVisibility = "visible",
|
|
194
|
+
width: WidthWithoutContent = "stretch",
|
|
190
195
|
) -> UploadedFile | None: ...
|
|
191
196
|
|
|
192
197
|
# The following 2 overloads represent the cases where
|
|
@@ -210,7 +215,8 @@ class FileUploaderMixin:
|
|
|
210
215
|
kwargs: WidgetKwargs | None = None,
|
|
211
216
|
disabled: bool = False,
|
|
212
217
|
label_visibility: LabelVisibility = "visible",
|
|
213
|
-
|
|
218
|
+
width: WidthWithoutContent = "stretch",
|
|
219
|
+
) -> list[UploadedFile]: ...
|
|
214
220
|
|
|
215
221
|
# 1. type is skipped or a keyword argument
|
|
216
222
|
# 2. accept_multiple_files = False or omitted
|
|
@@ -228,6 +234,7 @@ class FileUploaderMixin:
|
|
|
228
234
|
kwargs: WidgetKwargs | None = None,
|
|
229
235
|
disabled: bool = False,
|
|
230
236
|
label_visibility: LabelVisibility = "visible",
|
|
237
|
+
width: WidthWithoutContent = "stretch",
|
|
231
238
|
) -> UploadedFile | None: ...
|
|
232
239
|
|
|
233
240
|
@gather_metrics("file_uploader")
|
|
@@ -244,6 +251,7 @@ class FileUploaderMixin:
|
|
|
244
251
|
*, # keyword-only arguments:
|
|
245
252
|
disabled: bool = False,
|
|
246
253
|
label_visibility: LabelVisibility = "visible",
|
|
254
|
+
width: WidthWithoutContent = "stretch",
|
|
247
255
|
) -> UploadedFile | list[UploadedFile] | None:
|
|
248
256
|
r"""Display a file uploader widget.
|
|
249
257
|
By default, uploaded files are limited to 200 MB each. You can
|
|
@@ -325,9 +333,20 @@ class FileUploaderMixin:
|
|
|
325
333
|
label_visibility : "visible", "hidden", or "collapsed"
|
|
326
334
|
The visibility of the label. The default is ``"visible"``. If this
|
|
327
335
|
is ``"hidden"``, Streamlit displays an empty spacer instead of the
|
|
328
|
-
label, which can help keep the widget
|
|
336
|
+
label, which can help keep the widget aligned with other widgets.
|
|
329
337
|
If this is ``"collapsed"``, Streamlit displays no label or spacer.
|
|
330
338
|
|
|
339
|
+
width : "stretch" or int
|
|
340
|
+
The width of the file uploader widget. This can be one of the
|
|
341
|
+
following:
|
|
342
|
+
|
|
343
|
+
- ``"stretch"`` (default): The width of the widget matches the
|
|
344
|
+
width of the parent container.
|
|
345
|
+
- An integer specifying the width in pixels: The widget has a
|
|
346
|
+
fixed width. If the specified width is greater than the width of
|
|
347
|
+
the parent container, the width of the widget matches the width
|
|
348
|
+
of the parent container.
|
|
349
|
+
|
|
331
350
|
Returns
|
|
332
351
|
-------
|
|
333
352
|
None, UploadedFile, or list of UploadedFile
|
|
@@ -396,6 +415,7 @@ class FileUploaderMixin:
|
|
|
396
415
|
kwargs=kwargs,
|
|
397
416
|
disabled=disabled,
|
|
398
417
|
label_visibility=label_visibility,
|
|
418
|
+
width=width,
|
|
399
419
|
ctx=ctx,
|
|
400
420
|
)
|
|
401
421
|
|
|
@@ -413,6 +433,7 @@ class FileUploaderMixin:
|
|
|
413
433
|
label_visibility: LabelVisibility = "visible",
|
|
414
434
|
disabled: bool = False,
|
|
415
435
|
ctx: ScriptRunContext | None = None,
|
|
436
|
+
width: WidthWithoutContent = "stretch",
|
|
416
437
|
) -> UploadedFile | list[UploadedFile] | None:
|
|
417
438
|
key = to_key(key)
|
|
418
439
|
|
|
@@ -429,19 +450,22 @@ class FileUploaderMixin:
|
|
|
429
450
|
"file_uploader",
|
|
430
451
|
user_key=key,
|
|
431
452
|
form_id=current_form_id(self.dg),
|
|
453
|
+
dg=self.dg,
|
|
432
454
|
label=label,
|
|
433
455
|
type=type,
|
|
434
456
|
accept_multiple_files=accept_multiple_files,
|
|
435
457
|
help=help,
|
|
458
|
+
width=width,
|
|
436
459
|
)
|
|
437
460
|
|
|
438
|
-
if type
|
|
439
|
-
type = normalize_upload_file_type(type)
|
|
461
|
+
normalized_type = normalize_upload_file_type(type) if type else None
|
|
440
462
|
|
|
441
463
|
file_uploader_proto = FileUploaderProto()
|
|
442
464
|
file_uploader_proto.id = element_id
|
|
443
465
|
file_uploader_proto.label = label
|
|
444
|
-
file_uploader_proto.type[:] =
|
|
466
|
+
file_uploader_proto.type[:] = (
|
|
467
|
+
normalized_type if normalized_type is not None else []
|
|
468
|
+
)
|
|
445
469
|
file_uploader_proto.max_upload_size_mb = config.get_option(
|
|
446
470
|
"server.maxUploadSize"
|
|
447
471
|
)
|
|
@@ -455,7 +479,7 @@ class FileUploaderMixin:
|
|
|
455
479
|
if help is not None:
|
|
456
480
|
file_uploader_proto.help = dedent(help)
|
|
457
481
|
|
|
458
|
-
serde = FileUploaderSerde(accept_multiple_files, allowed_types=
|
|
482
|
+
serde = FileUploaderSerde(accept_multiple_files, allowed_types=normalized_type)
|
|
459
483
|
|
|
460
484
|
# FileUploader's widget value is a list of file IDs
|
|
461
485
|
# representing the current set of files that this uploader should
|
|
@@ -471,11 +495,16 @@ class FileUploaderMixin:
|
|
|
471
495
|
value_type="file_uploader_state_value",
|
|
472
496
|
)
|
|
473
497
|
|
|
474
|
-
|
|
498
|
+
validate_width(width)
|
|
499
|
+
layout_config = LayoutConfig(width=width)
|
|
500
|
+
|
|
501
|
+
self.dg._enqueue(
|
|
502
|
+
"file_uploader", file_uploader_proto, layout_config=layout_config
|
|
503
|
+
)
|
|
475
504
|
|
|
476
505
|
if isinstance(widget_state.value, DeletedFile):
|
|
477
506
|
return None
|
|
478
|
-
|
|
507
|
+
if isinstance(widget_state.value, list):
|
|
479
508
|
return [f for f in widget_state.value if not isinstance(f, DeletedFile)]
|
|
480
509
|
|
|
481
510
|
return widget_state.value
|
|
@@ -75,7 +75,7 @@ class MultiSelectSerde(Generic[T]):
|
|
|
75
75
|
formatted_options: list[str],
|
|
76
76
|
formatted_option_to_option_index: dict[str, int],
|
|
77
77
|
default_options_indices: list[int] | None = None,
|
|
78
|
-
):
|
|
78
|
+
) -> None:
|
|
79
79
|
"""Initialize the MultiSelectSerde.
|
|
80
80
|
|
|
81
81
|
We do not store an option_to_formatted_option mapping because the generic
|
|
@@ -110,17 +110,13 @@ class MultiSelectSerde(Generic[T]):
|
|
|
110
110
|
try:
|
|
111
111
|
option_index = self.options.index(v)
|
|
112
112
|
values.append(self.formatted_options[option_index])
|
|
113
|
-
except ValueError:
|
|
113
|
+
except ValueError: # noqa: PERF203
|
|
114
114
|
# at this point we know that v is a string, otherwise
|
|
115
115
|
# it would have been found in the options
|
|
116
116
|
values.append(cast("str", v))
|
|
117
117
|
return values
|
|
118
118
|
|
|
119
|
-
def deserialize(
|
|
120
|
-
self,
|
|
121
|
-
ui_value: list[str] | None,
|
|
122
|
-
widget_id: str = "",
|
|
123
|
-
) -> list[T | str] | list[T]:
|
|
119
|
+
def deserialize(self, ui_value: list[str] | None) -> list[T | str] | list[T]:
|
|
124
120
|
if ui_value is None:
|
|
125
121
|
return [self.options[i] for i in self.default_options_indices]
|
|
126
122
|
|
|
@@ -129,7 +125,7 @@ class MultiSelectSerde(Generic[T]):
|
|
|
129
125
|
try:
|
|
130
126
|
option_index = self.formatted_options.index(v)
|
|
131
127
|
values.append(self.options[option_index])
|
|
132
|
-
except ValueError:
|
|
128
|
+
except ValueError: # noqa: PERF203
|
|
133
129
|
values.append(v)
|
|
134
130
|
return values
|
|
135
131
|
|
|
@@ -144,7 +140,7 @@ def _get_default_count(default: Sequence[Any] | Any | None) -> int:
|
|
|
144
140
|
|
|
145
141
|
def _check_max_selections(
|
|
146
142
|
selections: Sequence[Any] | Any | None, max_selections: int | None
|
|
147
|
-
):
|
|
143
|
+
) -> None:
|
|
148
144
|
if max_selections is None:
|
|
149
145
|
return
|
|
150
146
|
|
|
@@ -320,7 +316,7 @@ class MultiSelectMixin:
|
|
|
320
316
|
label_visibility: "visible", "hidden", or "collapsed"
|
|
321
317
|
The visibility of the label. The default is ``"visible"``. If this
|
|
322
318
|
is ``"hidden"``, Streamlit displays an empty spacer instead of the
|
|
323
|
-
label, which can help keep the widget
|
|
319
|
+
label, which can help keep the widget aligned with other widgets.
|
|
324
320
|
If this is ``"collapsed"``, Streamlit displays no label or spacer.
|
|
325
321
|
|
|
326
322
|
accept_new_options: bool
|
|
@@ -453,6 +449,7 @@ class MultiSelectMixin:
|
|
|
453
449
|
widget_name,
|
|
454
450
|
user_key=key,
|
|
455
451
|
form_id=form_id,
|
|
452
|
+
dg=self.dg,
|
|
456
453
|
label=label,
|
|
457
454
|
options=formatted_options,
|
|
458
455
|
default=default_values,
|