streamlit-data-editor-plus 0.1.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 +292 -0
- streamlit/__main__.py +20 -0
- streamlit/auth_util.py +583 -0
- streamlit/cli_util.py +107 -0
- streamlit/column_config.py +60 -0
- streamlit/commands/__init__.py +13 -0
- streamlit/commands/echo.py +128 -0
- streamlit/commands/execution_control.py +318 -0
- streamlit/commands/logo.py +250 -0
- streamlit/commands/navigation.py +430 -0
- streamlit/commands/page_config.py +335 -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 +158 -0
- streamlit/components/v1/__init__.py +29 -0
- streamlit/components/v1/component_arrow.py +141 -0
- streamlit/components/v1/component_registry.py +147 -0
- streamlit/components/v1/components.py +38 -0
- streamlit/components/v1/custom_component.py +239 -0
- streamlit/components/v2/__init__.py +531 -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 +537 -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 +233 -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 +620 -0
- streamlit/components/v2/presentation.py +198 -0
- streamlit/components/v2/types.py +317 -0
- streamlit/config.py +2977 -0
- streamlit/config_option.py +319 -0
- streamlit/config_util.py +887 -0
- streamlit/connections/__init__.py +32 -0
- streamlit/connections/base_connection.py +215 -0
- streamlit/connections/snowflake_connection.py +765 -0
- streamlit/connections/snowpark_connection.py +213 -0
- streamlit/connections/sql_connection.py +427 -0
- streamlit/connections/util.py +97 -0
- streamlit/cursor.py +314 -0
- streamlit/dataframe_util.py +1434 -0
- streamlit/delta_generator.py +696 -0
- streamlit/delta_generator_singletons.py +243 -0
- streamlit/deprecation_util.py +253 -0
- streamlit/development.py +21 -0
- streamlit/elements/__init__.py +13 -0
- streamlit/elements/alert.py +341 -0
- streamlit/elements/arrow.py +1065 -0
- streamlit/elements/balloons.py +47 -0
- streamlit/elements/bokeh_chart.py +75 -0
- streamlit/elements/code.py +154 -0
- streamlit/elements/deck_gl_json_chart.py +627 -0
- streamlit/elements/dialog_decorator.py +320 -0
- streamlit/elements/empty.py +130 -0
- streamlit/elements/exception.py +370 -0
- streamlit/elements/form.py +481 -0
- streamlit/elements/graphviz_chart.py +226 -0
- streamlit/elements/heading.py +407 -0
- streamlit/elements/help.py +565 -0
- streamlit/elements/html.py +189 -0
- streamlit/elements/iframe.py +245 -0
- streamlit/elements/image.py +221 -0
- streamlit/elements/json.py +171 -0
- streamlit/elements/layouts.py +1534 -0
- streamlit/elements/lib/__init__.py +13 -0
- streamlit/elements/lib/built_in_chart_utils.py +1316 -0
- streamlit/elements/lib/color_util.py +272 -0
- streamlit/elements/lib/column_config_utils.py +555 -0
- streamlit/elements/lib/column_types.py +2699 -0
- streamlit/elements/lib/dialog.py +212 -0
- streamlit/elements/lib/dicttools.py +152 -0
- streamlit/elements/lib/file_uploader_utils.py +91 -0
- streamlit/elements/lib/form_utils.py +77 -0
- streamlit/elements/lib/image_utils.py +447 -0
- streamlit/elements/lib/js_number.py +105 -0
- streamlit/elements/lib/layout_utils.py +325 -0
- streamlit/elements/lib/mutable_expander_container.py +73 -0
- streamlit/elements/lib/mutable_popover_container.py +73 -0
- streamlit/elements/lib/mutable_status_container.py +194 -0
- streamlit/elements/lib/mutable_tab_container.py +73 -0
- streamlit/elements/lib/options_selector_utils.py +480 -0
- streamlit/elements/lib/pandas_styler_utils.py +302 -0
- streamlit/elements/lib/policies.py +198 -0
- streamlit/elements/lib/shortcut_utils.py +152 -0
- streamlit/elements/lib/streamlit_plotly_theme.py +206 -0
- streamlit/elements/lib/subtitle_utils.py +175 -0
- streamlit/elements/lib/utils.py +274 -0
- streamlit/elements/map.py +526 -0
- streamlit/elements/markdown.py +529 -0
- streamlit/elements/media.py +843 -0
- streamlit/elements/metric.py +529 -0
- streamlit/elements/pdf.py +190 -0
- streamlit/elements/plotly_chart.py +779 -0
- streamlit/elements/progress.py +172 -0
- streamlit/elements/pyplot.py +240 -0
- streamlit/elements/snow.py +47 -0
- streamlit/elements/space.py +121 -0
- streamlit/elements/spinner.py +152 -0
- streamlit/elements/table.py +240 -0
- streamlit/elements/text.py +113 -0
- streamlit/elements/toast.py +175 -0
- streamlit/elements/vega_charts.py +2510 -0
- streamlit/elements/widgets/__init__.py +13 -0
- streamlit/elements/widgets/audio_input.py +334 -0
- streamlit/elements/widgets/button.py +1559 -0
- streamlit/elements/widgets/button_group.py +1061 -0
- streamlit/elements/widgets/camera_input.py +281 -0
- streamlit/elements/widgets/chat.py +1028 -0
- streamlit/elements/widgets/checkbox.py +420 -0
- streamlit/elements/widgets/color_picker.py +329 -0
- streamlit/elements/widgets/data_editor.py +1168 -0
- streamlit/elements/widgets/data_editor_plus.py +902 -0
- streamlit/elements/widgets/feedback.py +322 -0
- streamlit/elements/widgets/file_uploader.py +592 -0
- streamlit/elements/widgets/multiselect.py +654 -0
- streamlit/elements/widgets/number_input.py +719 -0
- streamlit/elements/widgets/radio.py +551 -0
- streamlit/elements/widgets/select_slider.py +568 -0
- streamlit/elements/widgets/selectbox.py +680 -0
- streamlit/elements/widgets/slider.py +1093 -0
- streamlit/elements/widgets/text_widgets.py +779 -0
- streamlit/elements/widgets/time_widgets.py +1712 -0
- streamlit/elements/write.py +585 -0
- streamlit/emojis.py +34 -0
- streamlit/env_util.py +56 -0
- streamlit/error_util.py +112 -0
- streamlit/errors.py +680 -0
- streamlit/external/__init__.py +13 -0
- streamlit/external/langchain/__init__.py +23 -0
- streamlit/external/langchain/streamlit_callback_handler.py +410 -0
- streamlit/file_util.py +266 -0
- streamlit/git_util.py +200 -0
- streamlit/hello/__init__.py +13 -0
- streamlit/hello/__pycache__/__init__.cpython-312.pyc +0 -0
- streamlit/hello/__pycache__/streamlit_app.cpython-312.pyc +0 -0
- streamlit/hello/animation_demo.py +82 -0
- streamlit/hello/dataframe_demo.py +71 -0
- streamlit/hello/hello.py +46 -0
- streamlit/hello/mapping_demo.py +113 -0
- streamlit/hello/plotting_demo.py +62 -0
- streamlit/hello/streamlit_app.py +57 -0
- streamlit/hello/utils.py +30 -0
- streamlit/logger.py +129 -0
- streamlit/material_icon_names.py +25 -0
- streamlit/navigation/__init__.py +13 -0
- streamlit/navigation/page.py +365 -0
- streamlit/net_util.py +125 -0
- streamlit/path_security.py +98 -0
- streamlit/platform.py +31 -0
- streamlit/proto/Alert_pb2.py +28 -0
- streamlit/proto/Alert_pb2.pyi +100 -0
- streamlit/proto/AppPage_pb2.py +25 -0
- streamlit/proto/AppPage_pb2.pyi +75 -0
- streamlit/proto/ArrowData_pb2.py +27 -0
- streamlit/proto/ArrowData_pb2.pyi +103 -0
- streamlit/proto/ArrowNamedDataSet_pb2.py +26 -0
- streamlit/proto/ArrowNamedDataSet_pb2.pyi +65 -0
- streamlit/proto/AudioInput_pb2.py +26 -0
- streamlit/proto/AudioInput_pb2.pyi +72 -0
- streamlit/proto/Audio_pb2.py +26 -0
- streamlit/proto/Audio_pb2.pyi +75 -0
- streamlit/proto/AuthRedirect_pb2.py +25 -0
- streamlit/proto/AuthRedirect_pb2.pyi +48 -0
- streamlit/proto/AutoRerun_pb2.py +25 -0
- streamlit/proto/AutoRerun_pb2.pyi +52 -0
- streamlit/proto/BackMsg_pb2.py +29 -0
- streamlit/proto/BackMsg_pb2.pyi +132 -0
- streamlit/proto/Balloons_pb2.py +25 -0
- streamlit/proto/Balloons_pb2.pyi +48 -0
- streamlit/proto/BidiComponent_pb2.py +32 -0
- streamlit/proto/BidiComponent_pb2.pyi +176 -0
- streamlit/proto/Block_pb2.py +62 -0
- streamlit/proto/Block_pb2.pyi +518 -0
- streamlit/proto/ButtonGroup_pb2.py +32 -0
- streamlit/proto/ButtonGroup_pb2.pyi +157 -0
- streamlit/proto/ButtonLikeIconPosition_pb2.py +25 -0
- streamlit/proto/ButtonLikeIconPosition_pb2.pyi +47 -0
- streamlit/proto/Button_pb2.py +26 -0
- streamlit/proto/Button_pb2.pyi +82 -0
- streamlit/proto/CameraInput_pb2.py +26 -0
- streamlit/proto/CameraInput_pb2.pyi +66 -0
- streamlit/proto/ChatInput_pb2.py +27 -0
- streamlit/proto/ChatInput_pb2.pyi +113 -0
- streamlit/proto/Checkbox_pb2.py +28 -0
- streamlit/proto/Checkbox_pb2.pyi +99 -0
- streamlit/proto/ClientState_pb2.py +28 -0
- streamlit/proto/ClientState_pb2.pyi +137 -0
- streamlit/proto/Code_pb2.py +25 -0
- streamlit/proto/Code_pb2.pyi +59 -0
- streamlit/proto/ColorPicker_pb2.py +26 -0
- streamlit/proto/ColorPicker_pb2.pyi +82 -0
- streamlit/proto/Common_pb2.py +49 -0
- streamlit/proto/Common_pb2.pyi +325 -0
- streamlit/proto/Components_pb2.py +33 -0
- streamlit/proto/Components_pb2.pyi +196 -0
- streamlit/proto/Dataframe_pb2.py +30 -0
- streamlit/proto/Dataframe_pb2.pyi +172 -0
- streamlit/proto/DateInput_pb2.py +26 -0
- streamlit/proto/DateInput_pb2.pyi +91 -0
- streamlit/proto/DateTimeInput_pb2.py +26 -0
- streamlit/proto/DateTimeInput_pb2.pyi +94 -0
- streamlit/proto/DeckGlJsonChart_pb2.py +27 -0
- streamlit/proto/DeckGlJsonChart_pb2.pyi +91 -0
- streamlit/proto/Delta_pb2.py +29 -0
- streamlit/proto/Delta_pb2.pyi +82 -0
- streamlit/proto/DownloadButton_pb2.py +26 -0
- streamlit/proto/DownloadButton_pb2.pyi +92 -0
- streamlit/proto/Element_pb2.py +81 -0
- streamlit/proto/Element_pb2.pyi +348 -0
- streamlit/proto/Empty_pb2.py +25 -0
- streamlit/proto/Empty_pb2.pyi +42 -0
- streamlit/proto/Exception_pb2.py +26 -0
- streamlit/proto/Exception_pb2.pyi +88 -0
- streamlit/proto/Favicon_pb2.py +25 -0
- streamlit/proto/Favicon_pb2.pyi +47 -0
- streamlit/proto/Feedback_pb2.py +27 -0
- streamlit/proto/Feedback_pb2.pyi +93 -0
- streamlit/proto/FileUploader_pb2.py +26 -0
- streamlit/proto/FileUploader_pb2.pyi +90 -0
- streamlit/proto/ForwardMsg_pb2.py +48 -0
- streamlit/proto/ForwardMsg_pb2.pyi +296 -0
- streamlit/proto/GapSize_pb2.py +27 -0
- streamlit/proto/GapSize_pb2.pyi +82 -0
- streamlit/proto/GitInfo_pb2.py +27 -0
- streamlit/proto/GitInfo_pb2.pyi +84 -0
- streamlit/proto/GraphVizChart_pb2.py +25 -0
- streamlit/proto/GraphVizChart_pb2.pyi +56 -0
- streamlit/proto/Heading_pb2.py +25 -0
- streamlit/proto/Heading_pb2.pyi +63 -0
- streamlit/proto/HeightConfig_pb2.py +25 -0
- streamlit/proto/HeightConfig_pb2.pyi +61 -0
- streamlit/proto/Help_pb2.py +27 -0
- streamlit/proto/Help_pb2.pyi +104 -0
- streamlit/proto/Html_pb2.py +25 -0
- streamlit/proto/Html_pb2.pyi +52 -0
- streamlit/proto/IFrame_pb2.py +25 -0
- streamlit/proto/IFrame_pb2.pyi +68 -0
- streamlit/proto/Image_pb2.py +27 -0
- streamlit/proto/Image_pb2.pyi +73 -0
- streamlit/proto/Json_pb2.py +25 -0
- streamlit/proto/Json_pb2.pyi +63 -0
- streamlit/proto/LabelVisibility_pb2.py +27 -0
- streamlit/proto/LabelVisibility_pb2.pyi +69 -0
- streamlit/proto/LinkButton_pb2.py +26 -0
- streamlit/proto/LinkButton_pb2.pyi +76 -0
- streamlit/proto/Logo_pb2.py +27 -0
- streamlit/proto/Logo_pb2.pyi +82 -0
- streamlit/proto/Markdown_pb2.py +27 -0
- streamlit/proto/Markdown_pb2.pyi +83 -0
- streamlit/proto/Metric_pb2.py +32 -0
- streamlit/proto/Metric_pb2.pyi +145 -0
- streamlit/proto/MetricsEvent_pb2.py +28 -0
- streamlit/proto/MetricsEvent_pb2.pyi +224 -0
- streamlit/proto/MultiSelect_pb2.py +26 -0
- streamlit/proto/MultiSelect_pb2.pyi +108 -0
- streamlit/proto/Navigation_pb2.py +28 -0
- streamlit/proto/Navigation_pb2.pyi +89 -0
- streamlit/proto/NewSession_pb2.py +47 -0
- streamlit/proto/NewSession_pb2.pyi +753 -0
- streamlit/proto/NumberInput_pb2.py +28 -0
- streamlit/proto/NumberInput_pb2.pyi +138 -0
- streamlit/proto/PageConfig_pb2.py +33 -0
- streamlit/proto/PageConfig_pb2.pyi +179 -0
- streamlit/proto/PageInfo_pb2.py +25 -0
- streamlit/proto/PageInfo_pb2.pyi +50 -0
- streamlit/proto/PageLink_pb2.py +26 -0
- streamlit/proto/PageLink_pb2.pyi +80 -0
- streamlit/proto/PageNotFound_pb2.py +25 -0
- streamlit/proto/PageNotFound_pb2.pyi +49 -0
- streamlit/proto/PageProfile_pb2.py +29 -0
- streamlit/proto/PageProfile_pb2.pyi +146 -0
- streamlit/proto/ParentMessage_pb2.py +25 -0
- streamlit/proto/ParentMessage_pb2.pyi +53 -0
- streamlit/proto/PlotlyChart_pb2.py +27 -0
- streamlit/proto/PlotlyChart_pb2.pyi +96 -0
- streamlit/proto/Progress_pb2.py +25 -0
- streamlit/proto/Progress_pb2.pyi +50 -0
- streamlit/proto/Radio_pb2.py +26 -0
- streamlit/proto/Radio_pb2.pyi +104 -0
- streamlit/proto/RootContainer_pb2.py +25 -0
- streamlit/proto/RootContainer_pb2.pyi +56 -0
- streamlit/proto/Selectbox_pb2.py +26 -0
- streamlit/proto/Selectbox_pb2.pyi +107 -0
- streamlit/proto/SessionEvent_pb2.py +26 -0
- streamlit/proto/SessionEvent_pb2.pyi +72 -0
- streamlit/proto/SessionStatus_pb2.py +25 -0
- streamlit/proto/SessionStatus_pb2.pyi +64 -0
- streamlit/proto/Skeleton_pb2.py +27 -0
- streamlit/proto/Skeleton_pb2.pyi +75 -0
- streamlit/proto/Slider_pb2.py +30 -0
- streamlit/proto/Slider_pb2.pyi +161 -0
- streamlit/proto/Snow_pb2.py +25 -0
- streamlit/proto/Snow_pb2.pyi +48 -0
- streamlit/proto/Space_pb2.py +25 -0
- streamlit/proto/Space_pb2.pyi +48 -0
- streamlit/proto/Spinner_pb2.py +25 -0
- streamlit/proto/Spinner_pb2.pyi +56 -0
- streamlit/proto/Table_pb2.py +28 -0
- streamlit/proto/Table_pb2.pyi +83 -0
- streamlit/proto/TextAlignmentConfig_pb2.py +27 -0
- streamlit/proto/TextAlignmentConfig_pb2.pyi +69 -0
- streamlit/proto/TextArea_pb2.py +26 -0
- streamlit/proto/TextArea_pb2.pyi +97 -0
- streamlit/proto/TextInput_pb2.py +28 -0
- streamlit/proto/TextInput_pb2.pyi +124 -0
- streamlit/proto/Text_pb2.py +25 -0
- streamlit/proto/Text_pb2.pyi +53 -0
- streamlit/proto/TimeInput_pb2.py +26 -0
- streamlit/proto/TimeInput_pb2.pyi +86 -0
- streamlit/proto/Toast_pb2.py +25 -0
- streamlit/proto/Toast_pb2.pyi +64 -0
- streamlit/proto/Transient_pb2.py +26 -0
- streamlit/proto/Transient_pb2.pyi +53 -0
- streamlit/proto/VegaLiteChart_pb2.py +27 -0
- streamlit/proto/VegaLiteChart_pb2.pyi +92 -0
- streamlit/proto/Video_pb2.py +30 -0
- streamlit/proto/Video_pb2.pyi +129 -0
- streamlit/proto/WidgetStates_pb2.py +31 -0
- streamlit/proto/WidgetStates_pb2.pyi +157 -0
- streamlit/proto/WidthConfig_pb2.py +25 -0
- streamlit/proto/WidthConfig_pb2.pyi +61 -0
- streamlit/proto/__init__.py +15 -0
- streamlit/proto/openmetrics_data_model_pb2.py +58 -0
- streamlit/proto/openmetrics_data_model_pb2.pyi +558 -0
- streamlit/py.typed +0 -0
- streamlit/runtime/__init__.py +50 -0
- streamlit/runtime/app_session.py +1302 -0
- streamlit/runtime/caching/__init__.py +118 -0
- streamlit/runtime/caching/cache_data_api.py +775 -0
- streamlit/runtime/caching/cache_errors.py +143 -0
- streamlit/runtime/caching/cache_resource_api.py +756 -0
- streamlit/runtime/caching/cache_type.py +33 -0
- streamlit/runtime/caching/cache_utils.py +601 -0
- streamlit/runtime/caching/cached_message_replay.py +290 -0
- streamlit/runtime/caching/hashing.py +655 -0
- streamlit/runtime/caching/legacy_cache_api.py +170 -0
- streamlit/runtime/caching/storage/__init__.py +29 -0
- streamlit/runtime/caching/storage/cache_storage_protocol.py +236 -0
- streamlit/runtime/caching/storage/dummy_cache_storage.py +60 -0
- streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +159 -0
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +223 -0
- streamlit/runtime/caching/ttl_cleanup_cache.py +85 -0
- streamlit/runtime/connection_factory.py +498 -0
- streamlit/runtime/context.py +449 -0
- streamlit/runtime/context_util.py +49 -0
- streamlit/runtime/credentials.py +355 -0
- streamlit/runtime/download_data_util.py +53 -0
- streamlit/runtime/forward_msg_cache.py +101 -0
- streamlit/runtime/forward_msg_queue.py +263 -0
- streamlit/runtime/fragment.py +441 -0
- streamlit/runtime/media_file_manager.py +409 -0
- streamlit/runtime/media_file_storage.py +143 -0
- streamlit/runtime/memory_media_file_storage.py +201 -0
- streamlit/runtime/memory_session_storage.py +77 -0
- streamlit/runtime/memory_uploaded_file_manager.py +149 -0
- streamlit/runtime/metrics_util.py +612 -0
- streamlit/runtime/pages_manager.py +160 -0
- streamlit/runtime/runtime.py +775 -0
- streamlit/runtime/runtime_util.py +108 -0
- streamlit/runtime/script_data.py +46 -0
- streamlit/runtime/scriptrunner/__init__.py +38 -0
- streamlit/runtime/scriptrunner/exec_code.py +167 -0
- streamlit/runtime/scriptrunner/magic.py +277 -0
- streamlit/runtime/scriptrunner/magic_funcs.py +32 -0
- streamlit/runtime/scriptrunner/script_cache.py +89 -0
- streamlit/runtime/scriptrunner/script_runner.py +805 -0
- streamlit/runtime/scriptrunner_utils/__init__.py +19 -0
- streamlit/runtime/scriptrunner_utils/exceptions.py +44 -0
- streamlit/runtime/scriptrunner_utils/script_requests.py +311 -0
- streamlit/runtime/scriptrunner_utils/script_run_context.py +277 -0
- streamlit/runtime/secrets.py +533 -0
- streamlit/runtime/session_manager.py +430 -0
- streamlit/runtime/state/__init__.py +47 -0
- streamlit/runtime/state/common.py +256 -0
- streamlit/runtime/state/presentation.py +85 -0
- streamlit/runtime/state/query_params.py +767 -0
- streamlit/runtime/state/query_params_proxy.py +222 -0
- streamlit/runtime/state/safe_session_state.py +146 -0
- streamlit/runtime/state/session_state.py +1299 -0
- streamlit/runtime/state/session_state_proxy.py +153 -0
- streamlit/runtime/state/widgets.py +197 -0
- streamlit/runtime/stats.py +356 -0
- streamlit/runtime/theme_util.py +148 -0
- streamlit/runtime/uploaded_file_manager.py +152 -0
- streamlit/runtime/websocket_session_manager.py +301 -0
- streamlit/source_util.py +97 -0
- streamlit/starlette.py +34 -0
- streamlit/string_util.py +264 -0
- streamlit/temporary_directory.py +67 -0
- streamlit/testing/__init__.py +13 -0
- streamlit/testing/v1/__init__.py +17 -0
- streamlit/testing/v1/app_test.py +1089 -0
- streamlit/testing/v1/element_tree.py +2272 -0
- streamlit/testing/v1/local_script_runner.py +176 -0
- streamlit/testing/v1/util.py +61 -0
- streamlit/time_util.py +73 -0
- streamlit/type_util.py +480 -0
- streamlit/url_util.py +120 -0
- streamlit/user_info.py +698 -0
- streamlit/util.py +108 -0
- streamlit/vendor/__init__.py +0 -0
- streamlit/vendor/pympler/__init__.py +0 -0
- streamlit/vendor/pympler/asizeof.py +2870 -0
- streamlit/version.py +18 -0
- streamlit/watcher/__init__.py +28 -0
- streamlit/watcher/event_based_path_watcher.py +500 -0
- streamlit/watcher/folder_black_list.py +82 -0
- streamlit/watcher/local_sources_watcher.py +297 -0
- streamlit/watcher/path_watcher.py +244 -0
- streamlit/watcher/polling_path_watcher.py +138 -0
- streamlit/watcher/util.py +223 -0
- streamlit/web/__init__.py +13 -0
- streamlit/web/bootstrap.py +463 -0
- streamlit/web/cache_storage_manager_config.py +38 -0
- streamlit/web/cli.py +465 -0
- streamlit/web/server/__init__.py +30 -0
- streamlit/web/server/app_discovery.py +422 -0
- streamlit/web/server/app_static_file_handler.py +102 -0
- streamlit/web/server/authlib_tornado_integration.py +125 -0
- streamlit/web/server/bidi_component_request_handler.py +193 -0
- streamlit/web/server/browser_websocket_handler.py +341 -0
- streamlit/web/server/component_file_utils.py +105 -0
- streamlit/web/server/component_request_handler.py +107 -0
- streamlit/web/server/media_file_handler.py +148 -0
- streamlit/web/server/oauth_authlib_routes.py +314 -0
- streamlit/web/server/oidc_mixin.py +138 -0
- streamlit/web/server/routes.py +257 -0
- streamlit/web/server/server.py +555 -0
- streamlit/web/server/server_util.py +235 -0
- streamlit/web/server/starlette/__init__.py +23 -0
- streamlit/web/server/starlette/starlette_app.py +541 -0
- streamlit/web/server/starlette/starlette_app_utils.py +306 -0
- streamlit/web/server/starlette/starlette_auth_routes.py +584 -0
- streamlit/web/server/starlette/starlette_gzip_middleware.py +121 -0
- streamlit/web/server/starlette/starlette_path_security_middleware.py +97 -0
- streamlit/web/server/starlette/starlette_routes.py +884 -0
- streamlit/web/server/starlette/starlette_server.py +496 -0
- streamlit/web/server/starlette/starlette_server_config.py +55 -0
- streamlit/web/server/starlette/starlette_static_routes.py +181 -0
- streamlit/web/server/starlette/starlette_websocket.py +560 -0
- streamlit/web/server/stats_request_handler.py +116 -0
- streamlit/web/server/upload_file_request_handler.py +158 -0
- streamlit/web/server/websocket_headers.py +56 -0
- streamlit_data_editor_plus-0.1.0.dist-info/METADATA +76 -0
- streamlit_data_editor_plus-0.1.0.dist-info/RECORD +456 -0
- streamlit_data_editor_plus-0.1.0.dist-info/WHEEL +5 -0
- streamlit_data_editor_plus-0.1.0.dist-info/entry_points.txt +2 -0
- streamlit_data_editor_plus-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
|
|
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 collections import defaultdict
|
|
18
|
+
from collections.abc import Mapping
|
|
19
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
20
|
+
|
|
21
|
+
from streamlit import dataframe_util
|
|
22
|
+
from streamlit.errors import StreamlitAPIException
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from pandas import DataFrame
|
|
26
|
+
from pandas.io.formats.style import Styler
|
|
27
|
+
|
|
28
|
+
from streamlit.proto.ArrowData_pb2 import ArrowData as ArrowDataProto
|
|
29
|
+
|
|
30
|
+
from enum import Enum
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def marshall_styler(proto: ArrowDataProto, styler: Styler, default_uuid: str) -> None:
|
|
34
|
+
"""Marshall pandas.Styler into an ArrowData proto.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
proto : proto.ArrowData
|
|
39
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
40
|
+
|
|
41
|
+
styler : pandas.Styler
|
|
42
|
+
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
43
|
+
|
|
44
|
+
default_uuid : str
|
|
45
|
+
If pandas.Styler uuid is not provided, this value will be used.
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
import pandas as pd
|
|
49
|
+
|
|
50
|
+
styler_data_df: pd.DataFrame = styler.data # type: ignore[attr-defined]
|
|
51
|
+
if styler_data_df.size > int(pd.options.styler.render.max_elements):
|
|
52
|
+
raise StreamlitAPIException(
|
|
53
|
+
f"The dataframe has `{styler_data_df.size}` cells, but the maximum number "
|
|
54
|
+
"of cells allowed to be rendered by Pandas Styler is configured to "
|
|
55
|
+
f"`{pd.options.styler.render.max_elements}`. To allow more cells to be "
|
|
56
|
+
'styled, you can change the `"styler.render.max_elements"` config. For example: '
|
|
57
|
+
f'`pd.set_option("styler.render.max_elements", {styler_data_df.size})`'
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# pandas.Styler uuid should be set before _compute is called.
|
|
61
|
+
_marshall_uuid(proto, styler, default_uuid)
|
|
62
|
+
|
|
63
|
+
# We're using protected members of pandas.Styler to get styles,
|
|
64
|
+
# which is not ideal and could break if the interface changes.
|
|
65
|
+
styler._compute() # type: ignore
|
|
66
|
+
|
|
67
|
+
pandas_styles = styler._translate(False, False) # type: ignore
|
|
68
|
+
|
|
69
|
+
_marshall_caption(proto, styler)
|
|
70
|
+
_marshall_styles(proto, styler, pandas_styles)
|
|
71
|
+
_marshall_display_values(proto, styler_data_df, pandas_styles)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _marshall_uuid(proto: ArrowDataProto, styler: Styler, default_uuid: str) -> None:
|
|
75
|
+
"""Marshall pandas.Styler uuid into an ArrowData proto.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
proto : proto.ArrowData
|
|
80
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
81
|
+
|
|
82
|
+
styler : pandas.Styler
|
|
83
|
+
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
84
|
+
|
|
85
|
+
default_uuid : str
|
|
86
|
+
If pandas.Styler uuid is not provided, this value will be used.
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
if styler.uuid is None: # type: ignore[attr-defined]
|
|
90
|
+
styler.set_uuid(default_uuid)
|
|
91
|
+
|
|
92
|
+
proto.styler.uuid = str(styler.uuid) # type: ignore[attr-defined]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _marshall_caption(proto: ArrowDataProto, styler: Styler) -> None:
|
|
96
|
+
"""Marshall pandas.Styler caption into an ArrowData proto.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
proto : proto.ArrowData
|
|
101
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
102
|
+
|
|
103
|
+
styler : pandas.Styler
|
|
104
|
+
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
if styler.caption is not None: # type: ignore[attr-defined]
|
|
108
|
+
proto.styler.caption = styler.caption # type: ignore[attr-defined]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _marshall_styles(
|
|
112
|
+
proto: ArrowDataProto, styler: Styler, styles: Mapping[str, Any]
|
|
113
|
+
) -> None:
|
|
114
|
+
"""Marshall pandas.Styler styles into an ArrowData proto.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
proto : proto.ArrowData
|
|
119
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
120
|
+
|
|
121
|
+
styler : pandas.Styler
|
|
122
|
+
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
123
|
+
|
|
124
|
+
styles : dict
|
|
125
|
+
pandas.Styler translated styles.
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
css_rules = []
|
|
129
|
+
|
|
130
|
+
if "table_styles" in styles:
|
|
131
|
+
table_styles = styles["table_styles"]
|
|
132
|
+
table_styles = _trim_pandas_styles(table_styles)
|
|
133
|
+
for style in table_styles:
|
|
134
|
+
# styles in "table_styles" have a space
|
|
135
|
+
# between the uuid and selector.
|
|
136
|
+
rule = _pandas_style_to_css(
|
|
137
|
+
"table_styles",
|
|
138
|
+
style,
|
|
139
|
+
styler.uuid, # type: ignore[attr-defined]
|
|
140
|
+
separator=" ",
|
|
141
|
+
)
|
|
142
|
+
css_rules.append(rule)
|
|
143
|
+
|
|
144
|
+
if "cellstyle" in styles:
|
|
145
|
+
cellstyle = styles["cellstyle"]
|
|
146
|
+
cellstyle = _trim_pandas_styles(cellstyle)
|
|
147
|
+
for style in cellstyle:
|
|
148
|
+
rule = _pandas_style_to_css(
|
|
149
|
+
"cell_style",
|
|
150
|
+
style,
|
|
151
|
+
styler.uuid, # type: ignore[attr-defined]
|
|
152
|
+
separator="_",
|
|
153
|
+
)
|
|
154
|
+
css_rules.append(rule)
|
|
155
|
+
|
|
156
|
+
if len(css_rules) > 0:
|
|
157
|
+
proto.styler.styles = "\n".join(css_rules)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
M = TypeVar("M", bound=Mapping[str, Any])
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _trim_pandas_styles(styles: list[M]) -> list[M]:
|
|
164
|
+
"""Filter out empty styles.
|
|
165
|
+
|
|
166
|
+
Every cell will have a class, but the list of props
|
|
167
|
+
may just be [['', '']].
|
|
168
|
+
|
|
169
|
+
Parameters
|
|
170
|
+
----------
|
|
171
|
+
styles : list
|
|
172
|
+
pandas.Styler translated styles.
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
return [x for x in styles if any(any(y) for y in x["props"])]
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _pandas_style_to_css(
|
|
179
|
+
style_type: str,
|
|
180
|
+
style: Mapping[str, Any],
|
|
181
|
+
uuid: str,
|
|
182
|
+
separator: str = "_",
|
|
183
|
+
) -> str:
|
|
184
|
+
"""Convert pandas.Styler translated style to CSS.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
style_type : str
|
|
189
|
+
Either "table_styles" or "cell_style".
|
|
190
|
+
|
|
191
|
+
style : dict
|
|
192
|
+
pandas.Styler translated style.
|
|
193
|
+
|
|
194
|
+
uuid : str
|
|
195
|
+
pandas.Styler uuid.
|
|
196
|
+
|
|
197
|
+
separator : str
|
|
198
|
+
A string separator used between table and cell selectors.
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
declarations = []
|
|
202
|
+
for css_property, css_value in style["props"]:
|
|
203
|
+
declaration = str(css_property).strip() + ": " + str(css_value).strip()
|
|
204
|
+
declarations.append(declaration)
|
|
205
|
+
|
|
206
|
+
table_selector = f"#T_{uuid}"
|
|
207
|
+
|
|
208
|
+
# In pandas >= 1.1.0
|
|
209
|
+
# translated_style["cellstyle"] has the following shape:
|
|
210
|
+
# > [
|
|
211
|
+
# > {
|
|
212
|
+
# > "props": [("color", " black"), ("background-color", "orange"), ("", "")],
|
|
213
|
+
# > "selectors": ["row0_col0"]
|
|
214
|
+
# > }
|
|
215
|
+
# > ...
|
|
216
|
+
# > ]
|
|
217
|
+
cell_selectors = (
|
|
218
|
+
[style["selector"]] if style_type == "table_styles" else style["selectors"]
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
selectors = [
|
|
222
|
+
table_selector + separator + cell_selector for cell_selector in cell_selectors
|
|
223
|
+
]
|
|
224
|
+
selector = ", ".join(selectors)
|
|
225
|
+
|
|
226
|
+
declaration_block = "; ".join(declarations)
|
|
227
|
+
return selector + " { " + declaration_block + " }"
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _marshall_display_values(
|
|
231
|
+
proto: ArrowDataProto, df: DataFrame, styles: Mapping[str, Any]
|
|
232
|
+
) -> None:
|
|
233
|
+
"""Marshall pandas.Styler display values into an ArrowData proto.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
proto : proto.ArrowData
|
|
238
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
239
|
+
|
|
240
|
+
df : pandas.DataFrame
|
|
241
|
+
A dataframe with original values.
|
|
242
|
+
|
|
243
|
+
styles : dict
|
|
244
|
+
pandas.Styler translated styles.
|
|
245
|
+
|
|
246
|
+
"""
|
|
247
|
+
new_df = _use_display_values(df, styles)
|
|
248
|
+
proto.styler.display_values = dataframe_util.convert_pandas_df_to_arrow_bytes(
|
|
249
|
+
new_df
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _use_display_values(df: DataFrame, styles: Mapping[str, Any]) -> DataFrame:
|
|
254
|
+
"""Create a new pandas.DataFrame where display values are used instead of original ones.
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
df : pandas.DataFrame
|
|
259
|
+
A dataframe with original values.
|
|
260
|
+
|
|
261
|
+
styles : dict
|
|
262
|
+
pandas.Styler translated styles.
|
|
263
|
+
|
|
264
|
+
"""
|
|
265
|
+
import re
|
|
266
|
+
|
|
267
|
+
# If values in a column are not of the same type, Arrow
|
|
268
|
+
# serialization would fail. Thus, we need to cast all values
|
|
269
|
+
# of the dataframe to strings before assigning them display values.
|
|
270
|
+
|
|
271
|
+
new_df = df.astype(str)
|
|
272
|
+
cell_selector_regex = re.compile(r"row(\d+)_col(\d+)")
|
|
273
|
+
# Outer key = column index; inner key = row index -> target string value
|
|
274
|
+
updates_by_col: defaultdict[int, dict[int, str]] = defaultdict(dict)
|
|
275
|
+
for row in styles.get("body", []):
|
|
276
|
+
for cell in row:
|
|
277
|
+
cell_id = cell.get("id")
|
|
278
|
+
if not cell_id:
|
|
279
|
+
continue
|
|
280
|
+
match = cell_selector_regex.match(cell_id)
|
|
281
|
+
if not match:
|
|
282
|
+
continue
|
|
283
|
+
row_idx, col_idx = map(int, match.groups())
|
|
284
|
+
display_value = cell.get("display_value")
|
|
285
|
+
|
|
286
|
+
str_value = (
|
|
287
|
+
str(display_value.value)
|
|
288
|
+
# Check if the display value is an Enum type. Enum values need to be
|
|
289
|
+
# converted to their `.value` attribute to ensure proper serialization
|
|
290
|
+
# and display logic.
|
|
291
|
+
if isinstance(display_value, Enum)
|
|
292
|
+
else str(display_value)
|
|
293
|
+
)
|
|
294
|
+
updates_by_col[col_idx][row_idx] = str_value
|
|
295
|
+
|
|
296
|
+
for col_idx, values_by_row in updates_by_col.items():
|
|
297
|
+
row_indices = list(values_by_row.keys())
|
|
298
|
+
values = list(values_by_row.values())
|
|
299
|
+
# Batch-assign updates for this column using iloc for performance.
|
|
300
|
+
new_df.iloc[row_indices, col_idx] = values
|
|
301
|
+
|
|
302
|
+
return new_df # type: ignore[no-any-return, unused-ignore]
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
|
|
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, Final
|
|
18
|
+
|
|
19
|
+
from streamlit import config, errors, logger, runtime
|
|
20
|
+
from streamlit.elements.lib.form_utils import is_in_form
|
|
21
|
+
from streamlit.errors import (
|
|
22
|
+
StreamlitAPIWarning,
|
|
23
|
+
StreamlitFragmentWidgetsNotAllowedOutsideError,
|
|
24
|
+
StreamlitInvalidFormCallbackError,
|
|
25
|
+
StreamlitValueAssignmentNotAllowedError,
|
|
26
|
+
)
|
|
27
|
+
from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
|
28
|
+
get_script_run_ctx,
|
|
29
|
+
in_cached_function,
|
|
30
|
+
)
|
|
31
|
+
from streamlit.runtime.state import WidgetCallback, get_session_state
|
|
32
|
+
from streamlit.runtime.state.common import require_valid_user_key
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from collections.abc import Sequence
|
|
36
|
+
|
|
37
|
+
from streamlit.delta_generator import DeltaGenerator
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
_LOGGER: Final = logger.get_logger(__name__)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def check_callback_rules(dg: DeltaGenerator, on_change: WidgetCallback | None) -> None:
|
|
44
|
+
"""Ensures that widgets other than `st.form_submit_button` within a form don't have
|
|
45
|
+
an on_change callback set.
|
|
46
|
+
|
|
47
|
+
Raises
|
|
48
|
+
------
|
|
49
|
+
StreamlitInvalidFormCallbackError:
|
|
50
|
+
Raised when the described rule is violated.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
if runtime.exists() and is_in_form(dg) and on_change is not None:
|
|
54
|
+
raise StreamlitInvalidFormCallbackError()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_shown_default_value_warning: bool = False
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def check_session_state_rules(
|
|
61
|
+
default_value: Any, key: str | None, writes_allowed: bool = True
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Ensures that no values are set for widgets with the given key when writing
|
|
64
|
+
is not allowed.
|
|
65
|
+
|
|
66
|
+
Additionally, if `global.disableWidgetStateDuplicationWarning` is False a warning is
|
|
67
|
+
shown when a widget has a default value but its value is also set via session state.
|
|
68
|
+
|
|
69
|
+
Raises
|
|
70
|
+
------
|
|
71
|
+
StreamlitAPIException:
|
|
72
|
+
Raised when the described rule is violated.
|
|
73
|
+
"""
|
|
74
|
+
global _shown_default_value_warning # noqa: PLW0603
|
|
75
|
+
|
|
76
|
+
if key is None or not runtime.exists():
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
session_state = get_session_state()
|
|
80
|
+
if not session_state.is_new_state_value(key):
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
if not writes_allowed:
|
|
84
|
+
raise StreamlitValueAssignmentNotAllowedError(key=key)
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
default_value is not None
|
|
88
|
+
and not _shown_default_value_warning
|
|
89
|
+
and not config.get_option("global.disableWidgetStateDuplicationWarning")
|
|
90
|
+
):
|
|
91
|
+
from streamlit import warning
|
|
92
|
+
|
|
93
|
+
warning(
|
|
94
|
+
f'The widget with key "{key}" was created with a default value but'
|
|
95
|
+
" also had its value set via the Session State API."
|
|
96
|
+
)
|
|
97
|
+
_shown_default_value_warning = True
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class CachedWidgetWarning(StreamlitAPIWarning):
|
|
101
|
+
def __init__(self) -> None:
|
|
102
|
+
super().__init__(
|
|
103
|
+
"""
|
|
104
|
+
Your script uses a widget command in a cached function
|
|
105
|
+
(function decorated with `@st.cache_data` or `@st.cache_resource`).
|
|
106
|
+
This code will only be called when we detect a cache "miss",
|
|
107
|
+
which can lead to unexpected results.
|
|
108
|
+
|
|
109
|
+
To fix this, move all widget commands outside the cached function.
|
|
110
|
+
"""
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def check_cache_replay_rules() -> None:
|
|
115
|
+
"""Check if a widget is allowed to be used in the current context.
|
|
116
|
+
More specifically, this checks if the current context is inside a
|
|
117
|
+
cached function that disallows widget usage. If so, it raises a warning.
|
|
118
|
+
|
|
119
|
+
If there are other similar checks in the future, we could extend this
|
|
120
|
+
function to check for those as well. And rename it to check_widget_usage_rules.
|
|
121
|
+
"""
|
|
122
|
+
if in_cached_function.get():
|
|
123
|
+
from streamlit import exception
|
|
124
|
+
|
|
125
|
+
# We use an exception here to show a proper stack trace
|
|
126
|
+
# that indicates to the user where the issue is.
|
|
127
|
+
exception(CachedWidgetWarning())
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def check_fragment_path_policy(dg: DeltaGenerator) -> None:
|
|
131
|
+
"""Ensures that the current widget is not written outside of the
|
|
132
|
+
fragment's delta path.
|
|
133
|
+
|
|
134
|
+
Should be called by ever element that acts as a widget.
|
|
135
|
+
We don't allow writing widgets from within a widget to the outside path
|
|
136
|
+
because it can lead to unexpected behavior. For elements, this is okay
|
|
137
|
+
because they do not trigger a re-run.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
ctx = get_script_run_ctx()
|
|
141
|
+
# Check is only relevant for fragments
|
|
142
|
+
if ctx is None or ctx.current_fragment_id is None:
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
current_fragment_delta_path = ctx.current_fragment_delta_path
|
|
146
|
+
current_cursor = dg._active_dg._cursor
|
|
147
|
+
if current_cursor is None:
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
current_cursor_delta_path = current_cursor.delta_path
|
|
151
|
+
|
|
152
|
+
# the elements delta path cannot be smaller than the fragment's delta path if it is
|
|
153
|
+
# inside of the fragment
|
|
154
|
+
if len(current_cursor_delta_path) < len(current_fragment_delta_path):
|
|
155
|
+
raise StreamlitFragmentWidgetsNotAllowedOutsideError()
|
|
156
|
+
|
|
157
|
+
# all path indices of the fragment-path must occur in the inner-elements delta path,
|
|
158
|
+
# otherwise it is outside of the fragment container
|
|
159
|
+
for index, path_index in enumerate(current_fragment_delta_path):
|
|
160
|
+
if current_cursor_delta_path[index] != path_index:
|
|
161
|
+
raise StreamlitFragmentWidgetsNotAllowedOutsideError()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def check_widget_policies(
|
|
165
|
+
dg: DeltaGenerator,
|
|
166
|
+
key: str | None,
|
|
167
|
+
on_change: WidgetCallback | None = None,
|
|
168
|
+
*,
|
|
169
|
+
default_value: Sequence[Any] | Any | None = None,
|
|
170
|
+
writes_allowed: bool = True,
|
|
171
|
+
enable_check_callback_rules: bool = True,
|
|
172
|
+
) -> None:
|
|
173
|
+
"""Check all widget policies for the given DeltaGenerator."""
|
|
174
|
+
check_fragment_path_policy(dg)
|
|
175
|
+
check_cache_replay_rules()
|
|
176
|
+
if enable_check_callback_rules:
|
|
177
|
+
check_callback_rules(dg, on_change)
|
|
178
|
+
if key is not None:
|
|
179
|
+
require_valid_user_key(key)
|
|
180
|
+
check_session_state_rules(
|
|
181
|
+
default_value=default_value, key=key, writes_allowed=writes_allowed
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def maybe_raise_label_warnings(label: str | None, label_visibility: str | None) -> None:
|
|
186
|
+
if not label:
|
|
187
|
+
_LOGGER.warning(
|
|
188
|
+
"`label` got an empty value. This is discouraged for accessibility "
|
|
189
|
+
"reasons and may be disallowed in the future by raising an exception. "
|
|
190
|
+
"Please provide a non-empty label and hide it with label_visibility "
|
|
191
|
+
"if needed.",
|
|
192
|
+
stack_info=True,
|
|
193
|
+
)
|
|
194
|
+
if label_visibility not in {"visible", "hidden", "collapsed"}:
|
|
195
|
+
raise errors.StreamlitAPIException(
|
|
196
|
+
f"Unsupported label_visibility option '{label_visibility}'. "
|
|
197
|
+
f"Valid values are 'visible', 'hidden' or 'collapsed'."
|
|
198
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
|
|
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
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import (
|
|
19
|
+
Final,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from streamlit.errors import (
|
|
23
|
+
StreamlitAPIException,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
_MODIFIER_ALIASES: Final[dict[str, str]] = {
|
|
27
|
+
"ctrl": "ctrl",
|
|
28
|
+
"control": "ctrl",
|
|
29
|
+
"cmd": "cmd",
|
|
30
|
+
"command": "cmd",
|
|
31
|
+
"meta": "cmd",
|
|
32
|
+
"alt": "alt",
|
|
33
|
+
"option": "alt",
|
|
34
|
+
"shift": "shift",
|
|
35
|
+
"mod": "ctrl",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_MODIFIER_ORDER: Final[tuple[str, ...]] = ("ctrl", "cmd", "alt", "shift")
|
|
39
|
+
|
|
40
|
+
_KEY_ALIASES: Final[dict[str, str]] = {
|
|
41
|
+
"enter": "enter",
|
|
42
|
+
"return": "enter",
|
|
43
|
+
"space": "space",
|
|
44
|
+
"spacebar": "space",
|
|
45
|
+
"tab": "tab",
|
|
46
|
+
"escape": "escape",
|
|
47
|
+
"esc": "escape",
|
|
48
|
+
"backspace": "backspace",
|
|
49
|
+
"delete": "delete",
|
|
50
|
+
"del": "delete",
|
|
51
|
+
"home": "home",
|
|
52
|
+
"end": "end",
|
|
53
|
+
"pageup": "pageup",
|
|
54
|
+
"pagedown": "pagedown",
|
|
55
|
+
"left": "left",
|
|
56
|
+
"arrowleft": "left",
|
|
57
|
+
"right": "right",
|
|
58
|
+
"arrowright": "right",
|
|
59
|
+
"up": "up",
|
|
60
|
+
"arrowup": "up",
|
|
61
|
+
"down": "down",
|
|
62
|
+
"arrowdown": "down",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
_RESERVED_KEYS: Final[set[str]] = {"c", "r"}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _normalize_key_token(lower_token: str) -> str:
|
|
69
|
+
"""Normalize a key token to a format that can be used on the client side."""
|
|
70
|
+
|
|
71
|
+
if lower_token in _KEY_ALIASES:
|
|
72
|
+
return _KEY_ALIASES[lower_token]
|
|
73
|
+
|
|
74
|
+
if len(lower_token) == 1 and lower_token.isalnum():
|
|
75
|
+
return lower_token
|
|
76
|
+
|
|
77
|
+
if lower_token.startswith("f") and lower_token[1:].isdigit():
|
|
78
|
+
return lower_token
|
|
79
|
+
|
|
80
|
+
raise StreamlitAPIException(
|
|
81
|
+
"shortcut must include a single character or one of the supported keys "
|
|
82
|
+
"(e.g. Enter, Space, Tab, Escape)."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def normalize_shortcut(shortcut: str) -> str:
|
|
87
|
+
"""Normalize a shortcut string to a format that can be used on the client side.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
shortcut : str
|
|
92
|
+
The shortcut string to normalize.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
str
|
|
97
|
+
The normalized shortcut string.
|
|
98
|
+
|
|
99
|
+
Raises
|
|
100
|
+
------
|
|
101
|
+
StreamlitAPIException
|
|
102
|
+
If the shortcut is not a string value.
|
|
103
|
+
If the shortcut does not contain at least one key or modifier.
|
|
104
|
+
If the shortcut contains a single non-modifier key.
|
|
105
|
+
If the shortcut uses the keys 'C' or 'R', with or without modifiers.
|
|
106
|
+
If the shortcut does not include a non-modifier key.
|
|
107
|
+
"""
|
|
108
|
+
if not isinstance(shortcut, str):
|
|
109
|
+
raise StreamlitAPIException("shortcut must be a string value.")
|
|
110
|
+
|
|
111
|
+
tokens = [token.strip() for token in shortcut.split("+") if token.strip()]
|
|
112
|
+
if not tokens:
|
|
113
|
+
raise StreamlitAPIException(
|
|
114
|
+
"The `shortcut` must contain at least one key or modifier."
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
modifiers: list[str] = []
|
|
118
|
+
key: str | None = None
|
|
119
|
+
|
|
120
|
+
for raw_token in tokens:
|
|
121
|
+
lower_token = raw_token.lower()
|
|
122
|
+
if lower_token in _MODIFIER_ALIASES:
|
|
123
|
+
normalized_modifier = _MODIFIER_ALIASES[lower_token]
|
|
124
|
+
if normalized_modifier not in modifiers:
|
|
125
|
+
modifiers.append(normalized_modifier)
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
if key is not None:
|
|
129
|
+
raise StreamlitAPIException(
|
|
130
|
+
"The `shortcut` may only specify a single non-modifier key."
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
normalized_key = _normalize_key_token(lower_token)
|
|
134
|
+
if normalized_key in _RESERVED_KEYS:
|
|
135
|
+
raise StreamlitAPIException(
|
|
136
|
+
"The `shortcut` cannot use the keys 'C' or 'R', with or without modifiers."
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
key = normalized_key
|
|
140
|
+
|
|
141
|
+
if key is None:
|
|
142
|
+
raise StreamlitAPIException(
|
|
143
|
+
"The `shortcut` must include a non-modifier key such as 'K' or 'Ctrl+K'."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
normalized_tokens: list[str] = [
|
|
147
|
+
modifier for modifier in _MODIFIER_ORDER if modifier in modifiers
|
|
148
|
+
]
|
|
149
|
+
if key is not None:
|
|
150
|
+
normalized_tokens.append(key)
|
|
151
|
+
|
|
152
|
+
return "+".join(normalized_tokens)
|