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
@@ -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, Union, cast
20
-
21
- from typing_extensions import TypeAlias
19
+ from typing import TYPE_CHECKING, TypeAlias, cast
22
20
 
23
21
  from streamlit.elements.lib.file_uploader_utils import enforce_filename_restriction
24
22
  from streamlit.elements.lib.form_utils import current_form_id
@@ -53,7 +51,7 @@ if TYPE_CHECKING:
53
51
  from streamlit.delta_generator import DeltaGenerator
54
52
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
55
53
 
56
- SomeUploadedAudioFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
54
+ SomeUploadedAudioFile: TypeAlias = UploadedFile | DeletedFile | None
57
55
 
58
56
  # Allowed sample rates for audio recording
59
57
  ALLOWED_SAMPLE_RATES = {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}
@@ -131,13 +129,14 @@ class AudioInputMixin:
131
129
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
132
130
 
133
131
  sample_rate : int or None
134
- The target sample rate for the audio recording in Hz.
135
- This defaults to 16000 Hz, which is optimal for speech recognition.
132
+ The target sample rate for the audio recording in Hz. This
133
+ defaults to ``16000``, which is optimal for speech recognition.
136
134
 
137
- The following sample rates are supported: 8000, 11025, 16000,
138
- 22050, 24000, 32000, 44100, or 48000. If this is ``None``, the
139
- widget uses the browser's default sample rate (typically 44100 or
140
- 48000 Hz).
135
+ The following values are supported: ``8000`` (telephone quality),
136
+ ``11025``, ``16000`` (speech-recognition quality), ``22050``,
137
+ ``24000``, ``32000``, ``44100``, ``48000`` (high-quality), or
138
+ ``None``. If this is ``None``, the widget uses the browser's
139
+ default sample rate (typically 44100 or 48000 Hz).
141
140
 
142
141
  key : str or int
143
142
  An optional string or integer to use as the unique key for the widget.
@@ -282,11 +281,13 @@ class AudioInputMixin:
282
281
  element_id = compute_and_register_element_id(
283
282
  "audio_input",
284
283
  user_key=key,
285
- key_as_main_identity=False,
284
+ # Treat the provided key as the main identity.
285
+ key_as_main_identity=True,
286
286
  dg=self.dg,
287
287
  label=label,
288
288
  help=help,
289
289
  width=width,
290
+ sample_rate=sample_rate,
290
291
  )
291
292
 
292
293
  audio_input_proto = AudioInputProto()
@@ -16,6 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import io
18
18
  import os
19
+ from collections.abc import Callable
19
20
  from dataclasses import dataclass
20
21
  from pathlib import Path
21
22
  from textwrap import dedent
@@ -25,16 +26,15 @@ from typing import (
25
26
  Final,
26
27
  Literal,
27
28
  TextIO,
28
- Union,
29
+ TypeAlias,
29
30
  cast,
30
31
  )
31
32
 
32
- from typing_extensions import TypeAlias
33
-
34
33
  from streamlit import runtime
35
34
  from streamlit.elements.lib.form_utils import current_form_id, is_in_form
36
35
  from streamlit.elements.lib.layout_utils import LayoutConfig, Width, validate_width
37
36
  from streamlit.elements.lib.policies import check_widget_policies
37
+ from streamlit.elements.lib.shortcut_utils import normalize_shortcut
38
38
  from streamlit.elements.lib.utils import (
39
39
  Key,
40
40
  compute_and_register_element_id,
@@ -52,6 +52,7 @@ from streamlit.proto.Button_pb2 import Button as ButtonProto
52
52
  from streamlit.proto.DownloadButton_pb2 import DownloadButton as DownloadButtonProto
53
53
  from streamlit.proto.LinkButton_pb2 import LinkButton as LinkButtonProto
54
54
  from streamlit.proto.PageLink_pb2 import PageLink as PageLinkProto
55
+ from streamlit.runtime.download_data_util import convert_data_to_bytes_and_infer_mime
55
56
  from streamlit.runtime.metrics_util import gather_metrics
56
57
  from streamlit.runtime.pages_manager import PagesManager
57
58
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
@@ -61,12 +62,14 @@ from streamlit.runtime.state import (
61
62
  WidgetKwargs,
62
63
  register_widget,
63
64
  )
65
+ from streamlit.runtime.state.query_params import process_query_params
64
66
  from streamlit.string_util import validate_icon_or_emoji
65
67
  from streamlit.url_util import is_url
66
68
  from streamlit.util import in_sidebar
67
69
 
68
70
  if TYPE_CHECKING:
69
71
  from streamlit.delta_generator import DeltaGenerator
72
+ from streamlit.runtime.state.query_params import QueryParamsInput
70
73
 
71
74
  FORM_DOCS_INFO: Final = """
72
75
 
@@ -74,7 +77,14 @@ For more information, refer to the
74
77
  [documentation for forms](https://docs.streamlit.io/develop/api-reference/execution-flow/st.form).
75
78
  """
76
79
 
77
- DownloadButtonDataType: TypeAlias = Union[str, bytes, TextIO, BinaryIO, io.RawIOBase]
80
+ DownloadButtonDataType: TypeAlias = (
81
+ str
82
+ | bytes
83
+ | TextIO
84
+ | BinaryIO
85
+ | io.RawIOBase
86
+ | Callable[[], str | bytes | TextIO | BinaryIO | io.RawIOBase]
87
+ )
78
88
 
79
89
 
80
90
  @dataclass
@@ -102,6 +112,7 @@ class ButtonMixin:
102
112
  disabled: bool = False,
103
113
  use_container_width: bool | None = None,
104
114
  width: Width = "content",
115
+ shortcut: str | None = None,
105
116
  ) -> bool:
106
117
  r"""Display a button widget.
107
118
 
@@ -175,6 +186,8 @@ class ButtonMixin:
175
186
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
176
187
  font library.
177
188
 
189
+ - ``"spinner"``: Displays a spinner as an icon.
190
+
178
191
  disabled : bool
179
192
  An optional boolean that disables the button if set to ``True``.
180
193
  The default is ``False``.
@@ -207,6 +220,33 @@ class ButtonMixin:
207
220
  the parent container, the width of the button matches the width
208
221
  of the parent container.
209
222
 
223
+ shortcut : str or None
224
+ An optional keyboard shortcut that triggers the button. This can be
225
+ one of the following strings:
226
+
227
+ - A single alphanumeric key like ``"K"`` or ``"4"``.
228
+ - A function key like ``"F11"``.
229
+ - A special key like ``"Enter"``, ``"Esc"``, or ``"Tab"``.
230
+ - Any of the above combined with modifiers. For example, you can use
231
+ ``"Ctrl+K"`` or ``"Cmd+Shift+O"``.
232
+
233
+ .. important::
234
+ The keys ``"C"`` and ``"R"`` are reserved and can't be used,
235
+ even with modifiers. Punctuation keys like ``"."`` and ``","``
236
+ aren't currently supported.
237
+
238
+ The following special keys are supported: Backspace, Delete, Down,
239
+ End, Enter, Esc, Home, Left, PageDown, PageUp, Right, Space, Tab,
240
+ and Up.
241
+
242
+ The following modifiers are supported: Alt, Ctrl, Cmd, Meta, Mod,
243
+ Option, Shift.
244
+
245
+ - Ctrl, Cmd, Meta, and Mod are interchangeable and will display to
246
+ the user to match their platform.
247
+ - Option and Alt are interchangeable and will display to the user
248
+ to match their platform.
249
+
210
250
  Returns
211
251
  -------
212
252
  bool
@@ -251,6 +291,25 @@ class ButtonMixin:
251
291
  https://doc-button-icons.streamlit.app/
252
292
  height: 220px
253
293
 
294
+ **Example 3: Use keyboard shortcuts**
295
+
296
+ The following example shows how to use keyboard shortcuts to trigger a
297
+ button. If you use any of the platform-dependent modifiers (Ctrl, Cmd,
298
+ or Mod), they are interpreted interchangeably and always displayed to
299
+ the user to match their platform.
300
+
301
+ >>> import streamlit as st
302
+ >>>
303
+ >>> with st.container(horizontal=True, horizontal_alignment="distribute"):
304
+ >>> "`A`" if st.button("A", shortcut="A") else "` `"
305
+ >>> "`S`" if st.button("S", shortcut="Ctrl+S") else "` `"
306
+ >>> "`D`" if st.button("D", shortcut="Cmd+Shift+D") else "` `"
307
+ >>> "`F`" if st.button("F", shortcut="Mod+Alt+Shift+F") else "` `"
308
+
309
+ .. output::
310
+ https://doc-button-shortcuts.streamlit.app/
311
+ height: 220px
312
+
254
313
  """
255
314
  key = to_key(key)
256
315
  ctx = get_script_run_ctx()
@@ -278,6 +337,7 @@ class ButtonMixin:
278
337
  icon=icon,
279
338
  ctx=ctx,
280
339
  width=width,
340
+ shortcut=shortcut,
281
341
  )
282
342
 
283
343
  @gather_metrics("download_button")
@@ -298,15 +358,18 @@ class ButtonMixin:
298
358
  disabled: bool = False,
299
359
  use_container_width: bool | None = None,
300
360
  width: Width = "content",
361
+ shortcut: str | None = None,
301
362
  ) -> bool:
302
363
  r"""Display a download button widget.
303
364
 
304
365
  This is useful when you would like to provide a way for your users
305
366
  to download a file directly from your app.
306
367
 
307
- Note that the data to be downloaded is stored in-memory while the
308
- user is connected, so it's a good idea to keep file sizes under a
309
- couple hundred megabytes to conserve memory.
368
+ If you pass the data directly to the ``data`` parameter, then the data
369
+ is stored in-memory while the user is connected. It's a good idea to
370
+ keep file sizes under a couple hundred megabytes to conserve memory or
371
+ use deferred data generation by passing a callable to the ``data``
372
+ parameter.
310
373
 
311
374
  If you want to prevent your app from rerunning when a user clicks the
312
375
  download button, wrap the download button in a `fragment
@@ -332,10 +395,22 @@ class ButtonMixin:
332
395
  .. |st.markdown| replace:: ``st.markdown``
333
396
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
334
397
 
335
- data : str, bytes, or file
336
- The contents of the file to be downloaded.
398
+ data : str, bytes, file-like, or callable
399
+ The contents of the file to be downloaded or a callable that
400
+ returns the contents of the file.
401
+
402
+ File contents can be a string, bytes, or file-like object.
403
+ File-like objects include ``io.BytesIO``, ``io.StringIO``, or any
404
+ class that implements the abstract base class ``io.RawIOBase``.
337
405
 
338
- To prevent unncecessary recomputation, use caching when converting
406
+ If a callable is passed, it is executed when the user clicks
407
+ the download button and runs on a separate thread from the
408
+ resulting script rerun. This deferred generation is helpful for
409
+ large files to avoid blocking the page script. The callable can't
410
+ accept any arguments. If any Streamlit commands are executed inside
411
+ the callable, they will be ignored.
412
+
413
+ To prevent unnecessary recomputation, use caching when converting
339
414
  your data for download. For more information, see the Example 1
340
415
  below.
341
416
 
@@ -419,6 +494,8 @@ class ButtonMixin:
419
494
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
420
495
  font library.
421
496
 
497
+ - ``"spinner"``: Displays a spinner as an icon.
498
+
422
499
  disabled : bool
423
500
  An optional boolean that disables the download button if set to
424
501
  ``True``. The default is ``False``.
@@ -451,6 +528,27 @@ class ButtonMixin:
451
528
  the parent container, the width of the button matches the width
452
529
  of the parent container.
453
530
 
531
+ shortcut : str or None
532
+ An optional keyboard shortcut that triggers the button. This can be
533
+ one of the following strings:
534
+
535
+ - A single alphanumeric key like ``"K"`` or ``"4"``.
536
+ - A function key like ``"F11"``.
537
+ - A special key like ``"Enter"``, ``"Esc"``, or ``"Tab"``.
538
+ - Any of the above combined with modifiers. For example, you can use
539
+ ``"Ctrl+K"`` or ``"Cmd+Shift+O"``.
540
+
541
+ .. important::
542
+ The keys ``"C"`` and ``"R"`` are reserved and can't be used,
543
+ even with modifiers. Punctuation keys like ``"."`` and ``","``
544
+ aren't currently supported.
545
+
546
+ For a list of supported keys and modifiers, see the documentation
547
+ for |st.button|_.
548
+
549
+ .. |st.button| replace:: ``st.button``
550
+ .. _st.button: https://docs.streamlit.io/develop/api-reference/widgets/st.button
551
+
454
552
  Returns
455
553
  -------
456
554
  bool
@@ -561,6 +659,31 @@ class ButtonMixin:
561
659
  https://doc-download-button-file.streamlit.app/
562
660
  height: 200px
563
661
 
662
+ **Example 4: Generate the data on-click with a callable**
663
+
664
+ Pass a callable to ``data`` to generate the bytes lazily when the user
665
+ clicks the button. Streamlit commands inside this callable are ignored.
666
+ The callable can't accept any arguments and must return a file-like
667
+ object.
668
+
669
+ >>> import streamlit as st
670
+ >>> import time
671
+ >>>
672
+ >>> def make_report():
673
+ >>> time.sleep(1)
674
+ >>> return "col1,col2\n1,2\n3,4".encode("utf-8")
675
+ >>>
676
+ >>> st.download_button(
677
+ ... label="Download report",
678
+ ... data=make_report,
679
+ ... file_name="report.csv",
680
+ ... mime="text/csv",
681
+ ... )
682
+
683
+ .. output::
684
+ https://doc-download-button-deferred.streamlit.app/
685
+ height: 200px
686
+
564
687
  """
565
688
  ctx = get_script_run_ctx()
566
689
 
@@ -588,6 +711,7 @@ class ButtonMixin:
588
711
  disabled=disabled,
589
712
  ctx=ctx,
590
713
  width=width,
714
+ shortcut=shortcut,
591
715
  )
592
716
 
593
717
  @gather_metrics("link_button")
@@ -602,6 +726,7 @@ class ButtonMixin:
602
726
  disabled: bool = False,
603
727
  use_container_width: bool | None = None,
604
728
  width: Width = "content",
729
+ shortcut: str | None = None,
605
730
  ) -> DeltaGenerator:
606
731
  r"""Display a link button element.
607
732
 
@@ -667,6 +792,8 @@ class ButtonMixin:
667
792
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
668
793
  font library.
669
794
 
795
+ - ``"spinner"``: Displays a spinner as an icon.
796
+
670
797
  disabled : bool
671
798
  An optional boolean that disables the link button if set to
672
799
  ``True``. The default is ``False``.
@@ -699,6 +826,27 @@ class ButtonMixin:
699
826
  the parent container, the width of the button matches the width
700
827
  of the parent container.
701
828
 
829
+ shortcut : str or None
830
+ An optional keyboard shortcut that triggers the button. This can be
831
+ one of the following strings:
832
+
833
+ - A single alphanumeric key like ``"K"`` or ``"4"``.
834
+ - A function key like ``"F11"``.
835
+ - A special key like ``"Enter"``, ``"Esc"``, or ``"Tab"``.
836
+ - Any of the above combined with modifiers. For example, you can use
837
+ ``"Ctrl+K"`` or ``"Cmd+Shift+O"``.
838
+
839
+ .. important::
840
+ The keys ``"C"`` and ``"R"`` are reserved and can't be used,
841
+ even with modifiers. Punctuation keys like ``"."`` and ``","``
842
+ aren't currently supported.
843
+
844
+ For a list of supported keys and modifiers, see the documentation
845
+ for |st.button|_.
846
+
847
+ .. |st.button| replace:: ``st.button``
848
+ .. _st.button: https://docs.streamlit.io/develop/api-reference/widgets/st.button
849
+
702
850
  Example
703
851
  -------
704
852
  >>> import streamlit as st
@@ -728,6 +876,7 @@ class ButtonMixin:
728
876
  type=type,
729
877
  icon=icon,
730
878
  width=width,
879
+ shortcut=shortcut,
731
880
  )
732
881
 
733
882
  @gather_metrics("page_link")
@@ -741,6 +890,7 @@ class ButtonMixin:
741
890
  disabled: bool = False,
742
891
  use_container_width: bool | None = None,
743
892
  width: Width = "content",
893
+ query_params: QueryParamsInput | None = None,
744
894
  ) -> DeltaGenerator:
745
895
  r"""Display a link to another page in a multipage app or to an external page.
746
896
 
@@ -795,6 +945,8 @@ class ButtonMixin:
795
945
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
796
946
  font library.
797
947
 
948
+ - ``"spinner"``: Displays a spinner as an icon.
949
+
798
950
  help : str or None
799
951
  A tooltip that gets displayed when the link is hovered over. If
800
952
  this is ``None`` (default), no tooltip is displayed.
@@ -831,15 +983,27 @@ class ButtonMixin:
831
983
  the parent container, the width of the button matches the width
832
984
  of the parent container.
833
985
 
986
+ query_params : dict, list of tuples, or None
987
+ Query parameters to apply when navigating to the target page.
988
+ This can be a dictionary or an iterable of key-value tuples. Values can
989
+ be strings or iterables of strings (for repeated keys). When this is
990
+ ``None`` (default), all non-embed query parameters are cleared during
991
+ navigation.
992
+
834
993
  Example
835
994
  -------
836
- Consider the following example given this file structure:
995
+ **Example 1: Basic usage**
837
996
 
838
- >>> your-repository/
839
- >>> ├── pages/
840
- >>> │ ├── page_1.py
841
- >>> │ └── page_2.py
842
- >>> └── your_app.py
997
+ The following example shows how to create page links in a multipage app
998
+ that uses the ``pages/`` directory:
999
+
1000
+ .. code-block:: text
1001
+
1002
+ your-repository/
1003
+ ├── pages/
1004
+ │ ├── page_1.py
1005
+ │ └── page_2.py
1006
+ └── your_app.py
843
1007
 
844
1008
  >>> import streamlit as st
845
1009
  >>>
@@ -856,10 +1020,34 @@ class ButtonMixin:
856
1020
  .. |client.showSidebarNavigation| replace:: ``client.showSidebarNavigation``
857
1021
  .. _client.showSidebarNavigation: https://docs.streamlit.io/develop/api-reference/configuration/config.toml#client
858
1022
 
859
- .. output ::
1023
+ .. output::
860
1024
  https://doc-page-link.streamlit.app/
861
1025
  height: 350px
862
1026
 
1027
+ **Example 2: Passing query parameters**
1028
+
1029
+ The following example shows how to pass query parameters when creating a
1030
+ page link in a multipage app:
1031
+
1032
+ .. code-block:: text
1033
+
1034
+ your-repository/
1035
+ ├── page_2.py
1036
+ └── your_app.py
1037
+
1038
+ >>> import streamlit as st
1039
+ >>>
1040
+ >>> def page_1():
1041
+ >>> st.title("Page 1")
1042
+ >>> st.page_link("page_2.py", query_params={"utm_source": "page_1"})
1043
+ >>>
1044
+ >>> pg = st.navigation([page_1, "page_2.py"])
1045
+ >>> pg.run()
1046
+
1047
+ .. output::
1048
+ https://doc-page-link-query-params.streamlit.app/
1049
+ height: 350px
1050
+
863
1051
  """
864
1052
  if use_container_width is not None:
865
1053
  width = "stretch" if use_container_width else "content"
@@ -875,6 +1063,7 @@ class ButtonMixin:
875
1063
  help=help,
876
1064
  disabled=disabled,
877
1065
  width=width,
1066
+ query_params=query_params,
878
1067
  )
879
1068
 
880
1069
  def _download_button(
@@ -894,6 +1083,7 @@ class ButtonMixin:
894
1083
  disabled: bool = False,
895
1084
  ctx: ScriptRunContext | None = None,
896
1085
  width: Width = "content",
1086
+ shortcut: str | None = None,
897
1087
  ) -> bool:
898
1088
  key = to_key(key)
899
1089
 
@@ -903,6 +1093,10 @@ class ButtonMixin:
903
1093
  else cast("WidgetCallback", on_click)
904
1094
  )
905
1095
 
1096
+ normalized_shortcut: str | None = None
1097
+ if shortcut is not None:
1098
+ normalized_shortcut = normalize_shortcut(shortcut)
1099
+
906
1100
  check_widget_policies(
907
1101
  self.dg,
908
1102
  key,
@@ -923,6 +1117,7 @@ class ButtonMixin:
923
1117
  help=help,
924
1118
  type=type,
925
1119
  width=width,
1120
+ shortcut=normalized_shortcut,
926
1121
  )
927
1122
 
928
1123
  if is_in_form(self.dg):
@@ -951,6 +1146,9 @@ class ButtonMixin:
951
1146
  else:
952
1147
  download_button_proto.ignore_rerun = False
953
1148
 
1149
+ if normalized_shortcut is not None:
1150
+ download_button_proto.shortcut = normalized_shortcut
1151
+
954
1152
  serde = ButtonSerde()
955
1153
 
956
1154
  button_state = register_widget(
@@ -981,8 +1179,30 @@ class ButtonMixin:
981
1179
  icon: str | None = None,
982
1180
  disabled: bool = False,
983
1181
  width: Width = "content",
1182
+ shortcut: str | None = None,
984
1183
  ) -> DeltaGenerator:
985
1184
  link_button_proto = LinkButtonProto()
1185
+ normalized_shortcut: str | None = None
1186
+ if shortcut is not None:
1187
+ normalized_shortcut = normalize_shortcut(shortcut)
1188
+
1189
+ if normalized_shortcut is not None:
1190
+ # We only register the element ID if a shortcut is provide.
1191
+ # The ID is required to correctly register and handle the shortcut
1192
+ # on the client side.
1193
+ link_button_proto.id = compute_and_register_element_id(
1194
+ "link_button",
1195
+ user_key=None,
1196
+ key_as_main_identity=False,
1197
+ dg=self.dg,
1198
+ label=label,
1199
+ icon=icon,
1200
+ url=url,
1201
+ help=help,
1202
+ type=type,
1203
+ width=width,
1204
+ shortcut=normalized_shortcut,
1205
+ )
986
1206
  link_button_proto.label = label
987
1207
  link_button_proto.url = url
988
1208
  link_button_proto.type = type
@@ -994,6 +1214,9 @@ class ButtonMixin:
994
1214
  if icon is not None:
995
1215
  link_button_proto.icon = validate_icon_or_emoji(icon)
996
1216
 
1217
+ if normalized_shortcut is not None:
1218
+ link_button_proto.shortcut = normalized_shortcut
1219
+
997
1220
  validate_width(width, allow_content=True)
998
1221
  layout_config = LayoutConfig(width=width)
999
1222
  return self.dg._enqueue(
@@ -1009,8 +1232,12 @@ class ButtonMixin:
1009
1232
  help: str | None = None,
1010
1233
  disabled: bool = False,
1011
1234
  width: Width = "content",
1235
+ query_params: QueryParamsInput | None = None,
1012
1236
  ) -> DeltaGenerator:
1013
1237
  page_link_proto = PageLinkProto()
1238
+ if query_params:
1239
+ page_link_proto.query_string = process_query_params(query_params)
1240
+
1014
1241
  validate_width(width, allow_content=True)
1015
1242
 
1016
1243
  ctx = get_script_run_ctx()
@@ -1105,9 +1332,14 @@ class ButtonMixin:
1105
1332
  disabled: bool = False,
1106
1333
  ctx: ScriptRunContext | None = None,
1107
1334
  width: Width = "content",
1335
+ shortcut: str | None = None,
1108
1336
  ) -> bool:
1109
1337
  key = to_key(key)
1110
1338
 
1339
+ normalized_shortcut: str | None = None
1340
+ if shortcut is not None:
1341
+ normalized_shortcut = normalize_shortcut(shortcut)
1342
+
1111
1343
  check_widget_policies(
1112
1344
  self.dg,
1113
1345
  key,
@@ -1130,6 +1362,7 @@ class ButtonMixin:
1130
1362
  is_form_submitter=is_form_submitter,
1131
1363
  type=type,
1132
1364
  width=width,
1365
+ shortcut=normalized_shortcut,
1133
1366
  )
1134
1367
 
1135
1368
  # It doesn't make sense to create a button inside a form (except
@@ -1162,6 +1395,9 @@ class ButtonMixin:
1162
1395
  if icon is not None:
1163
1396
  button_proto.icon = validate_icon_or_emoji(icon)
1164
1397
 
1398
+ if normalized_shortcut is not None:
1399
+ button_proto.shortcut = normalized_shortcut
1400
+
1165
1401
  serde = ButtonSerde()
1166
1402
 
1167
1403
  button_state = register_widget(
@@ -1197,32 +1433,33 @@ def marshall_file(
1197
1433
  mimetype: str | None,
1198
1434
  file_name: str | None = None,
1199
1435
  ) -> None:
1200
- data_as_bytes: bytes
1201
- if isinstance(data, str):
1202
- data_as_bytes = data.encode()
1203
- mimetype = mimetype or "text/plain"
1204
- elif isinstance(data, io.TextIOWrapper):
1205
- string_data = data.read()
1206
- data_as_bytes = string_data.encode()
1207
- mimetype = mimetype or "text/plain"
1208
- # Assume bytes; try methods until we run out.
1209
- elif isinstance(data, bytes):
1210
- data_as_bytes = data
1211
- mimetype = mimetype or "application/octet-stream"
1212
- elif isinstance(data, io.BytesIO):
1213
- data.seek(0)
1214
- data_as_bytes = data.getvalue()
1215
- mimetype = mimetype or "application/octet-stream"
1216
- elif isinstance(data, io.BufferedReader):
1217
- data.seek(0)
1218
- data_as_bytes = data.read()
1219
- mimetype = mimetype or "application/octet-stream"
1220
- elif isinstance(data, io.RawIOBase):
1221
- data.seek(0)
1222
- data_as_bytes = data.read() or b""
1223
- mimetype = mimetype or "application/octet-stream"
1224
- else:
1225
- raise StreamlitAPIException(f"Invalid binary data format: {type(data)}")
1436
+ # Check if data is a callable (for deferred downloads)
1437
+ if callable(data):
1438
+ if not runtime.exists():
1439
+ # When running in "raw mode", we can't access the MediaFileManager.
1440
+ proto_download_button.url = ""
1441
+ return
1442
+
1443
+ # Register the callable for deferred execution
1444
+ file_id = runtime.get_instance().media_file_mgr.add_deferred(
1445
+ data,
1446
+ mimetype,
1447
+ coordinates,
1448
+ file_name=file_name,
1449
+ )
1450
+ proto_download_button.deferred_file_id = file_id
1451
+ proto_download_button.url = "" # No URL yet, will be generated on click
1452
+ return
1453
+
1454
+ # Existing logic for non-callable data
1455
+ data_as_bytes, inferred_mime_type = convert_data_to_bytes_and_infer_mime(
1456
+ data,
1457
+ unsupported_error=StreamlitAPIException(
1458
+ f"Invalid binary data format: {type(data)}"
1459
+ ),
1460
+ )
1461
+ if mimetype is None:
1462
+ mimetype = inferred_mime_type
1226
1463
 
1227
1464
  if runtime.exists():
1228
1465
  file_url = runtime.get_instance().media_file_mgr.add(