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.
Files changed (406) hide show
  1. streamlit/__init__.py +5 -1
  2. streamlit/commands/execution_control.py +89 -14
  3. streamlit/commands/navigation.py +4 -6
  4. streamlit/commands/page_config.py +4 -6
  5. streamlit/components/v1/component_arrow.py +7 -7
  6. streamlit/components/v2/__init__.py +514 -0
  7. streamlit/components/v2/bidi_component/__init__.py +20 -0
  8. streamlit/components/v2/bidi_component/constants.py +29 -0
  9. streamlit/components/v2/bidi_component/main.py +534 -0
  10. streamlit/components/v2/bidi_component/serialization.py +272 -0
  11. streamlit/components/v2/bidi_component/state.py +92 -0
  12. streamlit/components/v2/component_definition_resolver.py +143 -0
  13. streamlit/components/v2/component_file_watcher.py +403 -0
  14. streamlit/components/v2/component_manager.py +439 -0
  15. streamlit/components/v2/component_manifest_handler.py +122 -0
  16. streamlit/components/v2/component_path_utils.py +245 -0
  17. streamlit/components/v2/component_registry.py +426 -0
  18. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  19. streamlit/components/v2/manifest_scanner.py +615 -0
  20. streamlit/components/v2/presentation.py +198 -0
  21. streamlit/components/v2/types.py +324 -0
  22. streamlit/config.py +456 -53
  23. streamlit/config_option.py +4 -1
  24. streamlit/config_util.py +650 -1
  25. streamlit/connections/snowflake_connection.py +1 -1
  26. streamlit/connections/snowpark_connection.py +1 -1
  27. streamlit/dataframe_util.py +33 -26
  28. streamlit/delta_generator.py +13 -4
  29. streamlit/delta_generator_singletons.py +11 -15
  30. streamlit/deprecation_util.py +17 -6
  31. streamlit/elements/alert.py +16 -0
  32. streamlit/elements/arrow.py +68 -10
  33. streamlit/elements/bokeh_chart.py +10 -78
  34. streamlit/elements/code.py +2 -2
  35. streamlit/elements/deck_gl_json_chart.py +98 -40
  36. streamlit/elements/dialog_decorator.py +2 -1
  37. streamlit/elements/exception.py +4 -2
  38. streamlit/elements/form.py +27 -0
  39. streamlit/elements/graphviz_chart.py +1 -3
  40. streamlit/elements/heading.py +63 -10
  41. streamlit/elements/html.py +13 -2
  42. streamlit/elements/image.py +3 -5
  43. streamlit/elements/layouts.py +59 -33
  44. streamlit/elements/lib/built_in_chart_utils.py +50 -19
  45. streamlit/elements/lib/color_util.py +9 -19
  46. streamlit/elements/lib/column_config_utils.py +9 -12
  47. streamlit/elements/lib/column_types.py +40 -12
  48. streamlit/elements/lib/dialog.py +2 -2
  49. streamlit/elements/lib/image_utils.py +3 -5
  50. streamlit/elements/lib/layout_utils.py +100 -13
  51. streamlit/elements/lib/mutable_status_container.py +2 -2
  52. streamlit/elements/lib/options_selector_utils.py +2 -2
  53. streamlit/elements/lib/pandas_styler_utils.py +17 -9
  54. streamlit/elements/lib/shortcut_utils.py +152 -0
  55. streamlit/elements/lib/utils.py +4 -4
  56. streamlit/elements/map.py +80 -37
  57. streamlit/elements/markdown.py +50 -3
  58. streamlit/elements/media.py +5 -7
  59. streamlit/elements/metric.py +34 -6
  60. streamlit/elements/pdf.py +2 -4
  61. streamlit/elements/plotly_chart.py +197 -20
  62. streamlit/elements/progress.py +2 -4
  63. streamlit/elements/space.py +113 -0
  64. streamlit/elements/spinner.py +1 -1
  65. streamlit/elements/text.py +20 -3
  66. streamlit/elements/toast.py +2 -0
  67. streamlit/elements/vega_charts.py +356 -149
  68. streamlit/elements/widgets/audio_input.py +12 -11
  69. streamlit/elements/widgets/button.py +280 -43
  70. streamlit/elements/widgets/button_group.py +60 -9
  71. streamlit/elements/widgets/camera_input.py +3 -5
  72. streamlit/elements/widgets/chat.py +307 -43
  73. streamlit/elements/widgets/color_picker.py +8 -1
  74. streamlit/elements/widgets/data_editor.py +88 -44
  75. streamlit/elements/widgets/file_uploader.py +9 -11
  76. streamlit/elements/widgets/multiselect.py +4 -3
  77. streamlit/elements/widgets/number_input.py +4 -4
  78. streamlit/elements/widgets/radio.py +10 -3
  79. streamlit/elements/widgets/select_slider.py +8 -5
  80. streamlit/elements/widgets/selectbox.py +6 -3
  81. streamlit/elements/widgets/slider.py +38 -42
  82. streamlit/elements/widgets/text_widgets.py +2 -0
  83. streamlit/elements/widgets/time_widgets.py +587 -21
  84. streamlit/elements/write.py +27 -6
  85. streamlit/emojis.py +1 -1
  86. streamlit/errors.py +137 -0
  87. streamlit/git_util.py +1 -1
  88. streamlit/hello/hello.py +8 -0
  89. streamlit/hello/utils.py +2 -1
  90. streamlit/material_icon_names.py +1 -1
  91. streamlit/navigation/page.py +11 -1
  92. streamlit/net_util.py +2 -2
  93. streamlit/proto/Alert_pb2.pyi +3 -3
  94. streamlit/proto/AppPage_pb2.pyi +7 -1
  95. streamlit/proto/ArrowData_pb2.py +27 -0
  96. streamlit/proto/ArrowData_pb2.pyi +52 -0
  97. streamlit/proto/ArrowNamedDataSet_pb2.pyi +7 -1
  98. streamlit/proto/ArrowVegaLiteChart_pb2.pyi +7 -1
  99. streamlit/proto/Arrow_pb2.py +10 -10
  100. streamlit/proto/Arrow_pb2.pyi +19 -12
  101. streamlit/proto/AudioInput_pb2.pyi +7 -1
  102. streamlit/proto/Audio_pb2.pyi +7 -1
  103. streamlit/proto/AuthRedirect_pb2.pyi +7 -1
  104. streamlit/proto/AutoRerun_pb2.pyi +7 -1
  105. streamlit/proto/BackMsg_pb2.py +4 -2
  106. streamlit/proto/BackMsg_pb2.pyi +34 -4
  107. streamlit/proto/Balloons_pb2.pyi +7 -1
  108. streamlit/proto/BidiComponent_pb2.py +34 -0
  109. streamlit/proto/BidiComponent_pb2.pyi +159 -0
  110. streamlit/proto/Block_pb2.py +7 -7
  111. streamlit/proto/Block_pb2.pyi +39 -36
  112. streamlit/proto/BokehChart_pb2.pyi +7 -1
  113. streamlit/proto/ButtonGroup_pb2.pyi +9 -9
  114. streamlit/proto/Button_pb2.py +2 -2
  115. streamlit/proto/Button_pb2.pyi +11 -2
  116. streamlit/proto/CameraInput_pb2.pyi +7 -1
  117. streamlit/proto/ChatInput_pb2.py +6 -6
  118. streamlit/proto/ChatInput_pb2.pyi +18 -6
  119. streamlit/proto/Checkbox_pb2.pyi +3 -3
  120. streamlit/proto/ClientState_pb2.pyi +10 -4
  121. streamlit/proto/Code_pb2.pyi +7 -1
  122. streamlit/proto/ColorPicker_pb2.pyi +7 -1
  123. streamlit/proto/Common_pb2.py +3 -3
  124. streamlit/proto/Common_pb2.pyi +35 -23
  125. streamlit/proto/Components_pb2.pyi +19 -13
  126. streamlit/proto/DataFrame_pb2.pyi +55 -49
  127. streamlit/proto/DateInput_pb2.pyi +7 -1
  128. streamlit/proto/DateTimeInput_pb2.py +28 -0
  129. streamlit/proto/DateTimeInput_pb2.pyi +92 -0
  130. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  131. streamlit/proto/DeckGlJsonChart_pb2.pyi +12 -6
  132. streamlit/proto/Delta_pb2.pyi +7 -1
  133. streamlit/proto/DocString_pb2.pyi +10 -4
  134. streamlit/proto/DownloadButton_pb2.py +2 -2
  135. streamlit/proto/DownloadButton_pb2.pyi +16 -2
  136. streamlit/proto/Element_pb2.py +7 -3
  137. streamlit/proto/Element_pb2.pyi +33 -5
  138. streamlit/proto/Empty_pb2.pyi +7 -1
  139. streamlit/proto/Exception_pb2.pyi +7 -1
  140. streamlit/proto/Favicon_pb2.pyi +7 -1
  141. streamlit/proto/FileUploader_pb2.pyi +7 -1
  142. streamlit/proto/ForwardMsg_pb2.py +12 -10
  143. streamlit/proto/ForwardMsg_pb2.pyi +42 -15
  144. streamlit/proto/GapSize_pb2.pyi +4 -4
  145. streamlit/proto/GitInfo_pb2.pyi +3 -3
  146. streamlit/proto/GraphVizChart_pb2.pyi +7 -1
  147. streamlit/proto/Heading_pb2.pyi +7 -1
  148. streamlit/proto/HeightConfig_pb2.py +2 -2
  149. streamlit/proto/HeightConfig_pb2.pyi +13 -4
  150. streamlit/proto/Html_pb2.py +2 -2
  151. streamlit/proto/Html_pb2.pyi +11 -2
  152. streamlit/proto/IFrame_pb2.pyi +7 -1
  153. streamlit/proto/Image_pb2.pyi +10 -4
  154. streamlit/proto/Json_pb2.pyi +7 -1
  155. streamlit/proto/LabelVisibilityMessage_pb2.pyi +3 -3
  156. streamlit/proto/LinkButton_pb2.py +2 -2
  157. streamlit/proto/LinkButton_pb2.pyi +15 -2
  158. streamlit/proto/Logo_pb2.pyi +7 -1
  159. streamlit/proto/Markdown_pb2.pyi +3 -3
  160. streamlit/proto/Metric_pb2.pyi +7 -7
  161. streamlit/proto/MetricsEvent_pb2.pyi +10 -4
  162. streamlit/proto/MultiSelect_pb2.pyi +7 -1
  163. streamlit/proto/NamedDataSet_pb2.pyi +7 -1
  164. streamlit/proto/Navigation_pb2.pyi +3 -3
  165. streamlit/proto/NewSession_pb2.py +18 -18
  166. streamlit/proto/NewSession_pb2.pyi +59 -40
  167. streamlit/proto/NumberInput_pb2.pyi +3 -3
  168. streamlit/proto/PageConfig_pb2.pyi +7 -7
  169. streamlit/proto/PageInfo_pb2.pyi +7 -1
  170. streamlit/proto/PageLink_pb2.py +2 -2
  171. streamlit/proto/PageLink_pb2.pyi +11 -2
  172. streamlit/proto/PageNotFound_pb2.pyi +7 -1
  173. streamlit/proto/PageProfile_pb2.pyi +13 -7
  174. streamlit/proto/PagesChanged_pb2.pyi +7 -1
  175. streamlit/proto/ParentMessage_pb2.pyi +7 -1
  176. streamlit/proto/PlotlyChart_pb2.py +8 -6
  177. streamlit/proto/PlotlyChart_pb2.pyi +9 -7
  178. streamlit/proto/Progress_pb2.pyi +7 -1
  179. streamlit/proto/Radio_pb2.pyi +7 -1
  180. streamlit/proto/RootContainer_pb2.pyi +1 -1
  181. streamlit/proto/Selectbox_pb2.pyi +7 -1
  182. streamlit/proto/SessionEvent_pb2.pyi +7 -1
  183. streamlit/proto/SessionStatus_pb2.pyi +7 -1
  184. streamlit/proto/Skeleton_pb2.pyi +3 -3
  185. streamlit/proto/Slider_pb2.pyi +5 -5
  186. streamlit/proto/Snow_pb2.pyi +7 -1
  187. streamlit/proto/Space_pb2.py +27 -0
  188. streamlit/proto/Space_pb2.pyi +48 -0
  189. streamlit/proto/Spinner_pb2.pyi +7 -1
  190. streamlit/proto/TextAlignmentConfig_pb2.py +29 -0
  191. streamlit/proto/TextAlignmentConfig_pb2.pyi +68 -0
  192. streamlit/proto/TextArea_pb2.pyi +7 -1
  193. streamlit/proto/TextInput_pb2.pyi +3 -3
  194. streamlit/proto/Text_pb2.pyi +7 -1
  195. streamlit/proto/TimeInput_pb2.pyi +7 -1
  196. streamlit/proto/Toast_pb2.pyi +7 -1
  197. streamlit/proto/VegaLiteChart_pb2.pyi +7 -1
  198. streamlit/proto/Video_pb2.pyi +6 -6
  199. streamlit/proto/WidgetStates_pb2.py +2 -2
  200. streamlit/proto/WidgetStates_pb2.pyi +23 -7
  201. streamlit/proto/WidthConfig_pb2.py +2 -2
  202. streamlit/proto/WidthConfig_pb2.pyi +13 -4
  203. streamlit/proto/openmetrics_data_model_pb2.pyi +52 -52
  204. streamlit/runtime/app_session.py +65 -2
  205. streamlit/runtime/caching/cache_data_api.py +5 -5
  206. streamlit/runtime/caching/cache_errors.py +4 -1
  207. streamlit/runtime/caching/cache_resource_api.py +5 -4
  208. streamlit/runtime/caching/cache_utils.py +3 -2
  209. streamlit/runtime/caching/cached_message_replay.py +3 -3
  210. streamlit/runtime/caching/hashing.py +4 -5
  211. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  212. streamlit/runtime/connection_factory.py +1 -3
  213. streamlit/runtime/download_data_util.py +53 -0
  214. streamlit/runtime/forward_msg_queue.py +5 -1
  215. streamlit/runtime/fragment.py +2 -1
  216. streamlit/runtime/media_file_manager.py +178 -2
  217. streamlit/runtime/memory_media_file_storage.py +1 -1
  218. streamlit/runtime/metrics_util.py +91 -3
  219. streamlit/runtime/runtime.py +14 -0
  220. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  221. streamlit/runtime/scriptrunner/script_runner.py +5 -3
  222. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  223. streamlit/runtime/secrets.py +2 -4
  224. streamlit/runtime/session_manager.py +3 -1
  225. streamlit/runtime/state/common.py +30 -5
  226. streamlit/runtime/state/presentation.py +85 -0
  227. streamlit/runtime/state/query_params.py +80 -29
  228. streamlit/runtime/state/safe_session_state.py +2 -2
  229. streamlit/runtime/state/session_state.py +221 -17
  230. streamlit/runtime/state/widgets.py +19 -3
  231. streamlit/runtime/websocket_session_manager.py +3 -1
  232. streamlit/source_util.py +2 -2
  233. streamlit/static/index.html +2 -2
  234. streamlit/static/manifest.json +557 -239
  235. streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
  236. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  237. streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.ZJDbmVTx.js} +1 -1
  238. streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Dx0vI3vH.js} +1 -1
  239. streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.B7Ero7qQ.js} +3 -3
  240. streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.CG2XN1_g.js} +1 -1
  241. streamlit/static/static/js/IFrameUtil.DefezniK.js +1 -0
  242. streamlit/static/static/js/InputInstructions.Cj5-1zf6.js +1 -0
  243. streamlit/static/static/js/Particles.BfWfv0Aw.js +1 -0
  244. streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.CGQ8OgfO.js} +2 -2
  245. streamlit/static/static/js/StreamlitSyntaxHighlighter.DTKLpwhl.js +20 -0
  246. streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.B2qFUmd9.js} +1 -1
  247. streamlit/static/static/js/_arrayIncludes.B19Iyn2B.js +1 -0
  248. streamlit/static/static/js/_baseIndexOf.BTknn6Gb.js +1 -0
  249. streamlit/static/static/js/{base-input.BQft14La.js → base-input.o9tL8MDP.js} +4 -4
  250. streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.0BeV1IBL.js} +1 -1
  251. streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.RBO59fEm.js} +1 -1
  252. streamlit/static/static/js/data-grid-overlay-editor.CiTkUy0t.js +1 -0
  253. streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.DwNZg3Mw.js} +1 -1
  254. streamlit/static/static/js/embed.XT9xNd3F.js +195 -0
  255. streamlit/static/static/js/{es6.VpBPGCnM.js → es6.x9KsYQg-.js} +2 -2
  256. streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.ZVXpMPi0.js} +1 -1
  257. streamlit/static/static/js/index.5VPOamri.js +1 -0
  258. streamlit/static/static/js/index.8HslT92O.js +14 -0
  259. streamlit/static/static/js/index.AnXMIBz3.js +7 -0
  260. streamlit/static/static/js/index.B0yp3bM1.js +6 -0
  261. streamlit/static/static/js/index.B1fRb5wF.js +1 -0
  262. streamlit/static/static/js/index.B527JZdO.js +3 -0
  263. streamlit/static/static/js/index.BHgV-yW4.js +1 -0
  264. streamlit/static/static/js/index.BQr-XwGV.js +1 -0
  265. streamlit/static/static/js/index.BTtmaLDB.js +1 -0
  266. streamlit/static/static/js/index.BWB_91TA.js +1 -0
  267. streamlit/static/static/js/index.BfEKaEmw.js +1 -0
  268. streamlit/static/static/js/index.BfXjTO8b.js +1 -0
  269. streamlit/static/static/js/index.Bjy4NRu9.js +3 -0
  270. streamlit/static/static/js/index.Bu5JWpT_.js +1 -0
  271. streamlit/static/static/js/index.BuCx76ZV.js +1 -0
  272. streamlit/static/static/js/index.BxjzhVUb.js +2 -0
  273. streamlit/static/static/js/index.By55VdPY.js +1 -0
  274. streamlit/static/static/js/index.CF5MxTbK.js +1 -0
  275. streamlit/static/static/js/index.CLmq_z9K.js +1 -0
  276. streamlit/static/static/js/index.CNH4rdSz.js +1 -0
  277. streamlit/static/static/js/{index.B0H9IXUJ.js → index.CTgm_-jO.js} +10 -41
  278. streamlit/static/static/js/index.C_rK-Swb.js +188 -0
  279. streamlit/static/static/js/index.CjozwSzS.js +1 -0
  280. streamlit/static/static/js/{index.CH1tqnSs.js → index.CkGVt6-G.js} +1 -1
  281. streamlit/static/static/js/index.CuvXOyER.js +2 -0
  282. streamlit/static/static/js/{index.FFOzOWzC.js → index.CyUHWoCC.js} +2 -2
  283. streamlit/static/static/js/index.CyroQtI4.js +2 -0
  284. streamlit/static/static/js/index.D6HmkoDm.js +263 -0
  285. streamlit/static/static/js/index.DAqCNvsO.js +1 -0
  286. streamlit/static/static/js/index.DB_w_CZQ.js +1 -0
  287. streamlit/static/static/js/index.DBalctjj.js +2 -0
  288. streamlit/static/static/js/index.DK0RFJUG.js +11 -0
  289. streamlit/static/static/js/index.DMxc2XFp.js +151 -0
  290. streamlit/static/static/js/index.DO5utP74.js +2 -0
  291. streamlit/static/static/js/index.DS7lf09n.js +1 -0
  292. streamlit/static/static/js/index.DWexTVLY.js +1 -0
  293. streamlit/static/static/js/index.DXxnU5ej.js +1 -0
  294. streamlit/static/static/js/index.DcU3uDvB.js +2 -0
  295. streamlit/static/static/js/index.DlltaH7J.js +1 -0
  296. streamlit/static/static/js/index.DpNTZz82.js +27 -0
  297. streamlit/static/static/js/index.Dr9HIhQw.js +1 -0
  298. streamlit/static/static/js/index.DsgAU5lc.js +1 -0
  299. streamlit/static/static/js/{index.64ejlaaT.js → index.KfXqjDYy.js} +1 -1
  300. streamlit/static/static/js/index.PaidgjCs.js +1 -0
  301. streamlit/static/static/js/index.RJZuWCGA.js +1 -0
  302. streamlit/static/static/js/{index.Ctn27_AE.js → index.hbeqcRTn.js} +53 -122
  303. streamlit/static/static/js/index.q5hIQwAY.js +1 -0
  304. streamlit/static/static/js/index.rORSX6IW.js +1 -0
  305. streamlit/static/static/js/index.uSX757_v.js +1 -0
  306. streamlit/static/static/js/index.x_QRaLMd.js +1 -0
  307. streamlit/static/static/js/{input.s6pjQ49A.js → input.D5oh9-aB.js} +2 -2
  308. streamlit/static/static/js/main.q9oGOg0H.js +13 -0
  309. streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.5kCSFUJS.js} +1 -1
  310. streamlit/static/static/js/moment.C3j7ZXd7.js +4 -0
  311. streamlit/static/static/js/number-overlay-editor.Cn_LsK8N.js +9 -0
  312. streamlit/static/static/js/pandasStylerUtils.BqhXt51_.js +1 -0
  313. streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.DD9NK1Z8.js} +1 -1
  314. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  315. streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.DACSyz29.js} +1 -1
  316. streamlit/static/static/js/styled-components.C3R090At.js +1 -0
  317. streamlit/static/static/js/threshold.Q1mXg5rX.js +1 -0
  318. streamlit/static/static/js/throttle.B0GR3Iyz.js +1 -0
  319. streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.BdhzPxrv.js} +1 -1
  320. streamlit/static/static/js/timer.C2hYhUse.js +1 -0
  321. streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.Db2pdqM2.js} +1 -1
  322. streamlit/static/static/js/uniqueId.CtqIr-Yh.js +1 -0
  323. streamlit/static/static/js/urls.BwSlolu9.js +1 -0
  324. streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.Bfp6TnSw.js} +1 -1
  325. streamlit/static/static/js/useIntlLocale.hRV75Xgj.js +12 -0
  326. streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.QepX7n8Y.js} +1 -1
  327. streamlit/static/static/js/useUpdateUiValue.DHx8TzX6.js +1 -0
  328. streamlit/static/static/js/useWaveformController.WxVzpzEX.js +1 -0
  329. streamlit/static/static/js/value.B4vHRSi7.js +1 -0
  330. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  331. streamlit/static/static/js/withCalculatedWidth.DcKeRSWJ.js +1 -0
  332. streamlit/static/static/js/withFullScreenWrapper.CrHddARq.js +1 -0
  333. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  334. streamlit/string_util.py +9 -4
  335. streamlit/testing/v1/app_test.py +17 -2
  336. streamlit/testing/v1/element_tree.py +85 -9
  337. streamlit/testing/v1/util.py +2 -2
  338. streamlit/type_util.py +3 -4
  339. streamlit/url_util.py +1 -3
  340. streamlit/user_info.py +1 -2
  341. streamlit/util.py +3 -1
  342. streamlit/watcher/event_based_path_watcher.py +23 -12
  343. streamlit/watcher/local_sources_watcher.py +11 -1
  344. streamlit/watcher/path_watcher.py +9 -6
  345. streamlit/watcher/polling_path_watcher.py +4 -1
  346. streamlit/watcher/util.py +2 -2
  347. streamlit/web/bootstrap.py +24 -0
  348. streamlit/web/cli.py +51 -22
  349. streamlit/web/server/bidi_component_request_handler.py +193 -0
  350. streamlit/web/server/component_file_utils.py +97 -0
  351. streamlit/web/server/component_request_handler.py +8 -21
  352. streamlit/web/server/oauth_authlib_routes.py +5 -2
  353. streamlit/web/server/oidc_mixin.py +3 -1
  354. streamlit/web/server/routes.py +2 -2
  355. streamlit/web/server/server.py +9 -0
  356. streamlit/web/server/server_util.py +3 -1
  357. streamlit/web/server/upload_file_request_handler.py +19 -1
  358. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/METADATA +10 -7
  359. streamlit-1.52.0.dist-info/RECORD +620 -0
  360. streamlit/static/static/css/index.CHEnSPGk.css +0 -1
  361. streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
  362. streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
  363. streamlit/static/static/js/Particles.CElH0XX2.js +0 -1
  364. streamlit/static/static/js/data-grid-overlay-editor.DcuHuCyW.js +0 -1
  365. streamlit/static/static/js/index.6xX1278W.js +0 -975
  366. streamlit/static/static/js/index.B-hiXRzw.js +0 -1
  367. streamlit/static/static/js/index.B4cAbHP6.js +0 -1
  368. streamlit/static/static/js/index.B4dUQfni.js +0 -1
  369. streamlit/static/static/js/index.BPQo7BKk.js +0 -1
  370. streamlit/static/static/js/index.Baqa90pe.js +0 -2
  371. streamlit/static/static/js/index.Bj9JgOEC.js +0 -1
  372. streamlit/static/static/js/index.BjCwMzj4.js +0 -3
  373. streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
  374. streamlit/static/static/js/index.Bxz2yX3P.js +0 -1
  375. streamlit/static/static/js/index.BycLveZ4.js +0 -1
  376. streamlit/static/static/js/index.C9BdUqTi.js +0 -1
  377. streamlit/static/static/js/index.CFMf5_ez.js +0 -197
  378. streamlit/static/static/js/index.CGYqqs6j.js +0 -1
  379. streamlit/static/static/js/index.CMItVsFA.js +0 -1
  380. streamlit/static/static/js/index.CTBk8Vk2.js +0 -1
  381. streamlit/static/static/js/index.CiAQIz1H.js +0 -7
  382. streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
  383. streamlit/static/static/js/index.Ck8rQ9OL.js +0 -1
  384. streamlit/static/static/js/index.ClELlchS.js +0 -1617
  385. streamlit/static/static/js/index.Cnpi3o3E.js +0 -1
  386. streamlit/static/static/js/index.D2QEXQq_.js +0 -1
  387. streamlit/static/static/js/index.DH71Ezyj.js +0 -1
  388. streamlit/static/static/js/index.DHh-U0dK.js +0 -3
  389. streamlit/static/static/js/index.DK7hD7_w.js +0 -1
  390. streamlit/static/static/js/index.DKv_lNO7.js +0 -2
  391. streamlit/static/static/js/index.DNLrMXgm.js +0 -12
  392. streamlit/static/static/js/index.DW0Grddz.js +0 -1
  393. streamlit/static/static/js/index.Dbe-Q3C-.js +0 -2
  394. streamlit/static/static/js/index.DcPNYEUo.js +0 -1
  395. streamlit/static/static/js/index.DuxqVQpd.js +0 -1
  396. streamlit/static/static/js/index.GRUzrudl.js +0 -1
  397. streamlit/static/static/js/number-overlay-editor.DdgVR5m3.js +0 -9
  398. streamlit/static/static/js/uniqueId.RI1LJdtz.js +0 -1
  399. streamlit/static/static/js/useUpdateUiValue.DeXelfRH.js +0 -1
  400. streamlit/static/static/js/withFullScreenWrapper.C3561XxJ.js +0 -1
  401. streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
  402. streamlit-1.50.0.dist-info/RECORD +0 -557
  403. {streamlit-1.50.0.data → streamlit-1.52.0.data}/scripts/streamlit.cmd +0 -0
  404. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/WHEEL +0 -0
  405. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/entry_points.txt +0 -0
  406. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,7 @@ from typing import (
22
22
  Any,
23
23
  Final,
24
24
  Literal,
25
+ TypeAlias,
25
26
  TypedDict,
26
27
  TypeVar,
27
28
  Union,
@@ -29,7 +30,7 @@ from typing import (
29
30
  overload,
30
31
  )
31
32
 
32
- from typing_extensions import TypeAlias
33
+ from typing_extensions import Required
33
34
 
34
35
  from streamlit import dataframe_util
35
36
  from streamlit import logger as _logger
@@ -52,6 +53,7 @@ from streamlit.elements.lib.column_config_utils import (
52
53
  )
53
54
  from streamlit.elements.lib.form_utils import current_form_id
54
55
  from streamlit.elements.lib.layout_utils import (
56
+ Height,
55
57
  LayoutConfig,
56
58
  Width,
57
59
  validate_height,
@@ -89,26 +91,19 @@ _LOGGER: Final = _logger.get_logger(__name__)
89
91
  # formats will be returned with the same type when used with data_editor.
90
92
  EditableData = TypeVar(
91
93
  "EditableData",
92
- bound=Union[
93
- dataframe_util.DataFrameGenericAlias[Any], # covers DataFrame and Series
94
- tuple[Any],
95
- list[Any],
96
- set[Any],
97
- dict[str, Any],
98
- # TODO(lukasmasuch): Add support for np.ndarray
99
- # but it is not possible with np.ndarray.
100
- # NDArray[Any] works, but is only available in numpy>1.20.
101
- # TODO(lukasmasuch): Add support for pa.Table typing
102
- # pa.Table does not work since it is a C-based class resulting in Any
103
- ],
94
+ bound=dataframe_util.DataFrameGenericAlias[Any]
95
+ | tuple[Any]
96
+ | list[Any]
97
+ | set[Any]
98
+ | dict[str, Any],
104
99
  )
105
100
 
106
101
 
107
102
  # All data types supported by the data editor.
108
103
  DataTypes: TypeAlias = Union[
109
104
  "pd.DataFrame",
110
- "pd.Series",
111
- "pd.Index",
105
+ "pd.Series[Any]",
106
+ "pd.Index[Any]",
112
107
  "Styler",
113
108
  "pa.Table",
114
109
  "np.ndarray[Any, np.dtype[np.float64]]",
@@ -138,9 +133,9 @@ class EditingState(TypedDict, total=False):
138
133
  the deleted row.
139
134
  """
140
135
 
141
- edited_rows: dict[int, dict[str, str | int | float | bool | None]]
142
- added_rows: list[dict[str, str | int | float | bool | None]]
143
- deleted_rows: list[int]
136
+ edited_rows: Required[dict[int, dict[str, str | int | float | bool | None]]]
137
+ added_rows: Required[list[dict[str, str | int | float | bool | None]]]
138
+ deleted_rows: Required[list[int]]
144
139
 
145
140
 
146
141
  @dataclass
@@ -148,30 +143,32 @@ class DataEditorSerde:
148
143
  """DataEditorSerde is used to serialize and deserialize the data editor state."""
149
144
 
150
145
  def deserialize(self, ui_value: str | None) -> EditingState:
151
- data_editor_state: EditingState = (
146
+ data_editor_state: EditingState = cast(
147
+ "EditingState",
152
148
  {
153
149
  "edited_rows": {},
154
150
  "added_rows": [],
155
151
  "deleted_rows": [],
156
152
  }
157
153
  if ui_value is None
158
- else json.loads(ui_value)
154
+ else json.loads(ui_value),
159
155
  )
160
156
 
161
157
  # Make sure that all editing state keys are present:
162
158
  if "edited_rows" not in data_editor_state:
163
- data_editor_state["edited_rows"] = {}
159
+ data_editor_state["edited_rows"] = {} # type: ignore[unreachable]
164
160
 
165
161
  if "deleted_rows" not in data_editor_state:
166
- data_editor_state["deleted_rows"] = []
162
+ data_editor_state["deleted_rows"] = [] # type: ignore[unreachable]
167
163
 
168
164
  if "added_rows" not in data_editor_state:
169
- data_editor_state["added_rows"] = []
165
+ data_editor_state["added_rows"] = [] # type: ignore[unreachable]
170
166
 
171
167
  # Convert the keys (numerical row positions) to integers.
172
168
  # The keys are strings because they are serialized to JSON.
173
169
  data_editor_state["edited_rows"] = {
174
- int(k): v for k, v in data_editor_state["edited_rows"].items()
170
+ int(k): v
171
+ for k, v in data_editor_state["edited_rows"].items() # ty: ignore[possibly-missing-attribute]
175
172
  }
176
173
  return data_editor_state
177
174
 
@@ -204,7 +201,7 @@ def _parse_value(
204
201
  import pandas as pd
205
202
 
206
203
  try:
207
- if column_data_kind == ColumnDataKind.LIST:
204
+ if column_data_kind in (ColumnDataKind.LIST, ColumnDataKind.EMPTY):
208
205
  return list(value) if is_list_like(value) else [value] # ty: ignore
209
206
 
210
207
  if column_data_kind == ColumnDataKind.STRING:
@@ -215,7 +212,7 @@ def _parse_value(
215
212
  # This isn't expected to happen.
216
213
  if isinstance(value, list):
217
214
  raise TypeError( # noqa: TRY301
218
- "List values are only supported by list and string columns."
215
+ "List values are only supported by list, string and empty columns."
219
216
  )
220
217
 
221
218
  if column_data_kind == ColumnDataKind.INTEGER:
@@ -241,10 +238,10 @@ def _parse_value(
241
238
  ColumnDataKind.DATE,
242
239
  ColumnDataKind.TIME,
243
240
  ]:
244
- datetime_value = pd.Timestamp(value)
241
+ datetime_value = pd.Timestamp(value) # ty: ignore
245
242
 
246
- if datetime_value is pd.NaT:
247
- return None
243
+ if pd.isna(datetime_value):
244
+ return None # type: ignore[unreachable]
248
245
 
249
246
  if column_data_kind == ColumnDataKind.DATETIME:
250
247
  return datetime_value
@@ -301,7 +298,7 @@ def _apply_cell_edits(
301
298
  )
302
299
  else:
303
300
  col_pos = df.columns.get_loc(col_name)
304
- df.iat[row_pos, col_pos] = _parse_value(
301
+ df.iat[row_pos, col_pos] = _parse_value( # type: ignore
305
302
  value, dataframe_schema[col_name]
306
303
  )
307
304
 
@@ -326,6 +323,20 @@ def _parse_added_row(
326
323
  return index_value, new_row
327
324
 
328
325
 
326
+ def _assign_row_values(
327
+ df: pd.DataFrame,
328
+ row_label: Any,
329
+ row_values: list[Any],
330
+ ) -> None:
331
+ """Assign values to a dataframe row via a mapping.
332
+
333
+ This avoids numpy attempting to coerce nested sequences (e.g. lists) into
334
+ multi-dimensional arrays when a column legitimately stores list values.
335
+ """
336
+
337
+ df.loc[row_label] = dict(zip(df.columns, row_values, strict=True))
338
+
339
+
329
340
  def _apply_row_additions(
330
341
  df: pd.DataFrame,
331
342
  added_rows: list[dict[str, Any]],
@@ -382,13 +393,13 @@ def _apply_row_additions(
382
393
  # already exists. In the future, it would be better to
383
394
  # require users to provide unique non-None values for the index with
384
395
  # some kind of visual indications.
385
- df.loc[index_value, :] = new_row
396
+ _assign_row_values(df, index_value, new_row)
386
397
  continue
387
398
 
388
399
  if index_stop is not None and index_step is not None:
389
400
  # Case 2: Range or integer index that can be auto incremented.
390
401
  # Add row using the next value in the sequence
391
- df.loc[index_stop, :] = new_row
402
+ _assign_row_values(df, index_stop, new_row)
392
403
  # Increment to the next range index value
393
404
  index_stop += index_step
394
405
  continue
@@ -448,7 +459,7 @@ def _apply_dataframe_edits(
448
459
  _apply_row_additions(df, data_editor_state["added_rows"], dataframe_schema)
449
460
 
450
461
 
451
- def _is_supported_index(df_index: pd.Index) -> bool:
462
+ def _is_supported_index(df_index: pd.Index[Any]) -> bool:
452
463
  """Check if the index is supported by the data editor component.
453
464
 
454
465
  Parameters
@@ -564,7 +575,7 @@ def _check_type_compatibilities(
564
575
  indices = [(INDEX_IDENTIFIER, data_df.index)]
565
576
 
566
577
  for column in indices + list(data_df.items()):
567
- column_name, _ = column
578
+ column_name = str(column[0])
568
579
  column_data_kind = dataframe_schema[column_name]
569
580
 
570
581
  # TODO(lukasmasuch): support column config via numerical index here?
@@ -602,7 +613,7 @@ class DataEditorMixin:
602
613
  data: EditableData,
603
614
  *,
604
615
  width: Width = "stretch",
605
- height: int | Literal["auto"] = "auto",
616
+ height: Height | Literal["auto"] = "auto",
606
617
  use_container_width: bool | None = None,
607
618
  hide_index: bool | None = None,
608
619
  column_order: Iterable[str] | None = None,
@@ -614,6 +625,7 @@ class DataEditorMixin:
614
625
  args: WidgetArgs | None = None,
615
626
  kwargs: WidgetKwargs | None = None,
616
627
  row_height: int | None = None,
628
+ placeholder: str | None = None,
617
629
  ) -> EditableData:
618
630
  pass
619
631
 
@@ -623,7 +635,7 @@ class DataEditorMixin:
623
635
  data: Any,
624
636
  *,
625
637
  width: Width = "stretch",
626
- height: int | Literal["auto"] = "auto",
638
+ height: Height | Literal["auto"] = "auto",
627
639
  use_container_width: bool | None = None,
628
640
  hide_index: bool | None = None,
629
641
  column_order: Iterable[str] | None = None,
@@ -635,6 +647,7 @@ class DataEditorMixin:
635
647
  args: WidgetArgs | None = None,
636
648
  kwargs: WidgetKwargs | None = None,
637
649
  row_height: int | None = None,
650
+ placeholder: str | None = None,
638
651
  ) -> pd.DataFrame:
639
652
  pass
640
653
 
@@ -644,7 +657,7 @@ class DataEditorMixin:
644
657
  data: DataTypes,
645
658
  *,
646
659
  width: Width = "stretch",
647
- height: int | Literal["auto"] = "auto",
660
+ height: Height | Literal["auto"] = "auto",
648
661
  use_container_width: bool | None = None,
649
662
  hide_index: bool | None = None,
650
663
  column_order: Iterable[str] | None = None,
@@ -656,6 +669,7 @@ class DataEditorMixin:
656
669
  args: WidgetArgs | None = None,
657
670
  kwargs: WidgetKwargs | None = None,
658
671
  row_height: int | None = None,
672
+ placeholder: str | None = None,
659
673
  ) -> DataTypes:
660
674
  """Display a data editor widget.
661
675
 
@@ -670,6 +684,9 @@ class DataEditorMixin:
670
684
  - Styles from ``pandas.Styler`` will only be applied to non-editable columns.
671
685
  - Text and number formatting from ``column_config`` always takes
672
686
  precedence over text and number formatting from ``pandas.Styler``.
687
+ - If your dataframe starts with an empty column, you should set
688
+ the column datatype in the underlying dataframe to ensure your
689
+ intended datatype, especially for integers versus floats.
673
690
  - Mixing data types within a column can make the column uneditable.
674
691
  - Additionally, the following data types are not yet supported for editing:
675
692
  ``complex``, ``tuple``, ``bytes``, ``bytearray``,
@@ -693,16 +710,26 @@ class DataEditorMixin:
693
710
  the parent container, the width of the editor matches the width
694
711
  of the parent container.
695
712
 
696
- height : int or "auto"
713
+ height : "auto", "content", "stretch", or int
697
714
  The height of the data editor. This can be one of the following:
698
715
 
699
716
  - ``"auto"`` (default): Streamlit sets the height to show at most
700
717
  ten rows.
718
+ - ``"content"``: The height of the editor matches the height of
719
+ its content. The height is capped at 10,000 pixels to prevent
720
+ performance issues with very large dataframes.
721
+ - ``"stretch"``: The height of the editor expands to fill the
722
+ available vertical space in its parent container. When multiple
723
+ elements with stretch height are in the same container, they
724
+ share the available vertical space evenly. The editor will
725
+ maintain a minimum height to display up to three rows, but
726
+ otherwise won't exceed the available height in its parent
727
+ container.
701
728
  - An integer specifying the height in pixels: The editor has a
702
729
  fixed height.
703
730
 
704
- Vertical scrolling within the data editor is enabled when the
705
- height does not accommodate all rows.
731
+ Vertical scrolling within the editor is enabled when the height
732
+ does not accommodate all rows.
706
733
 
707
734
  use_container_width : bool
708
735
  Whether to override ``width`` with the width of the parent
@@ -798,6 +825,12 @@ class DataEditorMixin:
798
825
  is ``None`` (default), Streamlit will use a default row height,
799
826
  which fits one line of text.
800
827
 
828
+ placeholder : str or None
829
+ The text that should be shown for missing values. If this is
830
+ ``None`` (default), missing values are displayed as "None". To
831
+ leave a cell empty, use an empty string (``""``). Other common
832
+ values are ``"null"``, ``"NaN"`` and ``"-"``.
833
+
801
834
  Returns
802
835
  -------
803
836
  pandas.DataFrame, pandas.Series, pyarrow.Table, numpy.ndarray, list, set, tuple, or dict.
@@ -903,8 +936,8 @@ class DataEditorMixin:
903
936
  validate_width(width, allow_content=True)
904
937
  validate_height(
905
938
  height,
906
- allow_content=False,
907
- allow_stretch=False,
939
+ allow_content=True,
940
+ allow_stretch=True,
908
941
  additional_allowed=["auto"],
909
942
  )
910
943
 
@@ -967,10 +1000,10 @@ class DataEditorMixin:
967
1000
  for column_name, column_data in data_df.items():
968
1001
  if dataframe_util.is_colum_type_arrow_incompatible(column_data):
969
1002
  update_column_config(
970
- column_config_mapping, column_name, {"disabled": True}
1003
+ column_config_mapping, str(column_name), {"disabled": True}
971
1004
  )
972
1005
  # Convert incompatible type to string
973
- data_df[column_name] = column_data.astype("string")
1006
+ data_df[cast("Any", column_name)] = column_data.astype("string")
974
1007
 
975
1008
  apply_data_specific_configs(column_config_mapping, data_format)
976
1009
 
@@ -985,6 +1018,13 @@ class DataEditorMixin:
985
1018
  update_column_config(
986
1019
  column_config_mapping, INDEX_IDENTIFIER, {"required": True}
987
1020
  )
1021
+ if num_rows == "dynamic" and hide_index is True:
1022
+ _LOGGER.warning(
1023
+ "Setting `hide_index=True` in data editor with a non-range index will not have any effect "
1024
+ "when `num_rows='dynamic'`. It is required for the user to fill in index values for "
1025
+ "adding new rows. To hide the index, make sure to set the DataFrame "
1026
+ "index to a range index."
1027
+ )
988
1028
 
989
1029
  if hide_index is None and has_range_index and num_rows == "dynamic":
990
1030
  # Temporary workaround:
@@ -1038,6 +1078,7 @@ class DataEditorMixin:
1038
1078
  column_config_mapping=str(column_config_mapping),
1039
1079
  num_rows=num_rows,
1040
1080
  row_height=row_height,
1081
+ placeholder=placeholder,
1041
1082
  )
1042
1083
 
1043
1084
  proto = ArrowProto()
@@ -1049,6 +1090,9 @@ class DataEditorMixin:
1049
1090
  if column_order:
1050
1091
  proto.column_order[:] = column_order
1051
1092
 
1093
+ if placeholder is not None:
1094
+ proto.placeholder = placeholder
1095
+
1052
1096
  # Only set disabled to true if it is actually true
1053
1097
  # It can also be a list of columns, which should result in false here.
1054
1098
  proto.disabled = disabled is True
@@ -16,9 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  from dataclasses import dataclass
18
18
  from textwrap import dedent
19
- from typing import TYPE_CHECKING, Literal, Union, cast, overload
20
-
21
- from typing_extensions import TypeAlias
19
+ from typing import TYPE_CHECKING, Literal, TypeAlias, cast, overload
22
20
 
23
21
  from streamlit import config
24
22
  from streamlit.elements.lib.file_uploader_utils import (
@@ -60,18 +58,15 @@ if TYPE_CHECKING:
60
58
 
61
59
  from streamlit.delta_generator import DeltaGenerator
62
60
 
63
- SomeUploadedFiles: TypeAlias = Union[
64
- UploadedFile,
65
- DeletedFile,
66
- list[Union[UploadedFile, DeletedFile]],
67
- None,
68
- ]
61
+ SomeUploadedFiles: TypeAlias = (
62
+ UploadedFile | DeletedFile | list[UploadedFile | DeletedFile] | None
63
+ )
69
64
 
70
65
  # Type alias for accept_multiple_files parameter.
71
66
  # If True, multiple files can be uploaded.
72
67
  # If False, only a single file can be uploaded.
73
68
  # If set to the literal "directory", users can upload an entire directory (folder) of files.
74
- AcceptMultipleFiles: TypeAlias = Union[bool, Literal["directory"]]
69
+ AcceptMultipleFiles: TypeAlias = bool | Literal["directory"]
75
70
 
76
71
 
77
72
  def _get_upload_files(
@@ -488,7 +483,10 @@ class FileUploaderMixin:
488
483
  element_id = compute_and_register_element_id(
489
484
  "file_uploader",
490
485
  user_key=key,
491
- key_as_main_identity=False,
486
+ # Treat the provided key as the main identity; only include
487
+ # changes to the type and accept_multiple_files parameters in
488
+ # the identity computation as those can invalidate the current value.
489
+ key_as_main_identity={"type", "accept_multiple_files"},
492
490
  dg=self.dg,
493
491
  label=label,
494
492
  type=type,
@@ -19,7 +19,6 @@ from textwrap import dedent
19
19
  from typing import (
20
20
  TYPE_CHECKING,
21
21
  Any,
22
- Callable,
23
22
  Generic,
24
23
  Literal,
25
24
  TypeVar,
@@ -64,7 +63,7 @@ from streamlit.type_util import (
64
63
  )
65
64
 
66
65
  if TYPE_CHECKING:
67
- from collections.abc import Sequence
66
+ from collections.abc import Callable, Sequence
68
67
 
69
68
  from streamlit.dataframe_util import OptionSequence
70
69
  from streamlit.delta_generator import DeltaGenerator
@@ -370,7 +369,9 @@ class MultiSelectMixin:
370
369
  Returns
371
370
  -------
372
371
  list
373
- A list with the selected options
372
+ A list of the selected options.
373
+
374
+ The list contains copies of the selected options, not the originals.
374
375
 
375
376
  Examples
376
377
  --------
@@ -17,9 +17,7 @@ from __future__ import annotations
17
17
  import numbers
18
18
  from dataclasses import dataclass
19
19
  from textwrap import dedent
20
- from typing import TYPE_CHECKING, Literal, TypeVar, Union, cast, overload
21
-
22
- from typing_extensions import TypeAlias
20
+ from typing import TYPE_CHECKING, Literal, TypeAlias, TypeVar, cast, overload
23
21
 
24
22
  from streamlit.elements.lib.form_utils import current_form_id
25
23
  from streamlit.elements.lib.js_number import JSNumber, JSNumberBoundsException
@@ -62,7 +60,7 @@ if TYPE_CHECKING:
62
60
  from streamlit.delta_generator import DeltaGenerator
63
61
 
64
62
 
65
- Number: TypeAlias = Union[int, float]
63
+ Number: TypeAlias = int | float
66
64
  IntOrNone = TypeVar("IntOrNone", int, None)
67
65
  FloatOrNone = TypeVar("FloatOrNone", float, None)
68
66
 
@@ -355,6 +353,8 @@ class NumberInputMixin:
355
353
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
356
354
  font library.
357
355
 
356
+ - ``"spinner"``: Displays a spinner as an icon.
357
+
358
358
  width : "stretch" or int
359
359
  The width of the number input widget. This can be one of the
360
360
  following:
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  from dataclasses import dataclass
18
18
  from textwrap import dedent
19
- from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast, overload
19
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, overload
20
20
 
21
21
  from typing_extensions import Never
22
22
 
@@ -56,7 +56,7 @@ from streamlit.type_util import (
56
56
  )
57
57
 
58
58
  if TYPE_CHECKING:
59
- from collections.abc import Sequence
59
+ from collections.abc import Callable, Sequence
60
60
 
61
61
  from streamlit.delta_generator import DeltaGenerator
62
62
 
@@ -272,6 +272,8 @@ class RadioMixin:
272
272
  any
273
273
  The selected option or ``None`` if no option is selected.
274
274
 
275
+ This is a copy of the selected option, not the original.
276
+
275
277
  Example
276
278
  -------
277
279
  >>> import streamlit as st
@@ -369,7 +371,12 @@ class RadioMixin:
369
371
  element_id = compute_and_register_element_id(
370
372
  "radio",
371
373
  user_key=key,
372
- key_as_main_identity=False,
374
+ # Treat provided key as the main widget identity. Only include the
375
+ # following parameters in the identity computation since they can
376
+ # invalidate the current selection mapping.
377
+ # Changes to format_func also invalidate the current selection,
378
+ # but this is already handled via the `options` parameter below:
379
+ key_as_main_identity={"options"},
373
380
  dg=self.dg,
374
381
  label=label,
375
382
  options=[str(format_func(option)) for option in opt],
@@ -19,15 +19,13 @@ from textwrap import dedent
19
19
  from typing import (
20
20
  TYPE_CHECKING,
21
21
  Any,
22
- Callable,
23
22
  Generic,
23
+ TypeGuard,
24
24
  TypeVar,
25
25
  cast,
26
26
  overload,
27
27
  )
28
28
 
29
- from typing_extensions import TypeGuard
30
-
31
29
  from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
32
30
  from streamlit.elements.lib.form_utils import current_form_id
33
31
  from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
@@ -61,7 +59,7 @@ from streamlit.runtime.state import (
61
59
  from streamlit.type_util import check_python_comparable
62
60
 
63
61
  if TYPE_CHECKING:
64
- from collections.abc import Sequence
62
+ from collections.abc import Callable, Sequence
65
63
 
66
64
  from streamlit.delta_generator import DeltaGenerator
67
65
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
@@ -264,6 +262,8 @@ class SelectSliderMixin:
264
262
  The current value of the slider widget. The return type will match
265
263
  the data type of the value parameter.
266
264
 
265
+ This contains copies of the selected options, not the originals.
266
+
267
267
  Examples
268
268
  --------
269
269
  >>> import streamlit as st
@@ -377,7 +377,10 @@ class SelectSliderMixin:
377
377
  element_id = compute_and_register_element_id(
378
378
  "select_slider",
379
379
  user_key=key,
380
- key_as_main_identity=False,
380
+ # Treat the provided key as the main identity; only include
381
+ # changes to the options (and implicitly their formatting) in the
382
+ # identity computation as those can invalidate the current value.
383
+ key_as_main_identity={"options", "format_func"},
381
384
  dg=self.dg,
382
385
  label=label,
383
386
  options=[str(format_func(option)) for option in opt],
@@ -17,7 +17,6 @@ from textwrap import dedent
17
17
  from typing import (
18
18
  TYPE_CHECKING,
19
19
  Any,
20
- Callable,
21
20
  Generic,
22
21
  Literal,
23
22
  TypeVar,
@@ -67,7 +66,7 @@ from streamlit.type_util import (
67
66
  )
68
67
 
69
68
  if TYPE_CHECKING:
70
- from collections.abc import Sequence
69
+ from collections.abc import Callable, Sequence
71
70
 
72
71
  from streamlit.delta_generator import DeltaGenerator
73
72
 
@@ -404,6 +403,8 @@ class SelectboxMixin:
404
403
  any
405
404
  The selected option or ``None`` if no option is selected.
406
405
 
406
+ This is a copy of the selected option, not the original.
407
+
407
408
  Examples
408
409
  --------
409
410
  **Example 1: Use a basic selectbox widget**
@@ -544,7 +545,9 @@ class SelectboxMixin:
544
545
  # Treat the provided key as the main identity. Only include
545
546
  # the options and accept_new_options in the identity computation
546
547
  # as those can invalidate the current selection.
547
- key_as_main_identity={"options", "accept_new_options", "format_func"},
548
+ # Changes to format_func also invalidate the current selection,
549
+ # but this is already handled via the `options` parameter below:
550
+ key_as_main_identity={"options", "accept_new_options"},
548
551
  dg=self.dg,
549
552
  label=label,
550
553
  options=formatted_options,