streamlit 1.45.1__py3-none-any.whl → 1.46.1__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 (335) hide show
  1. streamlit/__init__.py +5 -1
  2. streamlit/auth_util.py +12 -12
  3. streamlit/cli_util.py +4 -3
  4. streamlit/column_config.py +11 -9
  5. streamlit/commands/echo.py +6 -4
  6. streamlit/commands/execution_control.py +33 -32
  7. streamlit/commands/experimental_query_params.py +2 -2
  8. streamlit/commands/logo.py +9 -4
  9. streamlit/commands/navigation.py +61 -18
  10. streamlit/commands/page_config.py +57 -47
  11. streamlit/components/types/base_custom_component.py +7 -7
  12. streamlit/components/v1/component_registry.py +7 -3
  13. streamlit/components/v1/components.py +1 -1
  14. streamlit/components/v1/custom_component.py +8 -8
  15. streamlit/config.py +289 -144
  16. streamlit/config_option.py +19 -15
  17. streamlit/config_util.py +29 -23
  18. streamlit/connections/__init__.py +2 -2
  19. streamlit/connections/base_connection.py +5 -5
  20. streamlit/connections/snowflake_connection.py +13 -11
  21. streamlit/connections/snowpark_connection.py +3 -3
  22. streamlit/connections/sql_connection.py +20 -18
  23. streamlit/connections/util.py +2 -2
  24. streamlit/cursor.py +6 -6
  25. streamlit/dataframe_util.py +52 -52
  26. streamlit/delta_generator.py +46 -48
  27. streamlit/delta_generator_singletons.py +3 -3
  28. streamlit/deprecation_util.py +6 -6
  29. streamlit/elements/alert.py +37 -29
  30. streamlit/elements/arrow.py +40 -22
  31. streamlit/elements/code.py +46 -13
  32. streamlit/elements/deck_gl_json_chart.py +38 -27
  33. streamlit/elements/dialog_decorator.py +3 -4
  34. streamlit/elements/doc_string.py +64 -58
  35. streamlit/elements/exception.py +23 -27
  36. streamlit/elements/form.py +41 -0
  37. streamlit/elements/graphviz_chart.py +1 -1
  38. streamlit/elements/heading.py +60 -9
  39. streamlit/elements/html.py +3 -4
  40. streamlit/elements/image.py +8 -9
  41. streamlit/elements/json.py +21 -2
  42. streamlit/elements/layouts.py +120 -31
  43. streamlit/elements/lib/built_in_chart_utils.py +96 -73
  44. streamlit/elements/lib/color_util.py +3 -3
  45. streamlit/elements/lib/column_config_utils.py +2 -4
  46. streamlit/elements/lib/column_types.py +14 -8
  47. streamlit/elements/lib/dialog.py +9 -5
  48. streamlit/elements/lib/image_utils.py +39 -40
  49. streamlit/elements/lib/js_number.py +4 -4
  50. streamlit/elements/lib/layout_utils.py +65 -1
  51. streamlit/elements/lib/mutable_status_container.py +14 -3
  52. streamlit/elements/lib/options_selector_utils.py +22 -12
  53. streamlit/elements/lib/pandas_styler_utils.py +25 -21
  54. streamlit/elements/lib/policies.py +6 -5
  55. streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
  56. streamlit/elements/lib/subtitle_utils.py +6 -9
  57. streamlit/elements/lib/utils.py +20 -5
  58. streamlit/elements/map.py +32 -56
  59. streamlit/elements/markdown.py +101 -12
  60. streamlit/elements/media.py +78 -21
  61. streamlit/elements/metric.py +32 -16
  62. streamlit/elements/plotly_chart.py +15 -15
  63. streamlit/elements/progress.py +33 -15
  64. streamlit/elements/spinner.py +31 -6
  65. streamlit/elements/text.py +21 -1
  66. streamlit/elements/toast.py +1 -2
  67. streamlit/elements/vega_charts.py +54 -23
  68. streamlit/elements/widgets/audio_input.py +24 -7
  69. streamlit/elements/widgets/button.py +26 -19
  70. streamlit/elements/widgets/button_group.py +10 -15
  71. streamlit/elements/widgets/camera_input.py +27 -7
  72. streamlit/elements/widgets/chat.py +91 -38
  73. streamlit/elements/widgets/checkbox.py +45 -4
  74. streamlit/elements/widgets/color_picker.py +40 -17
  75. streamlit/elements/widgets/data_editor.py +76 -37
  76. streamlit/elements/widgets/file_uploader.py +42 -13
  77. streamlit/elements/widgets/multiselect.py +7 -10
  78. streamlit/elements/widgets/number_input.py +123 -47
  79. streamlit/elements/widgets/radio.py +59 -13
  80. streamlit/elements/widgets/select_slider.py +35 -30
  81. streamlit/elements/widgets/selectbox.py +56 -9
  82. streamlit/elements/widgets/slider.py +190 -99
  83. streamlit/elements/widgets/text_widgets.py +54 -8
  84. streamlit/elements/widgets/time_widgets.py +53 -14
  85. streamlit/elements/write.py +5 -8
  86. streamlit/env_util.py +2 -7
  87. streamlit/error_util.py +16 -9
  88. streamlit/errors.py +69 -48
  89. streamlit/external/langchain/streamlit_callback_handler.py +10 -5
  90. streamlit/file_util.py +27 -10
  91. streamlit/git_util.py +29 -24
  92. streamlit/hello/animation_demo.py +9 -9
  93. streamlit/hello/dataframe_demo.py +5 -5
  94. streamlit/hello/hello.py +1 -0
  95. streamlit/hello/mapping_demo.py +7 -8
  96. streamlit/hello/plotting_demo.py +3 -3
  97. streamlit/hello/streamlit_app.py +28 -26
  98. streamlit/hello/utils.py +2 -1
  99. streamlit/logger.py +10 -11
  100. streamlit/navigation/page.py +11 -8
  101. streamlit/proto/Audio_pb2.py +4 -3
  102. streamlit/proto/Audio_pb2.pyi +8 -1
  103. streamlit/proto/Block_pb2.py +38 -29
  104. streamlit/proto/Block_pb2.pyi +72 -4
  105. streamlit/proto/ClientState_pb2.py +4 -4
  106. streamlit/proto/ClientState_pb2.pyi +7 -2
  107. streamlit/proto/Code_pb2.py +4 -2
  108. streamlit/proto/Code_pb2.pyi +1 -0
  109. streamlit/proto/DataFrame_pb2.pyi +1 -1
  110. streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
  111. streamlit/proto/Element_pb2.py +5 -3
  112. streamlit/proto/Element_pb2.pyi +20 -3
  113. streamlit/proto/GapSize_pb2.py +29 -0
  114. streamlit/proto/GapSize_pb2.pyi +70 -0
  115. streamlit/proto/HeightConfig_pb2.py +27 -0
  116. streamlit/proto/HeightConfig_pb2.pyi +48 -0
  117. streamlit/proto/NamedDataSet_pb2.pyi +1 -1
  118. streamlit/proto/Navigation_pb2.py +3 -3
  119. streamlit/proto/Navigation_pb2.pyi +4 -0
  120. streamlit/proto/NewSession_pb2.py +18 -16
  121. streamlit/proto/NewSession_pb2.pyi +29 -3
  122. streamlit/proto/PageConfig_pb2.py +7 -7
  123. streamlit/proto/PageConfig_pb2.pyi +21 -1
  124. streamlit/proto/Video_pb2.py +8 -7
  125. streamlit/proto/Video_pb2.pyi +8 -1
  126. streamlit/proto/WidthConfig_pb2.py +2 -2
  127. streamlit/proto/WidthConfig_pb2.pyi +15 -1
  128. streamlit/runtime/__init__.py +1 -1
  129. streamlit/runtime/app_session.py +53 -40
  130. streamlit/runtime/caching/__init__.py +9 -9
  131. streamlit/runtime/caching/cache_data_api.py +36 -30
  132. streamlit/runtime/caching/cache_errors.py +4 -4
  133. streamlit/runtime/caching/cache_resource_api.py +8 -8
  134. streamlit/runtime/caching/cache_utils.py +15 -14
  135. streamlit/runtime/caching/cached_message_replay.py +14 -8
  136. streamlit/runtime/caching/hashing.py +91 -97
  137. streamlit/runtime/caching/legacy_cache_api.py +2 -2
  138. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
  139. streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
  140. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +12 -14
  141. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -6
  142. streamlit/runtime/connection_factory.py +36 -36
  143. streamlit/runtime/context.py +58 -9
  144. streamlit/runtime/credentials.py +29 -40
  145. streamlit/runtime/forward_msg_queue.py +11 -11
  146. streamlit/runtime/fragment.py +7 -7
  147. streamlit/runtime/media_file_manager.py +3 -4
  148. streamlit/runtime/memory_media_file_storage.py +6 -5
  149. streamlit/runtime/memory_uploaded_file_manager.py +2 -2
  150. streamlit/runtime/metrics_util.py +11 -12
  151. streamlit/runtime/pages_manager.py +4 -6
  152. streamlit/runtime/runtime.py +8 -6
  153. streamlit/runtime/runtime_util.py +7 -6
  154. streamlit/runtime/scriptrunner/__init__.py +4 -4
  155. streamlit/runtime/scriptrunner/exec_code.py +12 -5
  156. streamlit/runtime/scriptrunner/magic.py +16 -12
  157. streamlit/runtime/scriptrunner/script_cache.py +1 -1
  158. streamlit/runtime/scriptrunner/script_runner.py +53 -29
  159. streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
  160. streamlit/runtime/scriptrunner_utils/script_requests.py +7 -4
  161. streamlit/runtime/scriptrunner_utils/script_run_context.py +10 -23
  162. streamlit/runtime/secrets.py +40 -35
  163. streamlit/runtime/session_manager.py +2 -1
  164. streamlit/runtime/state/__init__.py +5 -5
  165. streamlit/runtime/state/common.py +2 -2
  166. streamlit/runtime/state/query_params.py +13 -15
  167. streamlit/runtime/state/query_params_proxy.py +17 -13
  168. streamlit/runtime/state/safe_session_state.py +2 -2
  169. streamlit/runtime/state/session_state.py +52 -34
  170. streamlit/runtime/stats.py +2 -2
  171. streamlit/runtime/uploaded_file_manager.py +1 -1
  172. streamlit/runtime/websocket_session_manager.py +10 -6
  173. streamlit/source_util.py +8 -6
  174. streamlit/static/index.html +3 -17
  175. streamlit/static/manifest.json +1180 -0
  176. streamlit/static/static/css/{index.DqDwtg6_.css → index.CJVRHjQZ.css} +1 -1
  177. streamlit/static/static/js/{ErrorOutline.esm.DU9IrB3M.js → ErrorOutline.esm.DitPpe1Y.js} +1 -1
  178. streamlit/static/static/js/{FileDownload.esm.P9rKwKo8.js → FileDownload.esm.AI3watX9.js} +1 -1
  179. streamlit/static/static/js/{FileHelper.D7RMkx0e.js → FileHelper.kt7mhnu8.js} +5 -5
  180. streamlit/static/static/js/{FormClearHelper.B67tgll0.js → FormClearHelper.D1M9GM_c.js} +1 -1
  181. streamlit/static/static/js/{Hooks.ncTJktu9.js → Hooks.BGwHKeUc.js} +1 -1
  182. streamlit/static/static/js/{InputInstructions.D-Y8geDN.js → InputInstructions.DaZ89mzH.js} +1 -1
  183. streamlit/static/static/js/{ProgressBar.B-kexwwD.js → ProgressBar.C0zPMe-p.js} +2 -2
  184. streamlit/static/static/js/{RenderInPortalIfExists.BgaoZgep.js → RenderInPortalIfExists.Ox8gQvdz.js} +1 -1
  185. streamlit/static/static/js/Toolbar.KhlcEc0K.js +1 -0
  186. streamlit/static/static/js/UploadFileInfo.0DCkpDDf.js +6 -0
  187. streamlit/static/static/js/{base-input.BoAa1U94.js → base-input.BJ4qsfSq.js} +4 -4
  188. streamlit/static/static/js/{checkbox.Z6iSfe5F.js → checkbox.DSDh78Xz.js} +2 -2
  189. streamlit/static/static/js/{createSuper.B4oGDYRm.js → createSuper.wQ9SIXEJ.js} +1 -1
  190. streamlit/static/static/js/{data-grid-overlay-editor.msYws2Ou.js → data-grid-overlay-editor.DvbdPJ15.js} +1 -1
  191. streamlit/static/static/js/{downloader.kc14n2Hv.js → downloader.CD9rzih5.js} +1 -1
  192. streamlit/static/static/js/{es6.CxQz807-.js → es6.48Q9Qjgb.js} +2 -2
  193. streamlit/static/static/js/{iframeResizer.contentWindow.B19u0ONI.js → iframeResizer.contentWindow.CKdem3Bn.js} +1 -1
  194. streamlit/static/static/js/{index.LaIasviC.js → index.6md5Qhod.js} +1 -1
  195. streamlit/static/static/js/index.7hy6AeJ1.js +1 -0
  196. streamlit/static/static/js/index.B4CGJiBW.js +1 -0
  197. streamlit/static/static/js/index.B8oW0ZTD.js +1 -0
  198. streamlit/static/static/js/index.BU6RnlHI.js +73 -0
  199. streamlit/static/static/js/index.BUq9Wcf8.js +197 -0
  200. streamlit/static/static/js/{index.BFz9U2y0.js → index.BXXo-Yoj.js} +1 -1
  201. streamlit/static/static/js/index.Bae9H0OS.js +1 -0
  202. streamlit/static/static/js/{index.-5ruC9At.js → index.BhTl2Uyb.js} +1 -1
  203. streamlit/static/static/js/{index.BpILzHf_.js → index.BiSaCB1o.js} +20 -20
  204. streamlit/static/static/js/{index.xNQq3Ei5.js → index.BulSAJ9z.js} +1 -1
  205. streamlit/static/static/js/{index.9V1KdxfP.js → index.Bv-EuTKR.js} +1 -1
  206. streamlit/static/static/js/index.BvMLYCHi.js +1 -0
  207. streamlit/static/static/js/index.C1NIn1Y2.js +783 -0
  208. streamlit/static/static/js/index.CP-fthOJ.js +2 -0
  209. streamlit/static/static/js/{index.BoigZiu7.js → index.CS9guO3p.js} +1 -1
  210. streamlit/static/static/js/index.CYTBHth8.js +1 -0
  211. streamlit/static/static/js/{index.CmTAF0dM.js → index.CcJufcuD.js} +1 -1
  212. streamlit/static/static/js/index.CnENU1yn.js +1 -0
  213. streamlit/static/static/js/index.Cns13qBb.js +1 -0
  214. streamlit/static/static/js/index.Ct_xXq7w.js +1 -0
  215. streamlit/static/static/js/{index.BqfdT8-Q.js → index.CxGSemHL.js} +1 -1
  216. streamlit/static/static/js/index.D5S0ldVb.js +1 -0
  217. streamlit/static/static/js/index.D72B_ksb.js +2 -0
  218. streamlit/static/static/js/index.DI4yZ27M.js +1 -0
  219. streamlit/static/static/js/index.DN51vLxR.js +1 -0
  220. streamlit/static/static/js/index.DRtq5dka.js +1 -0
  221. streamlit/static/static/js/{index.BHXxWdde.js → index.DX-oiXlb.js} +1 -1
  222. streamlit/static/static/js/index.DlFE4_Aq.js +12 -0
  223. streamlit/static/static/js/{index.BHGGDa8K.js → index.J7BJwXOi.js} +2 -2
  224. streamlit/static/static/js/index.Jg38kJPP.js +1 -0
  225. streamlit/static/static/js/index.JhIO6abf.js +3 -0
  226. streamlit/static/static/js/{index.DeB9iKFW.js → index.NkRcWwc5.js} +255 -255
  227. streamlit/static/static/js/{index.BGga-hcS.js → index.prekPLrm.js} +25 -25
  228. streamlit/static/static/js/{index.BRXmLIsC.js → index.wyzngKUE.js} +1 -1
  229. streamlit/static/static/js/index.xW7mVdI8.js +1 -0
  230. streamlit/static/static/js/index.yk07dYGx.js +1 -0
  231. streamlit/static/static/js/{input.DsCfafm0.js → input.CxKZ5Wrc.js} +2 -2
  232. streamlit/static/static/js/{memory.nY_lMTtu.js → memory.DeZ9VUvl.js} +1 -1
  233. streamlit/static/static/js/{mergeWith.B_7zmsM4.js → mergeWith.CVkhrWUb.js} +1 -1
  234. streamlit/static/static/js/{number-overlay-editor.CSeVhHRU.js → number-overlay-editor.Bpkm3nTq.js} +1 -1
  235. streamlit/static/static/js/{possibleConstructorReturn.nNhsvgRd.js → possibleConstructorReturn.CIDCId52.js} +1 -1
  236. streamlit/static/static/js/{sandbox.Cgm3iuL6.js → sandbox.TrkMaokR.js} +1 -1
  237. streamlit/static/static/js/{textarea.BR8rlyih.js → textarea.QKjxR64N.js} +2 -2
  238. streamlit/static/static/js/{timepicker.w4XhAenH.js → timepicker.DJYmE1dK.js} +1 -1
  239. streamlit/static/static/js/{toConsumableArray.CgkEPBwD.js → toConsumableArray.BZoworE-.js} +1 -1
  240. streamlit/static/static/js/{uniqueId.j-1rlNNH.js → uniqueId.O0UbJ2Bu.js} +1 -1
  241. streamlit/static/static/js/{useBasicWidgetState.zXY9CjFS.js → useBasicWidgetState.Ci89jaH5.js} +1 -1
  242. streamlit/static/static/js/useOnInputChange.Cxh6ExEn.js +1 -0
  243. streamlit/static/static/js/{withFullScreenWrapper.Ov13692o.js → withFullScreenWrapper.iW37lS8Z.js} +1 -1
  244. streamlit/static/static/media/SourceCodeVF-Italic.ttf.Ba1oaZG1.woff2 +0 -0
  245. streamlit/static/static/media/SourceCodeVF-Upright.ttf.BjWn63N-.woff2 +0 -0
  246. streamlit/static/static/media/SourceSansVF-Italic.ttf.Bt9VkdQ3.woff2 +0 -0
  247. streamlit/static/static/media/SourceSansVF-Upright.ttf.BsWL4Kly.woff2 +0 -0
  248. streamlit/static/static/media/SourceSerifVariable-Italic.ttf.CVdzAtxO.woff2 +0 -0
  249. streamlit/static/static/media/SourceSerifVariable-Roman.ttf.mdpVL9bi.woff2 +0 -0
  250. streamlit/string_util.py +14 -19
  251. streamlit/temporary_directory.py +13 -4
  252. streamlit/testing/v1/app_test.py +15 -10
  253. streamlit/testing/v1/element_tree.py +157 -178
  254. streamlit/testing/v1/local_script_runner.py +11 -15
  255. streamlit/testing/v1/util.py +11 -4
  256. streamlit/type_util.py +8 -12
  257. streamlit/url_util.py +1 -1
  258. streamlit/user_info.py +6 -5
  259. streamlit/util.py +25 -1
  260. streamlit/vendor/pympler/asizeof.py +3 -2
  261. streamlit/watcher/event_based_path_watcher.py +21 -2
  262. streamlit/watcher/folder_black_list.py +2 -2
  263. streamlit/watcher/local_sources_watcher.py +64 -18
  264. streamlit/watcher/path_watcher.py +6 -10
  265. streamlit/watcher/polling_path_watcher.py +8 -7
  266. streamlit/watcher/util.py +7 -6
  267. streamlit/web/bootstrap.py +16 -14
  268. streamlit/web/cli.py +52 -45
  269. streamlit/web/server/__init__.py +7 -3
  270. streamlit/web/server/app_static_file_handler.py +1 -1
  271. streamlit/web/server/authlib_tornado_integration.py +9 -4
  272. streamlit/web/server/browser_websocket_handler.py +8 -2
  273. streamlit/web/server/component_request_handler.py +14 -10
  274. streamlit/web/server/media_file_handler.py +14 -7
  275. streamlit/web/server/oauth_authlib_routes.py +41 -9
  276. streamlit/web/server/oidc_mixin.py +35 -17
  277. streamlit/web/server/routes.py +32 -22
  278. streamlit/web/server/server.py +13 -24
  279. streamlit/web/server/server_util.py +43 -9
  280. streamlit/web/server/stats_request_handler.py +7 -5
  281. streamlit/web/server/upload_file_request_handler.py +22 -19
  282. streamlit/web/server/websocket_headers.py +1 -1
  283. {streamlit-1.45.1.dist-info → streamlit-1.46.1.dist-info}/METADATA +4 -4
  284. streamlit-1.46.1.dist-info/RECORD +559 -0
  285. {streamlit-1.45.1.dist-info → streamlit-1.46.1.dist-info}/WHEEL +1 -1
  286. streamlit/elements/lib/event_utils.py +0 -39
  287. streamlit/static/static/js/Toolbar.D9RUZv9G.js +0 -1
  288. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
  289. streamlit/static/static/js/index.8jhZBWF2.js +0 -3
  290. streamlit/static/static/js/index.BCx3C6e_.js +0 -1
  291. streamlit/static/static/js/index.BRuTz_S4.js +0 -1
  292. streamlit/static/static/js/index.Bcru_ti-.js +0 -1
  293. streamlit/static/static/js/index.Bl1FMJRd.js +0 -1
  294. streamlit/static/static/js/index.C1z8KpLA.js +0 -779
  295. streamlit/static/static/js/index.C32I2PUe.js +0 -2
  296. streamlit/static/static/js/index.C5GnDRB7.js +0 -1
  297. streamlit/static/static/js/index.CG4qPaaW.js +0 -2
  298. streamlit/static/static/js/index.C_msmT1u.js +0 -1
  299. streamlit/static/static/js/index.CbeNTdd6.js +0 -1
  300. streamlit/static/static/js/index.CnGQVJcw.js +0 -12
  301. streamlit/static/static/js/index.CopVVq4l.js +0 -1
  302. streamlit/static/static/js/index.CtXupx4d.js +0 -197
  303. streamlit/static/static/js/index.DGmCchO7.js +0 -1
  304. streamlit/static/static/js/index.DH6zBk0e.js +0 -1
  305. streamlit/static/static/js/index.DHVlVWsm.js +0 -1
  306. streamlit/static/static/js/index.DRKIVBoi.js +0 -1
  307. streamlit/static/static/js/index.DUd-lFXx.js +0 -73
  308. streamlit/static/static/js/index.D_uRBA4B.js +0 -1
  309. streamlit/static/static/js/index.QHNfgPJd.js +0 -1
  310. streamlit/static/static/js/index.a-RJocYL.js +0 -1
  311. streamlit/static/static/js/index.cvz4B1gy.js +0 -1
  312. streamlit/static/static/js/index.t--hEgTQ.js +0 -6
  313. streamlit/static/static/js/useOnInputChange.z04u96A8.js +0 -1
  314. streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
  315. streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
  316. streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
  317. streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
  318. streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
  319. streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
  320. streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
  321. streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
  322. streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
  323. streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
  324. streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
  325. streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
  326. streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
  327. streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
  328. streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
  329. streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
  330. streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
  331. streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
  332. streamlit-1.45.1.dist-info/RECORD +0 -568
  333. {streamlit-1.45.1.data → streamlit-1.46.1.data}/scripts/streamlit.cmd +0 -0
  334. {streamlit-1.45.1.dist-info → streamlit-1.46.1.dist-info}/entry_points.txt +0 -0
  335. {streamlit-1.45.1.dist-info → streamlit-1.46.1.dist-info}/top_level.txt +0 -0
@@ -16,14 +16,23 @@ from __future__ import annotations
16
16
 
17
17
  import contextlib
18
18
  import threading
19
- from typing import TYPE_CHECKING
19
+ from typing import TYPE_CHECKING, Final
20
20
 
21
21
  import streamlit as st
22
+ from streamlit.elements.lib.layout_utils import (
23
+ LayoutConfig,
24
+ Width,
25
+ validate_width,
26
+ )
22
27
  from streamlit.runtime.scriptrunner import add_script_run_ctx
23
28
 
24
29
  if TYPE_CHECKING:
25
30
  from collections.abc import Iterator
26
31
 
32
+ # Set the message 0.5 seconds in the future to avoid annoying
33
+ # flickering if this spinner runs too quickly.
34
+ DELAY_SECS: Final = 0.5
35
+
27
36
 
28
37
  @contextlib.contextmanager
29
38
  def spinner(
@@ -31,6 +40,7 @@ def spinner(
31
40
  *,
32
41
  show_time: bool = False,
33
42
  _cache: bool = False,
43
+ width: Width = "content",
34
44
  ) -> Iterator[None]:
35
45
  """Display a loading spinner while executing a block of code.
36
46
 
@@ -55,6 +65,19 @@ def spinner(
55
65
  elapsed time is displayed with a precision of 0.1 seconds. The time
56
66
  format is not configurable.
57
67
 
68
+ width : "content", "stretch", or int
69
+ The width of the spinner element. This can be one of the following:
70
+
71
+ - ``"content"`` (default): The width of the element matches the
72
+ width of its content, but doesn't exceed the width of the parent
73
+ container.
74
+ - ``"stretch"``: The width of the element matches the width of the
75
+ parent container.
76
+ - An integer specifying the width in pixels: The element has a
77
+ fixed width. If the specified width is greater than the width of
78
+ the parent container, the width of the element matches the width
79
+ of the parent container.
80
+
58
81
  Example
59
82
  -------
60
83
  >>> import streamlit as st
@@ -73,24 +96,26 @@ def spinner(
73
96
  from streamlit.proto.Spinner_pb2 import Spinner as SpinnerProto
74
97
  from streamlit.string_util import clean_text
75
98
 
99
+ validate_width(width, allow_content=True)
100
+ layout_config = LayoutConfig(width=width)
101
+
76
102
  message = st.empty()
77
103
 
78
- # Set the message 0.5 seconds in the future to avoid annoying
79
- # flickering if this spinner runs too quickly.
80
- DELAY_SECS = 0.5
81
104
  display_message = True
82
105
  display_message_lock = threading.Lock()
83
106
 
84
107
  try:
85
108
 
86
- def set_message():
109
+ def set_message() -> None:
87
110
  with display_message_lock:
88
111
  if display_message:
89
112
  spinner_proto = SpinnerProto()
90
113
  spinner_proto.text = clean_text(text)
91
114
  spinner_proto.cache = _cache
92
115
  spinner_proto.show_time = show_time
93
- message._enqueue("spinner", spinner_proto)
116
+ message._enqueue(
117
+ "spinner", spinner_proto, layout_config=layout_config
118
+ )
94
119
 
95
120
  add_script_run_ctx(threading.Timer(DELAY_SECS, set_message)).start()
96
121
 
@@ -16,12 +16,14 @@ from __future__ import annotations
16
16
 
17
17
  from typing import TYPE_CHECKING, cast
18
18
 
19
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
19
20
  from streamlit.proto.Text_pb2 import Text as TextProto
20
21
  from streamlit.runtime.metrics_util import gather_metrics
21
22
  from streamlit.string_util import clean_text
22
23
 
23
24
  if TYPE_CHECKING:
24
25
  from streamlit.delta_generator import DeltaGenerator
26
+ from streamlit.elements.lib.layout_utils import Width
25
27
  from streamlit.type_util import SupportsStr
26
28
 
27
29
 
@@ -32,6 +34,7 @@ class TextMixin:
32
34
  body: SupportsStr,
33
35
  *, # keyword-only arguments:
34
36
  help: str | None = None,
37
+ width: Width = "content",
35
38
  ) -> DeltaGenerator:
36
39
  r"""Write text without Markdown or HTML parsing.
37
40
 
@@ -53,6 +56,19 @@ class TextMixin:
53
56
  including the Markdown directives described in the ``body``
54
57
  parameter of ``st.markdown``.
55
58
 
59
+ width : "content", "stretch", or int
60
+ The width of the text element. This can be one of the following:
61
+
62
+ - ``"content"`` (default): The width of the element matches the
63
+ width of its content, but doesn't exceed the width of the parent
64
+ container.
65
+ - ``"stretch"``: The width of the element matches the width of the
66
+ parent container.
67
+ - An integer specifying the width in pixels: The element has a
68
+ fixed width. If the specified width is greater than the width of
69
+ the parent container, the width of the element matches the width
70
+ of the parent container.
71
+
56
72
  Example
57
73
  -------
58
74
  >>> import streamlit as st
@@ -68,7 +84,11 @@ class TextMixin:
68
84
  text_proto.body = clean_text(body)
69
85
  if help:
70
86
  text_proto.help = help
71
- return self.dg._enqueue("text", text_proto)
87
+
88
+ validate_width(width, allow_content=True)
89
+ layout_config = LayoutConfig(width=width)
90
+
91
+ return self.dg._enqueue("text", text_proto, layout_config=layout_config)
72
92
 
73
93
  @property
74
94
  def dg(self) -> DeltaGenerator:
@@ -31,8 +31,7 @@ def validate_text(toast_text: SupportsStr) -> SupportsStr:
31
31
  raise StreamlitAPIException(
32
32
  "Toast body cannot be blank - please provide a message."
33
33
  )
34
- else:
35
- return toast_text
34
+ return toast_text
36
35
 
37
36
 
38
37
  class ToastMixin:
@@ -31,10 +31,10 @@ from typing import (
31
31
  overload,
32
32
  )
33
33
 
34
- from typing_extensions import TypeAlias
34
+ from typing_extensions import Required, TypeAlias
35
35
 
36
- import streamlit.elements.lib.dicttools as dicttools
37
36
  from streamlit import dataframe_util, type_util
37
+ from streamlit.elements.lib import dicttools
38
38
  from streamlit.elements.lib.built_in_chart_utils import (
39
39
  AddRowsMetadata,
40
40
  ChartStackType,
@@ -42,7 +42,6 @@ from streamlit.elements.lib.built_in_chart_utils import (
42
42
  generate_chart,
43
43
  maybe_raise_stack_warning,
44
44
  )
45
- from streamlit.elements.lib.event_utils import AttributeDictionary
46
45
  from streamlit.elements.lib.form_utils import current_form_id
47
46
  from streamlit.elements.lib.policies import check_widget_policies
48
47
  from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
@@ -53,7 +52,7 @@ from streamlit.proto.ArrowVegaLiteChart_pb2 import (
53
52
  from streamlit.runtime.metrics_util import gather_metrics
54
53
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
55
54
  from streamlit.runtime.state import WidgetCallback, register_widget
56
- from streamlit.util import calc_md5
55
+ from streamlit.util import AttributeDictionary, calc_md5
57
56
 
58
57
  if TYPE_CHECKING:
59
58
  from collections.abc import Iterable, Sequence
@@ -218,7 +217,7 @@ class VegaLiteState(TypedDict, total=False):
218
217
 
219
218
  """
220
219
 
221
- selection: AttributeDictionary
220
+ selection: Required[AttributeDictionary]
222
221
 
223
222
 
224
223
  @dataclass
@@ -227,7 +226,7 @@ class VegaLiteStateSerde:
227
226
 
228
227
  selection_parameters: Sequence[str]
229
228
 
230
- def deserialize(self, ui_value: str | None, widget_id: str = "") -> VegaLiteState:
229
+ def deserialize(self, ui_value: str | None) -> VegaLiteState:
231
230
  empty_selection_state: VegaLiteState = {
232
231
  "selection": AttributeDictionary(
233
232
  # Initialize the select state with empty dictionaries for each selection parameter.
@@ -242,7 +241,7 @@ class VegaLiteStateSerde:
242
241
  )
243
242
 
244
243
  if "selection" not in selection_state:
245
- selection_state = empty_selection_state
244
+ selection_state = empty_selection_state # type: ignore[unreachable]
246
245
 
247
246
  return cast("VegaLiteState", AttributeDictionary(selection_state))
248
247
 
@@ -250,14 +249,38 @@ class VegaLiteStateSerde:
250
249
  return json.dumps(selection_state, default=str)
251
250
 
252
251
 
252
+ def _patch_null_legend_titles(spec: VegaLiteSpec) -> None:
253
+ """Patches null legend titles in the 'color' channel of the spec.
254
+ This is a fix for the Vega-Lite bug where null legend titles
255
+ cause a wrong formatting of the chart as shown on the issue #9339.
256
+ """
257
+
258
+ encoding = spec.get("encoding")
259
+ if not isinstance(encoding, dict):
260
+ return
261
+
262
+ color_spec = encoding.get("color")
263
+ if not isinstance(color_spec, dict):
264
+ return
265
+
266
+ if "title" in color_spec and color_spec.get("title") is None:
267
+ # Patch legend title given null value directly in the encoding
268
+ color_spec["title"] = " "
269
+
270
+ legend = color_spec.get("legend")
271
+ if isinstance(legend, dict) and "title" in legend and legend.get("title") is None:
272
+ # Patch legend title given null value in the legend
273
+ legend["title"] = " "
274
+
275
+
253
276
  def _prepare_vega_lite_spec(
254
277
  spec: VegaLiteSpec,
255
278
  use_container_width: bool,
256
- **kwargs,
279
+ **kwargs: Any,
257
280
  ) -> VegaLiteSpec:
258
281
  if kwargs:
259
- # Support passing in kwargs. Example:
260
- # marshall(proto, {foo: 'bar'}, baz='boz')
282
+ # Support passing in kwargs.
283
+ # > marshall(proto, {foo: 'bar'}, baz='boz')
261
284
  # Merge spec with unflattened kwargs, where kwargs take precedence.
262
285
  # This only works for string keys, but kwarg keys are strings anyways.
263
286
  spec = dict(spec, **dicttools.unflatten(kwargs, _CHANNELS))
@@ -278,6 +301,8 @@ def _prepare_vega_lite_spec(
278
301
  else:
279
302
  spec["autosize"] = {"type": "fit", "contains": "padding"}
280
303
 
304
+ _patch_null_legend_titles(spec)
305
+
281
306
  return spec
282
307
 
283
308
 
@@ -313,10 +338,10 @@ def _marshall_chart_data(
313
338
  del spec["datasets"]
314
339
 
315
340
  # Pull data out of spec dict when it's in a top-level 'data' key:
316
- # {data: df}
317
- # {data: {values: df, ...}}
318
- # {data: {url: 'url'}}
319
- # {data: {name: 'foo'}}
341
+ # > {data: df}
342
+ # > {data: {values: df, ...}}
343
+ # > {data: {url: 'url'}}
344
+ # > {data: {name: 'foo'}}
320
345
  if "data" in spec:
321
346
  data_spec = spec["data"]
322
347
 
@@ -345,7 +370,7 @@ def _convert_altair_to_vega_lite_spec(
345
370
 
346
371
  datasets = {}
347
372
 
348
- def id_transform(data) -> dict[str, str]:
373
+ def id_transform(data: Any) -> dict[str, str]:
349
374
  """Altair data transformer that serializes the data,
350
375
  creates a stable name based on the hash of the data,
351
376
  stores the bytes into the datasets mapping and
@@ -360,7 +385,7 @@ def _convert_altair_to_vega_lite_spec(
360
385
  datasets[name] = data_bytes
361
386
  return {"name": name}
362
387
 
363
- alt.data_transformers.register("id", id_transform) # type: ignore[attr-defined,unused-ignore]
388
+ alt.data_transformers.register("id", id_transform) # type: ignore[arg-type,attr-defined,unused-ignore]
364
389
 
365
390
  # The default altair theme has some width/height defaults defined
366
391
  # which are not useful for Streamlit. Therefore, we change the theme to
@@ -442,8 +467,8 @@ def _parse_selection_mode(
442
467
  raise StreamlitAPIException(
443
468
  "Selections are activated, but the provided chart spec does not "
444
469
  "have any selections defined. To add selections to `st.altair_chart`, check out the documentation "
445
- "[here](https://altair-viz.github.io/user_guide/interactions.html#selections-capturing-chart-interactions). "
446
- "For adding selections to `st.vega_lite_chart`, take a look "
470
+ "[here](https://altair-viz.github.io/user_guide/interactions.html#selections-capturing-chart-interactions)."
471
+ " For adding selections to `st.vega_lite_chart`, take a look "
447
472
  "at the specification [here](https://vega.github.io/vega-lite/docs/selection.html)."
448
473
  )
449
474
 
@@ -742,6 +767,7 @@ class VegaChartsMixin:
742
767
  size_from_user=None,
743
768
  width=width,
744
769
  height=height,
770
+ use_container_width=use_container_width,
745
771
  )
746
772
  return cast(
747
773
  "DeltaGenerator",
@@ -983,6 +1009,7 @@ class VegaChartsMixin:
983
1009
  width=width,
984
1010
  height=height,
985
1011
  stack=stack,
1012
+ use_container_width=use_container_width,
986
1013
  )
987
1014
  return cast(
988
1015
  "DeltaGenerator",
@@ -1248,7 +1275,9 @@ class VegaChartsMixin:
1248
1275
  size_from_user=None,
1249
1276
  width=width,
1250
1277
  height=height,
1278
+ use_container_width=use_container_width,
1251
1279
  stack=stack,
1280
+ horizontal=horizontal,
1252
1281
  )
1253
1282
  return cast(
1254
1283
  "DeltaGenerator",
@@ -1459,6 +1488,7 @@ class VegaChartsMixin:
1459
1488
  size_from_user=size,
1460
1489
  width=width,
1461
1490
  height=height,
1491
+ use_container_width=use_container_width,
1462
1492
  )
1463
1493
  return cast(
1464
1494
  "DeltaGenerator",
@@ -1479,7 +1509,7 @@ class VegaChartsMixin:
1479
1509
  use_container_width: bool | None = None,
1480
1510
  theme: Literal["streamlit"] | None = "streamlit",
1481
1511
  key: Key | None = None,
1482
- on_select: Literal["ignore"], # No default value here to make it work with mypy
1512
+ on_select: Literal["ignore"] = "ignore",
1483
1513
  selection_mode: str | Iterable[str] | None = None,
1484
1514
  ) -> DeltaGenerator: ...
1485
1515
 
@@ -1492,7 +1522,7 @@ class VegaChartsMixin:
1492
1522
  use_container_width: bool | None = None,
1493
1523
  theme: Literal["streamlit"] | None = "streamlit",
1494
1524
  key: Key | None = None,
1495
- on_select: Literal["rerun"] | WidgetCallback = "rerun",
1525
+ on_select: Literal["rerun"] | WidgetCallback,
1496
1526
  selection_mode: str | Iterable[str] | None = None,
1497
1527
  ) -> VegaLiteState: ...
1498
1528
 
@@ -1567,7 +1597,7 @@ class VegaChartsMixin:
1567
1597
  as a dictionary.
1568
1598
 
1569
1599
  To use selection events, the object passed to ``altair_chart`` must
1570
- include selection paramters. To learn about defining interactions
1600
+ include selection parameters. To learn about defining interactions
1571
1601
  in Altair and how to declare selection-type parameters, see
1572
1602
  `Interactive Charts \
1573
1603
  <https://altair-viz.github.io/user_guide/interactions.html>`_
@@ -1638,7 +1668,7 @@ class VegaChartsMixin:
1638
1668
  use_container_width: bool | None = None,
1639
1669
  theme: Literal["streamlit"] | None = "streamlit",
1640
1670
  key: Key | None = None,
1641
- on_select: Literal["ignore"], # No default value here to make it work with mypy
1671
+ on_select: Literal["ignore"] = "ignore",
1642
1672
  selection_mode: str | Iterable[str] | None = None,
1643
1673
  **kwargs: Any,
1644
1674
  ) -> DeltaGenerator: ...
@@ -1653,7 +1683,7 @@ class VegaChartsMixin:
1653
1683
  use_container_width: bool | None = None,
1654
1684
  theme: Literal["streamlit"] | None = "streamlit",
1655
1685
  key: Key | None = None,
1656
- on_select: Literal["rerun"] | WidgetCallback = "rerun",
1686
+ on_select: Literal["rerun"] | WidgetCallback,
1657
1687
  selection_mode: str | Iterable[str] | None = None,
1658
1688
  **kwargs: Any,
1659
1689
  ) -> VegaLiteState: ...
@@ -1942,6 +1972,7 @@ class VegaChartsMixin:
1942
1972
  "arrow_vega_lite_chart",
1943
1973
  user_key=key,
1944
1974
  form_id=vega_lite_proto.form_id,
1975
+ dg=self.dg,
1945
1976
  vega_lite_spec=vega_lite_proto.spec,
1946
1977
  # The data is either in vega_lite_proto.data.data
1947
1978
  # or in a named dataset in vega_lite_proto.datasets
@@ -22,6 +22,7 @@ from typing_extensions import TypeAlias
22
22
 
23
23
  from streamlit.elements.lib.file_uploader_utils import enforce_filename_restriction
24
24
  from streamlit.elements.lib.form_utils import current_form_id
25
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
25
26
  from streamlit.elements.lib.policies import (
26
27
  check_widget_policies,
27
28
  maybe_raise_label_warnings,
@@ -49,6 +50,7 @@ from streamlit.runtime.uploaded_file_manager import DeletedFile, UploadedFile
49
50
 
50
51
  if TYPE_CHECKING:
51
52
  from streamlit.delta_generator import DeltaGenerator
53
+ from streamlit.elements.lib.layout_utils import WidthWithoutContent
52
54
 
53
55
  SomeUploadedAudioFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
54
56
 
@@ -73,13 +75,10 @@ class AudioInputSerde:
73
75
  return state_proto
74
76
 
75
77
  def deserialize(
76
- self, ui_value: FileUploaderStateProto | None, widget_id: str
78
+ self, ui_value: FileUploaderStateProto | None
77
79
  ) -> SomeUploadedAudioFile:
78
80
  upload_files = _get_upload_files(ui_value)
79
- if len(upload_files) == 0:
80
- return_value = None
81
- else:
82
- return_value = upload_files[0]
81
+ return_value = None if len(upload_files) == 0 else upload_files[0]
83
82
  if return_value is not None and not isinstance(return_value, DeletedFile):
84
83
  enforce_filename_restriction(return_value.name, [".wav"])
85
84
  return return_value
@@ -98,6 +97,7 @@ class AudioInputMixin:
98
97
  kwargs: WidgetKwargs | None = None,
99
98
  disabled: bool = False,
100
99
  label_visibility: LabelVisibility = "visible",
100
+ width: WidthWithoutContent = "stretch",
101
101
  ) -> UploadedFile | None:
102
102
  r"""Display a widget that returns an audio recording from the user's microphone.
103
103
 
@@ -156,9 +156,19 @@ class AudioInputMixin:
156
156
  label_visibility : "visible", "hidden", or "collapsed"
157
157
  The visibility of the label. The default is ``"visible"``. If this
158
158
  is ``"hidden"``, Streamlit displays an empty spacer instead of the
159
- label, which can help keep the widget alligned with other widgets.
159
+ label, which can help keep the widget aligned with other widgets.
160
160
  If this is ``"collapsed"``, Streamlit displays no label or spacer.
161
161
 
162
+ width : "stretch" or int
163
+ The width of the audio input widget. This can be one of the following:
164
+
165
+ - ``"stretch"`` (default): The width of the widget matches the
166
+ width of the parent container.
167
+ - An integer specifying the width in pixels: The widget has a
168
+ fixed width. If the specified width is greater than the width of
169
+ the parent container, the width of the widget matches the width
170
+ of the parent container.
171
+
162
172
  Returns
163
173
  -------
164
174
  None or UploadedFile
@@ -197,6 +207,7 @@ class AudioInputMixin:
197
207
  kwargs=kwargs,
198
208
  disabled=disabled,
199
209
  label_visibility=label_visibility,
210
+ width=width,
200
211
  ctx=ctx,
201
212
  )
202
213
 
@@ -211,6 +222,7 @@ class AudioInputMixin:
211
222
  *, # keyword-only arguments:
212
223
  disabled: bool = False,
213
224
  label_visibility: LabelVisibility = "visible",
225
+ width: WidthWithoutContent = "stretch",
214
226
  ctx: ScriptRunContext | None = None,
215
227
  ) -> UploadedFile | None:
216
228
  key = to_key(key)
@@ -228,8 +240,10 @@ class AudioInputMixin:
228
240
  "audio_input",
229
241
  user_key=key,
230
242
  form_id=current_form_id(self.dg),
243
+ dg=self.dg,
231
244
  label=label,
232
245
  help=help,
246
+ width=width,
233
247
  )
234
248
 
235
249
  audio_input_proto = AudioInputProto()
@@ -244,6 +258,9 @@ class AudioInputMixin:
244
258
  if label and help is not None:
245
259
  audio_input_proto.help = dedent(help)
246
260
 
261
+ validate_width(width)
262
+ layout_config = LayoutConfig(width=width)
263
+
247
264
  serde = AudioInputSerde()
248
265
 
249
266
  audio_input_state = register_widget(
@@ -257,7 +274,7 @@ class AudioInputMixin:
257
274
  value_type="file_uploader_state_value",
258
275
  )
259
276
 
260
- self.dg._enqueue("audio_input", audio_input_proto)
277
+ self.dg._enqueue("audio_input", audio_input_proto, layout_config=layout_config)
261
278
 
262
279
  if isinstance(audio_input_state.value, DeletedFile):
263
280
  return None
@@ -80,7 +80,7 @@ class ButtonSerde:
80
80
  def serialize(self, v: bool) -> bool:
81
81
  return bool(v)
82
82
 
83
- def deserialize(self, ui_value: bool | None, widget_id: str = "") -> bool:
83
+ def deserialize(self, ui_value: bool | None) -> bool:
84
84
  return ui_value or False
85
85
 
86
86
 
@@ -420,7 +420,7 @@ class ButtonMixin:
420
420
  data with a cached function. When working with a download button, it's
421
421
  similarly recommended to convert your data into a downloadable format
422
422
  with a cached function. Caching ensures that the app reruns
423
- effeciently.
423
+ efficiently.
424
424
 
425
425
  >>> import streamlit as st
426
426
  >>> import pandas as pd
@@ -682,10 +682,10 @@ class ButtonMixin:
682
682
 
683
683
  Parameters
684
684
  ----------
685
- page : str, Path, or st.Page
686
- The file path (relative to the main script) or an st.Page indicating
687
- the page to switch to. Alternatively, this can be the URL to an
688
- external page (must start with "http://" or "https://").
685
+ page : str, Path, or StreamlitPage
686
+ The file path (relative to the main script) or a ``StreamlitPage``
687
+ indicating the page to switch to. Alternatively, this can be the
688
+ URL to an external page (must start with "http://" or "https://").
689
689
 
690
690
  label : str
691
691
  The label for the page link. Labels are required for external pages.
@@ -706,8 +706,9 @@ class ButtonMixin:
706
706
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
707
707
 
708
708
  icon : str or None
709
- An optional emoji or icon to display next to the button label. If ``icon``
710
- is ``None`` (default), no icon is displayed. If ``icon`` is a
709
+ An optional emoji or icon to display next to the button label. If
710
+ ``icon`` is ``None`` (default), the icon is inferred from the
711
+ ``StreamlitPage`` object or no icon is displayed. If ``icon`` is a
711
712
  string, the following options are valid:
712
713
 
713
714
  - A single-character emoji. For example, you can set ``icon="🚨"``
@@ -799,15 +800,16 @@ class ButtonMixin:
799
800
  ) -> bool:
800
801
  key = to_key(key)
801
802
 
802
- if on_click == "ignore" or on_click == "rerun":
803
- on_click_callback = None
804
- else:
805
- on_click_callback = on_click
803
+ on_click_callback: WidgetCallback | None = (
804
+ None
805
+ if on_click is None or on_click in {"ignore", "rerun"}
806
+ else cast("WidgetCallback", on_click)
807
+ )
806
808
 
807
809
  check_widget_policies(
808
810
  self.dg,
809
811
  key,
810
- on_click_callback,
812
+ on_change=on_click_callback,
811
813
  default_value=None,
812
814
  writes_allowed=False,
813
815
  )
@@ -817,6 +819,7 @@ class ButtonMixin:
817
819
  user_key=key,
818
820
  # download_button is not allowed to be used in a form.
819
821
  form_id=None,
822
+ dg=self.dg,
820
823
  label=label,
821
824
  icon=icon,
822
825
  file_name=file_name,
@@ -930,6 +933,10 @@ class ButtonMixin:
930
933
  page_link_proto.page = page.url_path
931
934
  if label is None:
932
935
  page_link_proto.label = page.title
936
+ if icon is None:
937
+ page_link_proto.icon = page.icon
938
+ # Here the StreamlitPage's icon is already validated
939
+ # (using validate_icon_or_emoji) during its initialization
933
940
  else:
934
941
  # Convert Path to string if necessary
935
942
  if isinstance(page, Path):
@@ -939,10 +946,9 @@ class ButtonMixin:
939
946
  if is_url(page):
940
947
  if label is None or label == "":
941
948
  raise StreamlitMissingPageLabelError()
942
- else:
943
- page_link_proto.page = page
944
- page_link_proto.external = True
945
- return self.dg._enqueue("page_link", page_link_proto)
949
+ page_link_proto.page = page
950
+ page_link_proto.external = True
951
+ return self.dg._enqueue("page_link", page_link_proto)
946
952
 
947
953
  ctx_main_script = ""
948
954
  all_app_pages = {}
@@ -1009,6 +1015,7 @@ class ButtonMixin:
1009
1015
  user_key=key,
1010
1016
  # Only the
1011
1017
  form_id=form_id,
1018
+ dg=self.dg,
1012
1019
  label=label,
1013
1020
  icon=icon,
1014
1021
  help=help,
@@ -1027,7 +1034,7 @@ class ButtonMixin:
1027
1034
  raise StreamlitAPIException(
1028
1035
  f"`st.button()` can't be used in an `st.form()`.{FORM_DOCS_INFO}"
1029
1036
  )
1030
- elif not is_in_form(self.dg) and is_form_submitter:
1037
+ if not is_in_form(self.dg) and is_form_submitter:
1031
1038
  raise StreamlitAPIException(
1032
1039
  f"`st.form_submit_button()` must be used inside an `st.form()`.{FORM_DOCS_INFO}"
1033
1040
  )
@@ -1105,7 +1112,7 @@ def marshall_file(
1105
1112
  data_as_bytes = data.read() or b""
1106
1113
  mimetype = mimetype or "application/octet-stream"
1107
1114
  else:
1108
- raise RuntimeError("Invalid binary data format: %s" % type(data))
1115
+ raise StreamlitAPIException(f"Invalid binary data format: {type(data)}")
1109
1116
 
1110
1117
  if runtime.exists():
1111
1118
  file_url = runtime.get_instance().media_file_mgr.add(