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
@@ -0,0 +1,53 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import io
18
+
19
+
20
+ def convert_data_to_bytes_and_infer_mime(
21
+ data: object, unsupported_error: Exception
22
+ ) -> tuple[bytes, str]:
23
+ # Convert data to bytes and infer mimetype if needed
24
+ data_as_bytes: bytes
25
+ inferred_mime_type: str
26
+
27
+ if isinstance(data, str):
28
+ data_as_bytes = data.encode()
29
+ inferred_mime_type = "text/plain"
30
+ elif isinstance(data, io.TextIOWrapper):
31
+ string_data = data.read()
32
+ data_as_bytes = string_data.encode()
33
+ inferred_mime_type = "text/plain"
34
+ # Assume bytes; try methods until we run out.
35
+ elif isinstance(data, bytes):
36
+ data_as_bytes = data
37
+ inferred_mime_type = "application/octet-stream"
38
+ elif isinstance(data, io.BytesIO):
39
+ data.seek(0)
40
+ data_as_bytes = data.getvalue()
41
+ inferred_mime_type = "application/octet-stream"
42
+ elif isinstance(data, io.BufferedReader):
43
+ data.seek(0)
44
+ data_as_bytes = data.read()
45
+ inferred_mime_type = "application/octet-stream"
46
+ elif isinstance(data, io.RawIOBase):
47
+ data.seek(0)
48
+ data_as_bytes = data.read() or b""
49
+ inferred_mime_type = "application/octet-stream"
50
+ else:
51
+ raise unsupported_error
52
+
53
+ return data_as_bytes, inferred_mime_type
@@ -14,10 +14,13 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Callable
17
+ from typing import TYPE_CHECKING, Any
18
18
 
19
19
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
20
20
 
21
+ if TYPE_CHECKING:
22
+ from collections.abc import Callable
23
+
21
24
 
22
25
  class ForwardMsgQueue:
23
26
  """Accumulates a session's outgoing ForwardMsgs.
@@ -134,6 +137,7 @@ class ForwardMsgQueue:
134
137
  "script_finished",
135
138
  "session_status_changed",
136
139
  "parent_message",
140
+ "page_info_changed",
137
141
  }
138
142
  or (
139
143
  # preserve all messages if this is a fragment rerun and...
@@ -17,9 +17,10 @@ from __future__ import annotations
17
17
  import contextlib
18
18
  import inspect
19
19
  from abc import abstractmethod
20
+ from collections.abc import Callable
20
21
  from copy import deepcopy
21
22
  from functools import wraps
22
- from typing import TYPE_CHECKING, Any, Callable, Protocol, TypeVar, overload
23
+ from typing import TYPE_CHECKING, Any, Protocol, TypeVar, overload
23
24
 
24
25
  from streamlit.error_util import handle_uncaught_app_exception
25
26
  from streamlit.errors import FragmentHandledException, FragmentStorageKeyError
@@ -18,14 +18,33 @@ from __future__ import annotations
18
18
 
19
19
  import collections
20
20
  import threading
21
- from typing import Final
21
+ import uuid
22
+ from typing import TYPE_CHECKING, BinaryIO, Final, TextIO, TypedDict, cast
22
23
 
23
24
  from streamlit.logger import get_logger
24
- from streamlit.runtime.media_file_storage import MediaFileKind, MediaFileStorage
25
+ from streamlit.runtime.download_data_util import convert_data_to_bytes_and_infer_mime
26
+ from streamlit.runtime.media_file_storage import (
27
+ MediaFileKind,
28
+ MediaFileStorage,
29
+ MediaFileStorageError,
30
+ )
31
+
32
+ if TYPE_CHECKING:
33
+ import io
34
+ from collections.abc import Callable
25
35
 
26
36
  _LOGGER: Final = get_logger(__name__)
27
37
 
28
38
 
39
+ class DeferredCallableEntry(TypedDict):
40
+ """Typed metadata for deferred download callables."""
41
+
42
+ callable: Callable[[], bytes | str | BinaryIO | TextIO | io.RawIOBase]
43
+ mimetype: str | None
44
+ filename: str | None
45
+ coordinates: str
46
+
47
+
29
48
  def _get_session_id() -> str:
30
49
  """Get the active AppSession's session_id."""
31
50
  from streamlit.runtime.scriptrunner_utils.script_run_context import (
@@ -90,6 +109,10 @@ class MediaFileManager:
90
109
  collections.defaultdict(dict)
91
110
  )
92
111
 
112
+ # Dict of [file_id -> deferred callable metadata]
113
+ # Used for deferred download button execution
114
+ self._deferred_callables: dict[str, DeferredCallableEntry] = {}
115
+
93
116
  # MediaFileManager is used from multiple threads, so all operations
94
117
  # need to be protected with a Lock. (This is not an RLock, which
95
118
  # means taking it multiple times from the same thread will deadlock.)
@@ -129,6 +152,31 @@ class MediaFileManager:
129
152
  else:
130
153
  file.mark_for_delete()
131
154
 
155
+ # Clean up orphaned deferred callables
156
+ self._remove_orphaned_deferred_callables()
157
+
158
+ def _remove_orphaned_deferred_callables(self) -> None:
159
+ """Remove deferred callables that are not referenced by any active session.
160
+
161
+ Thread safety: callers must hold `self._lock`.
162
+ """
163
+ _LOGGER.debug("Removing orphaned deferred callables...")
164
+
165
+ # Get all file_ids currently referenced by any session
166
+ active_file_ids = set[str]()
167
+ for session_file_ids_by_coord in self._files_by_session_and_coord.values():
168
+ active_file_ids.update(session_file_ids_by_coord.values())
169
+
170
+ # Remove deferred callables that are no longer referenced
171
+ deferred_ids_to_remove = [
172
+ file_id
173
+ for file_id in self._deferred_callables
174
+ if file_id not in active_file_ids
175
+ ]
176
+ for file_id in deferred_ids_to_remove:
177
+ _LOGGER.debug("Removing deferred callable: %s", file_id)
178
+ del self._deferred_callables[file_id]
179
+
132
180
  def _delete_file(self, file_id: str) -> None:
133
181
  """Delete the given file from storage, and remove its metadata from
134
182
  self._files_by_id.
@@ -158,6 +206,10 @@ class MediaFileManager:
158
206
  if session_id in self._files_by_session_and_coord:
159
207
  del self._files_by_session_and_coord[session_id]
160
208
 
209
+ # Don't immediately delete deferred callables here to avoid race conditions.
210
+ # They will be cleaned up by remove_orphaned_deferred_callables() which
211
+ # only removes callables that are not referenced by ANY session.
212
+
161
213
  _LOGGER.debug(
162
214
  "Sessions still active: %r", self._files_by_session_and_coord.keys()
163
215
  )
@@ -231,3 +283,127 @@ class MediaFileManager:
231
283
  self._files_by_session_and_coord[session_id][coordinates] = file_id
232
284
 
233
285
  return self._storage.get_url(file_id)
286
+
287
+ def add_deferred(
288
+ self,
289
+ data_callable: Callable[[], bytes | str | BinaryIO | TextIO | io.RawIOBase],
290
+ mimetype: str | None,
291
+ coordinates: str,
292
+ file_name: str | None = None,
293
+ ) -> str:
294
+ """Register a callable for deferred execution. Returns placeholder file_id.
295
+
296
+ The callable will be executed later when execute_deferred() is called,
297
+ typically when the user clicks a download button.
298
+
299
+ Safe to call from any thread.
300
+
301
+ Parameters
302
+ ----------
303
+ data_callable : Callable[[], bytes | str | BinaryIO | TextIO | io.RawIOBase]
304
+ A callable that returns the file data when invoked.
305
+ mimetype : str or None
306
+ The mime type for the file. E.g. "text/csv".
307
+ If None, the mimetype will be inferred from the data type when
308
+ execute_deferred() is called.
309
+ coordinates : str
310
+ Unique string identifying an element's location.
311
+ file_name : str or None
312
+ Optional file_name. Used to set the filename in the response header.
313
+
314
+ Returns
315
+ -------
316
+ str
317
+ A placeholder file_id that can be used to execute the callable later.
318
+ """
319
+ session_id = _get_session_id()
320
+
321
+ with self._lock:
322
+ # Generate a unique placeholder ID for this deferred callable
323
+ # Expected: a new placeholder ID is created on every script rerun.
324
+ file_id = uuid.uuid4().hex
325
+
326
+ # Store the callable with its metadata
327
+ self._deferred_callables[file_id] = cast(
328
+ "DeferredCallableEntry",
329
+ {
330
+ "callable": data_callable,
331
+ "mimetype": mimetype,
332
+ "filename": file_name,
333
+ "coordinates": coordinates,
334
+ },
335
+ )
336
+
337
+ # Track this deferred file by session and coordinate
338
+ self._files_by_session_and_coord[session_id][coordinates] = file_id
339
+
340
+ return file_id
341
+
342
+ def execute_deferred(self, file_id: str) -> str:
343
+ """Execute a deferred callable and return the URL to the generated file.
344
+
345
+ This method retrieves the callable registered with add_deferred(),
346
+ executes it, stores the result, and returns a URL to access it.
347
+
348
+ Safe to call from any thread.
349
+
350
+ Parameters
351
+ ----------
352
+ file_id : str
353
+ The placeholder file_id returned by add_deferred().
354
+
355
+ Returns
356
+ -------
357
+ str
358
+ The URL that can be used to download the generated file.
359
+
360
+ Raises
361
+ ------
362
+ MediaFileStorageError
363
+ If the file_id is not found or if the callable execution fails.
364
+ """
365
+ # Retrieve deferred callable metadata while holding lock
366
+ with self._lock:
367
+ if file_id not in self._deferred_callables:
368
+ raise MediaFileStorageError(f"Deferred file {file_id} not found")
369
+
370
+ deferred = self._deferred_callables[file_id]
371
+
372
+ # Execute callable outside lock to avoid blocking other operations
373
+ try:
374
+ data = deferred["callable"]()
375
+ except Exception as e:
376
+ raise MediaFileStorageError(f"Callable execution failed: {e}") from e
377
+
378
+ # Convert data to bytes and infer mimetype if needed
379
+ data_as_bytes, inferred_mime_type = convert_data_to_bytes_and_infer_mime(
380
+ data,
381
+ unsupported_error=MediaFileStorageError(
382
+ f"Callable returned unsupported type: {type(data)}"
383
+ ),
384
+ )
385
+
386
+ # Use provided mimetype if available, otherwise use inferred mimetype
387
+ mime_type: str = deferred["mimetype"] or inferred_mime_type
388
+
389
+ # Store the generated data and get the actual file_id
390
+ with self._lock:
391
+ actual_file_id = self._storage.load_and_get_id(
392
+ data_as_bytes,
393
+ mime_type,
394
+ MediaFileKind.DOWNLOADABLE,
395
+ deferred["filename"],
396
+ )
397
+
398
+ # Create metadata for the actual file
399
+ metadata = MediaFileMetadata(kind=MediaFileKind.DOWNLOADABLE)
400
+ self._file_metadata[actual_file_id] = metadata
401
+
402
+ # Keep the deferred callable so users can download multiple times
403
+ # It will be cleaned up when clear_session_refs() is called on rerun
404
+
405
+ # We leave actual_file_id unmapped so repeat clicks rerun the callable.
406
+ # Cleanup prunes the stored file once no session references it.
407
+
408
+ # Return the URL to access the file
409
+ return self._storage.get_url(actual_file_id)
@@ -34,7 +34,7 @@ _LOGGER: Final = get_logger(__name__)
34
34
 
35
35
  # Mimetype -> filename extension map for the `get_extension_for_mimetype`
36
36
  # function. We use Python's `mimetypes.guess_extension` for most mimetypes,
37
- # but (as of Python 3.9) `mimetypes.guess_extension("audio/wav")` returns None,
37
+ # but (as of Python 3.12) `mimetypes.guess_extension("audio/wav")` returns None,
38
38
  # so we handle it ourselves.
39
39
  PREFERRED_MIMETYPE_EXTENSION_MAP: Final = {
40
40
  "audio/wav": ".wav",
@@ -21,9 +21,9 @@ import sys
21
21
  import threading
22
22
  import time
23
23
  import uuid
24
- from collections.abc import Sized
24
+ from collections.abc import Callable, Sized
25
25
  from functools import wraps
26
- from typing import Any, Callable, Final, TypeVar, cast, overload
26
+ from typing import Any, Final, TypeVar, cast, overload
27
27
 
28
28
  from streamlit import config, file_util, util
29
29
  from streamlit.logger import get_logger
@@ -78,6 +78,7 @@ _ATTRIBUTIONS_TO_CHECK: Final = [
78
78
  "duckdb",
79
79
  "opensearchpy",
80
80
  "supabase",
81
+ "databricks",
81
82
  # Dataframe Libraries:
82
83
  "polars",
83
84
  "dask",
@@ -92,6 +93,7 @@ _ATTRIBUTIONS_TO_CHECK: Final = [
92
93
  "tables",
93
94
  "zarr",
94
95
  "datasets",
96
+ "daft",
95
97
  # ML & LLM Tools:
96
98
  "mistralai",
97
99
  "openai",
@@ -131,11 +133,62 @@ _ATTRIBUTIONS_TO_CHECK: Final = [
131
133
  "lightgbm",
132
134
  "catboost",
133
135
  "sklearn",
136
+ "pydantic_ai",
137
+ "datachain",
138
+ "docling",
139
+ "litserve",
140
+ "crawl4ai",
141
+ "baml_client",
142
+ "browser_use",
143
+ "crewai",
144
+ "unsloth",
145
+ "langgraph",
146
+ "dspy",
147
+ "ultralytics",
148
+ "instructor",
149
+ "ragas",
150
+ "swarm",
151
+ "faster_whisper",
152
+ "memori",
153
+ "autogen_agentchat",
154
+ "xai_sdk",
155
+ "agno",
156
+ "langfuse",
157
+ "smolagents",
158
+ "ollama",
159
+ "groq",
160
+ "together",
161
+ "ai21",
162
+ "marvin",
163
+ "outlines",
164
+ "guardrails",
165
+ "promptflow",
166
+ "semantic_router",
167
+ "mem0",
168
+ "aisuite",
169
+ "mlflow",
170
+ "optuna",
171
+ "keras",
172
+ "jax",
173
+ "shap",
174
+ "evidently",
175
+ "great_expectations",
176
+ "bentoml",
177
+ "modal",
178
+ "sagemaker",
179
+ "vertexai",
180
+ "tiktoken",
181
+ "sentence_transformers",
182
+ "spacy",
183
+ "nltk",
184
+ "onnxruntime",
185
+ "llama_api_client",
134
186
  # Workflow Tools:
135
187
  "prefect",
136
188
  "luigi",
137
189
  "airflow",
138
190
  "dagster",
191
+ "celery",
139
192
  # Vector Stores:
140
193
  "pgvector",
141
194
  "faiss",
@@ -148,11 +201,40 @@ _ATTRIBUTIONS_TO_CHECK: Final = [
148
201
  "lancedb",
149
202
  # Others:
150
203
  "snowflake",
204
+ "pydantic",
205
+ "fastapi",
206
+ "starlette",
207
+ "playwright",
208
+ "folium",
209
+ "geopandas",
210
+ "httpx",
211
+ "pyecharts",
212
+ "fastplotlib",
213
+ "pygfx",
214
+ "highcharts_core",
215
+ # Optional streamlit dependencies:
216
+ "seaborn",
217
+ "graphviz",
218
+ "matplotlib",
219
+ "uvloop",
220
+ "orjson",
221
+ "rich",
151
222
  "streamlit_extras",
152
223
  "streamlit_pydantic",
153
- "pydantic",
224
+ "pygwalker",
225
+ "plotly",
226
+ "bokeh",
154
227
  "plost",
155
228
  "authlib",
229
+ # Document Processing:
230
+ "pypdf",
231
+ "pdfplumber",
232
+ "docx",
233
+ "openpyxl",
234
+ "xlsxwriter",
235
+ # Image/Vision:
236
+ "cv2",
237
+ "mediapipe",
156
238
  ]
157
239
 
158
240
  _ETC_MACHINE_ID_PATH = "/etc/machine-id"
@@ -331,6 +413,12 @@ def _get_command_telemetry(
331
413
  ):
332
414
  name = f"component:{self_arg.name}"
333
415
 
416
+ if name == "_bidi_component" and len(args) > 1 and isinstance(args[1], str):
417
+ # Bound DeltaGenerator methods always receive `self` as args[0], so args[1]
418
+ # is the user-supplied component name.
419
+ component_name = args[1]
420
+ name = f"component_v2:{component_name}"
421
+
334
422
  return Command(name=name, args=arguments)
335
423
 
336
424
 
@@ -23,6 +23,7 @@ from enum import Enum
23
23
  from typing import TYPE_CHECKING, Final, NamedTuple
24
24
 
25
25
  from streamlit.components.lib.local_component_registry import LocalComponentRegistry
26
+ from streamlit.components.v2.component_manager import BidiComponentManager
26
27
  from streamlit.logger import get_logger
27
28
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
28
29
  from streamlit.runtime.app_session import AppSession
@@ -101,6 +102,11 @@ class RuntimeConfig:
101
102
  default_factory=LocalComponentRegistry
102
103
  )
103
104
 
105
+ # The BidiComponentManager instance to use for v2 components.
106
+ bidi_component_registry: BidiComponentManager = field(
107
+ default_factory=BidiComponentManager
108
+ )
109
+
104
110
  # The SessionManager class to be used.
105
111
  session_manager_class: type[SessionManager] = WebsocketSessionManager
106
112
 
@@ -201,11 +207,15 @@ class Runtime:
201
207
 
202
208
  # Initialize managers
203
209
  self._component_registry = config.component_registry
210
+ self._bidi_component_registry = config.bidi_component_registry
204
211
  self._uploaded_file_mgr = config.uploaded_file_manager
205
212
  self._media_file_mgr = MediaFileManager(storage=config.media_file_storage)
206
213
  self._cache_storage_manager = config.cache_storage_manager
207
214
  self._script_cache = ScriptCache()
208
215
 
216
+ # Discover and register components for CCv2 from installed packages
217
+ self._bidi_component_registry.discover_and_register_components()
218
+
209
219
  self._session_mgr = config.session_manager_class(
210
220
  session_storage=config.session_storage,
211
221
  uploaded_file_manager=self._uploaded_file_mgr,
@@ -227,6 +237,10 @@ class Runtime:
227
237
  def component_registry(self) -> BaseComponentRegistry:
228
238
  return self._component_registry
229
239
 
240
+ @property
241
+ def bidi_component_registry(self) -> BidiComponentManager:
242
+ return self._bidi_component_registry
243
+
230
244
  @property
231
245
  def uploaded_file_mgr(self) -> UploadedFileManager:
232
246
  return self._uploaded_file_mgr
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import sys
18
- from typing import TYPE_CHECKING, Any, Callable, Literal
18
+ from typing import TYPE_CHECKING, Any, Literal
19
19
 
20
20
  from streamlit import util
21
21
  from streamlit.delta_generator_singletons import (
@@ -30,6 +30,7 @@ from streamlit.runtime.scriptrunner_utils.exceptions import (
30
30
  )
31
31
 
32
32
  if TYPE_CHECKING:
33
+ from collections.abc import Callable
33
34
  from types import TracebackType
34
35
 
35
36
  from streamlit.runtime.scriptrunner_utils.script_requests import RerunData
@@ -21,7 +21,7 @@ import types
21
21
  from contextlib import contextmanager
22
22
  from enum import Enum
23
23
  from timeit import default_timer as timer
24
- from typing import TYPE_CHECKING, Any, Callable, Final, Literal, cast
24
+ from typing import TYPE_CHECKING, Any, Final, Literal, cast
25
25
 
26
26
  from blinker import Signal
27
27
 
@@ -62,7 +62,7 @@ from streamlit.runtime.state import (
62
62
  from streamlit.source_util import page_sort_key
63
63
 
64
64
  if TYPE_CHECKING:
65
- from collections.abc import Generator
65
+ from collections.abc import Callable, Generator
66
66
 
67
67
  from streamlit.runtime.fragment import FragmentStorage
68
68
  from streamlit.runtime.scriptrunner.script_cache import ScriptCache
@@ -529,7 +529,9 @@ class ScriptRunner:
529
529
  widget_ids = {w.id for w in rerun_data.widget_states.widgets}
530
530
  self._session_state.on_script_finished(widget_ids)
531
531
 
532
- fragment_ids_this_run = list(rerun_data.fragment_id_queue)
532
+ fragment_ids_this_run: list[str] | None = (
533
+ rerun_data.fragment_id_queue or None
534
+ )
533
535
 
534
536
  ctx.reset(
535
537
  query_string=rerun_data.query_string,
@@ -22,14 +22,11 @@ from collections import Counter
22
22
  from dataclasses import dataclass, field
23
23
  from typing import (
24
24
  TYPE_CHECKING,
25
- Callable,
26
25
  Final,
27
- Union,
26
+ TypeAlias,
28
27
  )
29
28
  from urllib import parse
30
29
 
31
- from typing_extensions import TypeAlias
32
-
33
30
  from streamlit.errors import (
34
31
  NoSessionContext,
35
32
  StreamlitAPIException,
@@ -41,7 +38,7 @@ from streamlit.runtime.forward_msg_cache import (
41
38
  )
42
39
 
43
40
  if TYPE_CHECKING:
44
- from collections.abc import Generator
41
+ from collections.abc import Callable, Generator
45
42
  from pathlib import Path
46
43
 
47
44
  from streamlit.cursor import RunningCursor
@@ -55,7 +52,7 @@ if TYPE_CHECKING:
55
52
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
56
53
  _LOGGER: Final = get_logger(__name__)
57
54
 
58
- UserInfo: TypeAlias = dict[str, Union[str, bool, None]]
55
+ UserInfo: TypeAlias = dict[str, str | bool | None]
59
56
 
60
57
 
61
58
  # If true, it indicates that we are in a cached function that disallows the usage of
@@ -16,11 +16,10 @@ from __future__ import annotations
16
16
 
17
17
  import os
18
18
  import threading
19
- from collections.abc import ItemsView, Iterator, KeysView, Mapping, ValuesView
19
+ from collections.abc import Callable, ItemsView, Iterator, KeysView, Mapping, ValuesView
20
20
  from copy import deepcopy
21
21
  from typing import (
22
22
  Any,
23
- Callable,
24
23
  Final,
25
24
  NoReturn,
26
25
  )
@@ -461,8 +460,7 @@ class Secrets(Mapping[str, Any]):
461
460
  return value
462
461
  return AttrDict(value)
463
462
  # We add FileNotFoundError since __getattr__ is expected to only raise
464
- # AttributeError. Without handling FileNotFoundError, unittests.mocks
465
- # fails during mock creation on Python3.9
463
+ # AttributeError and mocking utilities expect that contract.
466
464
  except (KeyError, FileNotFoundError):
467
465
  raise AttributeError(_missing_attr_error_message(key))
468
466
 
@@ -16,9 +16,11 @@ from __future__ import annotations
16
16
 
17
17
  from abc import abstractmethod
18
18
  from dataclasses import dataclass
19
- from typing import TYPE_CHECKING, Callable, Protocol, cast
19
+ from typing import TYPE_CHECKING, Protocol, cast
20
20
 
21
21
  if TYPE_CHECKING:
22
+ from collections.abc import Callable
23
+
22
24
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
23
25
  from streamlit.runtime.app_session import AppSession
24
26
  from streamlit.runtime.script_data import ScriptData