streamlit 1.45.0__py3-none-any.whl → 1.46.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 (336) 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/file_uploader_utils.py +7 -2
  49. streamlit/elements/lib/image_utils.py +39 -40
  50. streamlit/elements/lib/js_number.py +4 -4
  51. streamlit/elements/lib/layout_utils.py +65 -1
  52. streamlit/elements/lib/mutable_status_container.py +14 -3
  53. streamlit/elements/lib/options_selector_utils.py +22 -12
  54. streamlit/elements/lib/pandas_styler_utils.py +25 -21
  55. streamlit/elements/lib/policies.py +6 -5
  56. streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
  57. streamlit/elements/lib/subtitle_utils.py +6 -9
  58. streamlit/elements/lib/utils.py +20 -5
  59. streamlit/elements/map.py +32 -56
  60. streamlit/elements/markdown.py +101 -12
  61. streamlit/elements/media.py +78 -21
  62. streamlit/elements/metric.py +32 -16
  63. streamlit/elements/plotly_chart.py +15 -15
  64. streamlit/elements/progress.py +33 -15
  65. streamlit/elements/spinner.py +31 -6
  66. streamlit/elements/text.py +21 -1
  67. streamlit/elements/toast.py +1 -2
  68. streamlit/elements/vega_charts.py +54 -23
  69. streamlit/elements/widgets/audio_input.py +24 -7
  70. streamlit/elements/widgets/button.py +26 -19
  71. streamlit/elements/widgets/button_group.py +10 -15
  72. streamlit/elements/widgets/camera_input.py +27 -7
  73. streamlit/elements/widgets/chat.py +91 -38
  74. streamlit/elements/widgets/checkbox.py +45 -4
  75. streamlit/elements/widgets/color_picker.py +40 -17
  76. streamlit/elements/widgets/data_editor.py +76 -37
  77. streamlit/elements/widgets/file_uploader.py +42 -13
  78. streamlit/elements/widgets/multiselect.py +7 -10
  79. streamlit/elements/widgets/number_input.py +123 -47
  80. streamlit/elements/widgets/radio.py +59 -13
  81. streamlit/elements/widgets/select_slider.py +35 -30
  82. streamlit/elements/widgets/selectbox.py +56 -9
  83. streamlit/elements/widgets/slider.py +190 -99
  84. streamlit/elements/widgets/text_widgets.py +54 -8
  85. streamlit/elements/widgets/time_widgets.py +53 -14
  86. streamlit/elements/write.py +5 -8
  87. streamlit/env_util.py +2 -7
  88. streamlit/error_util.py +16 -9
  89. streamlit/errors.py +69 -48
  90. streamlit/external/langchain/streamlit_callback_handler.py +10 -5
  91. streamlit/file_util.py +27 -10
  92. streamlit/git_util.py +29 -24
  93. streamlit/hello/animation_demo.py +9 -9
  94. streamlit/hello/dataframe_demo.py +5 -5
  95. streamlit/hello/hello.py +1 -0
  96. streamlit/hello/mapping_demo.py +7 -8
  97. streamlit/hello/plotting_demo.py +3 -3
  98. streamlit/hello/streamlit_app.py +28 -26
  99. streamlit/hello/utils.py +2 -1
  100. streamlit/logger.py +10 -11
  101. streamlit/navigation/page.py +11 -8
  102. streamlit/proto/Audio_pb2.py +4 -3
  103. streamlit/proto/Audio_pb2.pyi +8 -1
  104. streamlit/proto/Block_pb2.py +38 -29
  105. streamlit/proto/Block_pb2.pyi +72 -4
  106. streamlit/proto/ClientState_pb2.py +4 -4
  107. streamlit/proto/ClientState_pb2.pyi +7 -2
  108. streamlit/proto/Code_pb2.py +4 -2
  109. streamlit/proto/Code_pb2.pyi +1 -0
  110. streamlit/proto/DataFrame_pb2.pyi +1 -1
  111. streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
  112. streamlit/proto/Element_pb2.py +5 -3
  113. streamlit/proto/Element_pb2.pyi +20 -3
  114. streamlit/proto/GapSize_pb2.py +29 -0
  115. streamlit/proto/GapSize_pb2.pyi +70 -0
  116. streamlit/proto/HeightConfig_pb2.py +27 -0
  117. streamlit/proto/HeightConfig_pb2.pyi +48 -0
  118. streamlit/proto/NamedDataSet_pb2.pyi +1 -1
  119. streamlit/proto/Navigation_pb2.py +3 -3
  120. streamlit/proto/Navigation_pb2.pyi +4 -0
  121. streamlit/proto/NewSession_pb2.py +18 -16
  122. streamlit/proto/NewSession_pb2.pyi +29 -3
  123. streamlit/proto/PageConfig_pb2.py +7 -7
  124. streamlit/proto/PageConfig_pb2.pyi +21 -1
  125. streamlit/proto/Video_pb2.py +8 -7
  126. streamlit/proto/Video_pb2.pyi +8 -1
  127. streamlit/proto/WidthConfig_pb2.py +2 -2
  128. streamlit/proto/WidthConfig_pb2.pyi +15 -1
  129. streamlit/runtime/__init__.py +1 -1
  130. streamlit/runtime/app_session.py +53 -40
  131. streamlit/runtime/caching/__init__.py +9 -9
  132. streamlit/runtime/caching/cache_data_api.py +36 -30
  133. streamlit/runtime/caching/cache_errors.py +4 -4
  134. streamlit/runtime/caching/cache_resource_api.py +8 -8
  135. streamlit/runtime/caching/cache_utils.py +15 -14
  136. streamlit/runtime/caching/cached_message_replay.py +14 -8
  137. streamlit/runtime/caching/hashing.py +91 -97
  138. streamlit/runtime/caching/legacy_cache_api.py +2 -2
  139. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
  140. streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
  141. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +12 -14
  142. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -6
  143. streamlit/runtime/connection_factory.py +36 -36
  144. streamlit/runtime/context.py +58 -9
  145. streamlit/runtime/credentials.py +29 -40
  146. streamlit/runtime/forward_msg_queue.py +11 -11
  147. streamlit/runtime/fragment.py +7 -7
  148. streamlit/runtime/media_file_manager.py +3 -4
  149. streamlit/runtime/memory_media_file_storage.py +6 -5
  150. streamlit/runtime/memory_uploaded_file_manager.py +2 -2
  151. streamlit/runtime/metrics_util.py +11 -12
  152. streamlit/runtime/pages_manager.py +4 -6
  153. streamlit/runtime/runtime.py +8 -6
  154. streamlit/runtime/runtime_util.py +7 -6
  155. streamlit/runtime/scriptrunner/__init__.py +4 -4
  156. streamlit/runtime/scriptrunner/exec_code.py +12 -5
  157. streamlit/runtime/scriptrunner/magic.py +16 -12
  158. streamlit/runtime/scriptrunner/script_cache.py +1 -1
  159. streamlit/runtime/scriptrunner/script_runner.py +55 -34
  160. streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
  161. streamlit/runtime/scriptrunner_utils/script_requests.py +7 -4
  162. streamlit/runtime/scriptrunner_utils/script_run_context.py +10 -23
  163. streamlit/runtime/secrets.py +40 -35
  164. streamlit/runtime/session_manager.py +2 -1
  165. streamlit/runtime/state/__init__.py +5 -5
  166. streamlit/runtime/state/common.py +2 -2
  167. streamlit/runtime/state/query_params.py +13 -15
  168. streamlit/runtime/state/query_params_proxy.py +17 -13
  169. streamlit/runtime/state/safe_session_state.py +2 -2
  170. streamlit/runtime/state/session_state.py +52 -34
  171. streamlit/runtime/stats.py +2 -2
  172. streamlit/runtime/uploaded_file_manager.py +1 -1
  173. streamlit/runtime/websocket_session_manager.py +10 -6
  174. streamlit/source_util.py +8 -6
  175. streamlit/static/index.html +3 -17
  176. streamlit/static/manifest.json +1180 -0
  177. streamlit/static/static/css/{index.DqDwtg6_.css → index.CJVRHjQZ.css} +1 -1
  178. streamlit/static/static/js/{ErrorOutline.esm.DyIfDYvY.js → ErrorOutline.esm.6PVAQvlT.js} +1 -1
  179. streamlit/static/static/js/{FileDownload.esm.kF1FCxeJ.js → FileDownload.esm.BZQHC61b.js} +1 -1
  180. streamlit/static/static/js/{FileHelper.DKt6tIeO.js → FileHelper.Bn1VShMJ.js} +5 -5
  181. streamlit/static/static/js/{FormClearHelper.DpJR9YCu.js → FormClearHelper.CsFEiTNN.js} +1 -1
  182. streamlit/static/static/js/{Hooks.BT6PF2Zi.js → Hooks.DguOHQL1.js} +1 -1
  183. streamlit/static/static/js/{InputInstructions.BmnD4oa3.js → InputInstructions.CTYn2BJQ.js} +1 -1
  184. streamlit/static/static/js/{ProgressBar.Ch7VNdkM.js → ProgressBar.CPOGBKCi.js} +2 -2
  185. streamlit/static/static/js/{RenderInPortalIfExists.43tDswzK.js → RenderInPortalIfExists.BYu_CZaF.js} +1 -1
  186. streamlit/static/static/js/Toolbar.gXKw7ANv.js +1 -0
  187. streamlit/static/static/js/UploadFileInfo.0DCkpDDf.js +6 -0
  188. streamlit/static/static/js/{base-input.BjeC3XFX.js → base-input.DBYPj91R.js} +4 -4
  189. streamlit/static/static/js/{checkbox.DIVN0GOS.js → checkbox.BUm2vnNv.js} +2 -2
  190. streamlit/static/static/js/{createSuper.CKyBiJe0.js → createSuper.KD4RuZ-W.js} +1 -1
  191. streamlit/static/static/js/{data-grid-overlay-editor.CXpaXRk5.js → data-grid-overlay-editor.CUwpDfvI.js} +1 -1
  192. streamlit/static/static/js/{downloader.B-uWAyLB.js → downloader.CkDtclup.js} +1 -1
  193. streamlit/static/static/js/{es6._eGNfJ2i.js → es6.Dlcvh_r0.js} +2 -2
  194. streamlit/static/static/js/{iframeResizer.contentWindow.CebQfV1Q.js → iframeResizer.contentWindow.DOXlFfve.js} +1 -1
  195. streamlit/static/static/js/{index.EbMzSayc.js → index.B0cuGMAB.js} +25 -25
  196. streamlit/static/static/js/index.BCWTclSV.js +73 -0
  197. streamlit/static/static/js/index.BJY_fap7.js +1 -0
  198. streamlit/static/static/js/index.BL3l6dnk.js +1 -0
  199. streamlit/static/static/js/{index.CpV1hnf8.js → index.BMZzRZjB.js} +1 -1
  200. streamlit/static/static/js/{index.l6QfBDTC.js → index.BOzUTGDe.js} +1 -1
  201. streamlit/static/static/js/index.BYI5iO-o.js +1 -0
  202. streamlit/static/static/js/index.BYo0ywlm.js +783 -0
  203. streamlit/static/static/js/{index.CuUJHsRK.js → index.BYz9btsY.js} +1 -1
  204. streamlit/static/static/js/{index.C_nMqHLH.js → index.CCVzQz0Z.js} +2 -2
  205. streamlit/static/static/js/index.CD6FydK9.js +1 -0
  206. streamlit/static/static/js/index.CDYEqgC8.js +2 -0
  207. streamlit/static/static/js/{index.BAdBHmJD.js → index.CMP9c4xA.js} +1 -1
  208. streamlit/static/static/js/index.CN30QAPD.js +1 -0
  209. streamlit/static/static/js/{index.CtTgot1Z.js → index.CNqWQkTe.js} +1 -1
  210. streamlit/static/static/js/index.CaxS67Xz.js +1 -0
  211. streamlit/static/static/js/{index.HsXxdgGd.js → index.CbsT4sGW.js} +1 -1
  212. streamlit/static/static/js/index.ChAVlxpQ.js +1 -0
  213. streamlit/static/static/js/{index.BaYSBSaz.js → index.ClLMMmDd.js} +1 -1
  214. streamlit/static/static/js/{index.CxxktCLw.js → index.D-O9rQmV.js} +1 -1
  215. streamlit/static/static/js/{index.Coc8OVG7.js → index.D4k7VZZL.js} +1 -1
  216. streamlit/static/static/js/index.DLBi0Ar1.js +1 -0
  217. streamlit/static/static/js/index.DVq5XmJo.js +197 -0
  218. streamlit/static/static/js/{index.ClX0ambk.js → index.DZKmKXWw.js} +1 -1
  219. streamlit/static/static/js/index.DkaVx80F.js +1 -0
  220. streamlit/static/static/js/index.Dr968Klx.js +1 -0
  221. streamlit/static/static/js/{index.BaozEIL-.js → index.DtUYLn9j.js} +20 -20
  222. streamlit/static/static/js/index.DwjYSyhs.js +1 -0
  223. streamlit/static/static/js/index.DzrImxu4.js +1 -0
  224. streamlit/static/static/js/index.HyGsn4VM.js +1 -0
  225. streamlit/static/static/js/index.OwxC65od.js +12 -0
  226. streamlit/static/static/js/index.PZs7VZkC.js +1 -0
  227. streamlit/static/static/js/index.Voiqpj4q.js +1 -0
  228. streamlit/static/static/js/index.bSROvR-J.js +3 -0
  229. streamlit/static/static/js/index.oT9GD3l4.js +1 -0
  230. streamlit/static/static/js/{index.schmj9D9.js → index.qb-yAPH6.js} +255 -255
  231. streamlit/static/static/js/index.rJFy_Ygy.js +2 -0
  232. streamlit/static/static/js/{input.VQEe_bZy.js → input.CwQtEnFN.js} +2 -2
  233. streamlit/static/static/js/{memory.DGVHab07.js → memory.C5XaFIjR.js} +1 -1
  234. streamlit/static/static/js/{mergeWith.-RIuUGoA.js → mergeWith.DzwwH6AG.js} +1 -1
  235. streamlit/static/static/js/{number-overlay-editor.wzFLIbEE.js → number-overlay-editor.Dx0XqCkD.js} +1 -1
  236. streamlit/static/static/js/{possibleConstructorReturn.GIObu6rf.js → possibleConstructorReturn.CVfSu9Ws.js} +1 -1
  237. streamlit/static/static/js/{sandbox.DpjSeqe2.js → sandbox.BT0gdMXk.js} +1 -1
  238. streamlit/static/static/js/{textarea.Dz0J9LZe.js → textarea.DNCbrtbM.js} +2 -2
  239. streamlit/static/static/js/{timepicker.BLgJZnzX.js → timepicker.4UYJD9Ts.js} +1 -1
  240. streamlit/static/static/js/{toConsumableArray.0OZlxz7U.js → toConsumableArray.DUmnaVWV.js} +1 -1
  241. streamlit/static/static/js/{uniqueId.DbzplC8D.js → uniqueId.DUvh-GL8.js} +1 -1
  242. streamlit/static/static/js/{useBasicWidgetState.COJZng1S.js → useBasicWidgetState.Cwd7-jJa.js} +1 -1
  243. streamlit/static/static/js/useOnInputChange.DvemQrOM.js +1 -0
  244. streamlit/static/static/js/{withFullScreenWrapper.CzWvNbvi.js → withFullScreenWrapper.CiQ10ByU.js} +1 -1
  245. streamlit/static/static/media/SourceCodeVF-Italic.ttf.Ba1oaZG1.woff2 +0 -0
  246. streamlit/static/static/media/SourceCodeVF-Upright.ttf.BjWn63N-.woff2 +0 -0
  247. streamlit/static/static/media/SourceSansVF-Italic.ttf.Bt9VkdQ3.woff2 +0 -0
  248. streamlit/static/static/media/SourceSansVF-Upright.ttf.BsWL4Kly.woff2 +0 -0
  249. streamlit/static/static/media/SourceSerifVariable-Italic.ttf.CVdzAtxO.woff2 +0 -0
  250. streamlit/static/static/media/SourceSerifVariable-Roman.ttf.mdpVL9bi.woff2 +0 -0
  251. streamlit/string_util.py +14 -19
  252. streamlit/temporary_directory.py +13 -4
  253. streamlit/testing/v1/app_test.py +15 -10
  254. streamlit/testing/v1/element_tree.py +157 -178
  255. streamlit/testing/v1/local_script_runner.py +11 -15
  256. streamlit/testing/v1/util.py +11 -4
  257. streamlit/type_util.py +8 -12
  258. streamlit/url_util.py +1 -1
  259. streamlit/user_info.py +6 -5
  260. streamlit/util.py +25 -1
  261. streamlit/vendor/pympler/asizeof.py +3 -2
  262. streamlit/watcher/event_based_path_watcher.py +15 -1
  263. streamlit/watcher/folder_black_list.py +2 -2
  264. streamlit/watcher/local_sources_watcher.py +64 -18
  265. streamlit/watcher/path_watcher.py +6 -10
  266. streamlit/watcher/polling_path_watcher.py +8 -7
  267. streamlit/watcher/util.py +7 -6
  268. streamlit/web/bootstrap.py +16 -14
  269. streamlit/web/cli.py +52 -45
  270. streamlit/web/server/__init__.py +7 -3
  271. streamlit/web/server/app_static_file_handler.py +1 -1
  272. streamlit/web/server/authlib_tornado_integration.py +9 -4
  273. streamlit/web/server/browser_websocket_handler.py +8 -2
  274. streamlit/web/server/component_request_handler.py +14 -10
  275. streamlit/web/server/media_file_handler.py +14 -7
  276. streamlit/web/server/oauth_authlib_routes.py +41 -9
  277. streamlit/web/server/oidc_mixin.py +35 -17
  278. streamlit/web/server/routes.py +32 -22
  279. streamlit/web/server/server.py +6 -18
  280. streamlit/web/server/server_util.py +19 -9
  281. streamlit/web/server/stats_request_handler.py +7 -5
  282. streamlit/web/server/upload_file_request_handler.py +22 -19
  283. streamlit/web/server/websocket_headers.py +1 -1
  284. {streamlit-1.45.0.dist-info → streamlit-1.46.0.dist-info}/METADATA +4 -4
  285. streamlit-1.46.0.dist-info/RECORD +559 -0
  286. {streamlit-1.45.0.dist-info → streamlit-1.46.0.dist-info}/WHEEL +1 -1
  287. streamlit/elements/lib/event_utils.py +0 -39
  288. streamlit/static/static/js/Toolbar.HTGsjfCP.js +0 -1
  289. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
  290. streamlit/static/static/js/index.B5TWFN5r.js +0 -1
  291. streamlit/static/static/js/index.BI9-p_-s.js +0 -3
  292. streamlit/static/static/js/index.BYHnDZYn.js +0 -1
  293. streamlit/static/static/js/index.B_M97aPz.js +0 -1
  294. streamlit/static/static/js/index.BdN5swP0.js +0 -1
  295. streamlit/static/static/js/index.BfCAp_Sj.js +0 -1
  296. streamlit/static/static/js/index.BqDl3eRM.js +0 -779
  297. streamlit/static/static/js/index.C0VtYb3T.js +0 -2
  298. streamlit/static/static/js/index.C1qW_Owy.js +0 -1
  299. streamlit/static/static/js/index.C4AcBARa.js +0 -1
  300. streamlit/static/static/js/index.CCOiJRk1.js +0 -1
  301. streamlit/static/static/js/index.COvpza5W.js +0 -1
  302. streamlit/static/static/js/index.C_9qGjbK.js +0 -2
  303. streamlit/static/static/js/index.CqISBfsc.js +0 -197
  304. streamlit/static/static/js/index.D1WOs2Ce.js +0 -1
  305. streamlit/static/static/js/index.DQljs-9e.js +0 -1
  306. streamlit/static/static/js/index.DZqX4P_2.js +0 -1
  307. streamlit/static/static/js/index.DajIfBOb.js +0 -1
  308. streamlit/static/static/js/index.DuOXre0H.js +0 -1
  309. streamlit/static/static/js/index.EWD98YhP.js +0 -1
  310. streamlit/static/static/js/index.LaZloCTl.js +0 -73
  311. streamlit/static/static/js/index.S_1klBoy.js +0 -1
  312. streamlit/static/static/js/index.b0Gf958T.js +0 -12
  313. streamlit/static/static/js/index.t--hEgTQ.js +0 -6
  314. streamlit/static/static/js/useOnInputChange.CgOwAHyw.js +0 -1
  315. streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
  316. streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
  317. streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
  318. streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
  319. streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
  320. streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
  321. streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
  322. streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
  323. streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
  324. streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
  325. streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
  326. streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
  327. streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
  328. streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
  329. streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
  330. streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
  331. streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
  332. streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
  333. streamlit-1.45.0.dist-info/RECORD +0 -568
  334. {streamlit-1.45.0.data → streamlit-1.46.0.data}/scripts/streamlit.cmd +0 -0
  335. {streamlit-1.45.0.dist-info → streamlit-1.46.0.dist-info}/entry_points.txt +0 -0
  336. {streamlit-1.45.0.dist-info → streamlit-1.46.0.dist-info}/top_level.txt +0 -0
@@ -24,17 +24,19 @@ import types
24
24
  from typing import TYPE_CHECKING, Any, Final, cast
25
25
 
26
26
  import streamlit
27
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
27
28
  from streamlit.proto.DocString_pb2 import DocString as DocStringProto
28
29
  from streamlit.proto.DocString_pb2 import Member as MemberProto
29
30
  from streamlit.runtime.metrics_util import gather_metrics
30
31
  from streamlit.runtime.scriptrunner.script_runner import (
31
- __file__ as SCRIPTRUNNER_FILENAME,
32
+ __file__ as SCRIPTRUNNER_FILENAME, # noqa: N812
32
33
  )
33
34
  from streamlit.runtime.secrets import Secrets
34
35
  from streamlit.string_util import is_mem_address_str
35
36
 
36
37
  if TYPE_CHECKING:
37
38
  from streamlit.delta_generator import DeltaGenerator
39
+ from streamlit.elements.lib.layout_utils import WidthWithoutContent
38
40
 
39
41
 
40
42
  CONFUSING_STREAMLIT_SIG_PREFIXES: Final = ("(element, ",)
@@ -42,7 +44,9 @@ CONFUSING_STREAMLIT_SIG_PREFIXES: Final = ("(element, ",)
42
44
 
43
45
  class HelpMixin:
44
46
  @gather_metrics("help")
45
- def help(self, obj: Any = streamlit) -> DeltaGenerator:
47
+ def help(
48
+ self, obj: Any = streamlit, *, width: WidthWithoutContent = "stretch"
49
+ ) -> DeltaGenerator:
46
50
  """Display help and other information for a given object.
47
51
 
48
52
  Depending on the type of object that is passed in, this displays the
@@ -54,6 +58,15 @@ class HelpMixin:
54
58
  obj : any
55
59
  The object whose information should be displayed. If left
56
60
  unspecified, this call will display help for Streamlit itself.
61
+ width : "stretch" or int
62
+ The width of the help element. This can be one of the following:
63
+
64
+ - ``"stretch"`` (default): The width of the element matches the
65
+ width of the parent container.
66
+ - An integer specifying the width in pixels: The element has a
67
+ fixed width. If the specified width is greater than the width of
68
+ the parent container, the width of the element matches the width
69
+ of the parent container.
57
70
 
58
71
  Example
59
72
  -------
@@ -115,8 +128,14 @@ class HelpMixin:
115
128
  height: 700px
116
129
  """
117
130
  doc_string_proto = DocStringProto()
131
+
132
+ validate_width(width, allow_content=False)
133
+ layout_config = LayoutConfig(width=width)
118
134
  _marshall(doc_string_proto, obj)
119
- return self.dg._enqueue("doc_string", doc_string_proto)
135
+
136
+ return self.dg._enqueue(
137
+ "doc_string", doc_string_proto, layout_config=layout_config
138
+ )
120
139
 
121
140
  @property
122
141
  def dg(self) -> DeltaGenerator:
@@ -147,38 +166,30 @@ def _marshall(doc_string_proto: DocStringProto, obj: Any) -> None:
147
166
  doc_string_proto.members.extend(_get_members(obj))
148
167
 
149
168
 
150
- def _get_name(obj):
169
+ def _get_name(obj: object) -> str | None:
151
170
  # Try to get the fully-qualified name of the object.
152
- # For example:
153
- # st.help(bar.Baz(123))
154
- #
155
- # The name is bar.Baz
171
+ # For example: st.help(bar.Baz(123))
172
+ # The name is bar.Baz
156
173
  name = getattr(obj, "__qualname__", None)
157
174
  if name:
158
- return name
175
+ return cast("str", name)
159
176
 
160
177
  # Try to get the name of the object.
161
- # For example:
162
- # st.help(bar.Baz(123))
163
- #
178
+ # For example: st.help(bar.Baz(123))
164
179
  # The name is Baz
165
- return getattr(obj, "__name__", None)
180
+ return cast("str | None", getattr(obj, "__name__", None))
166
181
 
167
182
 
168
- def _get_module(obj):
183
+ def _get_module(obj: object) -> str | None:
169
184
  return getattr(obj, "__module__", None)
170
185
 
171
186
 
172
- def _get_signature(obj):
187
+ def _get_signature(obj: object) -> str | None:
173
188
  if not inspect.isclass(obj) and not callable(obj):
174
189
  return None
175
190
 
176
191
  sig = ""
177
192
 
178
- # TODO: Can we replace below with this?
179
- # with contextlib.suppress(ValueError):
180
- # sig = str(inspect.signature(obj))
181
-
182
193
  try:
183
194
  sig = str(inspect.signature(obj))
184
195
  except ValueError:
@@ -202,7 +213,7 @@ def _get_signature(obj):
202
213
  return sig
203
214
 
204
215
 
205
- def _get_docstring(obj):
216
+ def _get_docstring(obj: object) -> str | None:
206
217
  doc_string = inspect.getdoc(obj)
207
218
 
208
219
  # Sometimes an object has no docstring, but the object's type does.
@@ -226,7 +237,7 @@ def _get_docstring(obj):
226
237
  return None
227
238
 
228
239
 
229
- def _get_variable_name():
240
+ def _get_variable_name() -> str | None:
230
241
  """Try to get the name of the variable in the current line, as set by the user.
231
242
 
232
243
  For example:
@@ -243,25 +254,25 @@ def _get_variable_name():
243
254
  return _get_variable_name_from_code_str(code)
244
255
 
245
256
 
246
- def _get_variable_name_from_code_str(code):
257
+ def _get_variable_name_from_code_str(code: str) -> str | None:
247
258
  tree = ast.parse(code)
248
259
 
249
260
  # Example:
250
261
  #
251
- # tree = Module(
252
- # body=[
253
- # Expr(
254
- # value=Call(
255
- # args=[
256
- # Name(id='the variable name')
257
- # ],
258
- # keywords=[
259
- # ???
260
- # ],
261
- # )
262
- # )
263
- # ]
264
- # )
262
+ # > tree = Module(
263
+ # > body=[
264
+ # > Expr(
265
+ # > value=Call(
266
+ # > args=[
267
+ # > Name(id='the variable name')
268
+ # > ],
269
+ # > keywords=[
270
+ # > ???
271
+ # > ],
272
+ # > )
273
+ # > )
274
+ # > ]
275
+ # > )
265
276
 
266
277
  # Check if this is an magic call (i.e. it's not st.help or st.write).
267
278
  # If that's the case, just clean it up and return it.
@@ -270,9 +281,7 @@ def _get_variable_name_from_code_str(code):
270
281
  ):
271
282
  # A common pattern is to add "," at the end of a magic command to make it print.
272
283
  # This removes that final ",", so it looks nicer.
273
- code = code.removesuffix(",")
274
-
275
- return code
284
+ return code.removesuffix(",")
276
285
 
277
286
  arg_node = _get_stcommand_arg(tree)
278
287
 
@@ -282,7 +291,7 @@ def _get_variable_name_from_code_str(code):
282
291
 
283
292
  # If walrus, get name.
284
293
  # E.g. st.help(foo := 123) should give you "foo".
285
- elif type(arg_node) is ast.NamedExpr:
294
+ if type(arg_node) is ast.NamedExpr:
286
295
  # This next "if" will always be true, but need to add this for the type-checking test to
287
296
  # pass.
288
297
  if type(arg_node.target) is ast.Name:
@@ -316,7 +325,7 @@ def _get_variable_name_from_code_str(code):
316
325
  _NEWLINES = re.compile(r"[\n\r]+")
317
326
 
318
327
 
319
- def _get_current_line_of_code_as_str():
328
+ def _get_current_line_of_code_as_str() -> str | None:
320
329
  scriptrunner_frame = _get_scriptrunner_frame()
321
330
 
322
331
  if scriptrunner_frame is None:
@@ -339,7 +348,7 @@ def _get_current_line_of_code_as_str():
339
348
  return re.sub(_NEWLINES, "", code_as_string.strip())
340
349
 
341
350
 
342
- def _get_scriptrunner_frame():
351
+ def _get_scriptrunner_frame() -> inspect.FrameInfo | None:
343
352
  prev_frame = None
344
353
  scriptrunner_frame = None
345
354
 
@@ -362,7 +371,7 @@ def _get_scriptrunner_frame():
362
371
  return scriptrunner_frame
363
372
 
364
373
 
365
- def _is_stcommand(tree, command_name):
374
+ def _is_stcommand(tree: Any, command_name: str) -> bool:
366
375
  """Checks whether the AST in tree is a call for command_name."""
367
376
  root_node = tree.body[0].value
368
377
 
@@ -378,25 +387,25 @@ def _is_stcommand(tree, command_name):
378
387
  )
379
388
 
380
389
 
381
- def _get_stcommand_arg(tree):
390
+ def _get_stcommand_arg(tree: ast.Module) -> ast.expr | None:
382
391
  """Gets the argument node for the st command in tree (AST)."""
383
392
 
384
- root_node = tree.body[0].value
393
+ root_node = tree.body[0].value # type: ignore
385
394
 
386
395
  if root_node.args:
387
- return root_node.args[0]
396
+ return cast("ast.expr", root_node.args[0])
388
397
 
389
398
  return None
390
399
 
391
400
 
392
- def _get_type_as_str(obj):
401
+ def _get_type_as_str(obj: object) -> str:
393
402
  if inspect.isclass(obj):
394
403
  return "class"
395
404
 
396
405
  return str(type(obj).__name__)
397
406
 
398
407
 
399
- def _get_first_line(text):
408
+ def _get_first_line(text: str) -> str:
400
409
  if not text:
401
410
  return ""
402
411
 
@@ -404,7 +413,7 @@ def _get_first_line(text):
404
413
  return left
405
414
 
406
415
 
407
- def _get_weight(value):
416
+ def _get_weight(value: Any) -> int:
408
417
  if inspect.ismodule(value):
409
418
  return 3
410
419
  if inspect.isclass(value):
@@ -414,7 +423,7 @@ def _get_weight(value):
414
423
  return 0
415
424
 
416
425
 
417
- def _get_value(obj, var_name):
426
+ def _get_value(obj: object, var_name: str | None) -> str | None:
418
427
  obj_value = _get_human_readable_value(obj)
419
428
 
420
429
  if obj_value is not None:
@@ -436,10 +445,7 @@ def _get_value(obj, var_name):
436
445
  sig = _get_signature(name_obj) or ""
437
446
 
438
447
  if name:
439
- if module:
440
- obj_value = f"{module}.{name}{sig}"
441
- else:
442
- obj_value = f"{name}{sig}"
448
+ obj_value = f"{module}.{name}{sig}" if module else f"{name}{sig}"
443
449
 
444
450
  if obj_value == var_name:
445
451
  # No need to repeat the same info.
@@ -449,7 +455,7 @@ def _get_value(obj, var_name):
449
455
  return obj_value
450
456
 
451
457
 
452
- def _get_human_readable_value(value):
458
+ def _get_human_readable_value(value: Any) -> str | None:
453
459
  if isinstance(value, Secrets):
454
460
  # Don't want to read secrets.toml because that will show a warning if there's no
455
461
  # secrets.toml file.
@@ -472,12 +478,12 @@ def _get_human_readable_value(value):
472
478
  return _shorten(value_str)
473
479
 
474
480
 
475
- def _shorten(s, length=300):
481
+ def _shorten(s: str, length: int = 300) -> str:
476
482
  s = s.strip()
477
483
  return s[:length] + "..." if len(s) > length else s
478
484
 
479
485
 
480
- def _is_computed_property(obj, attr_name):
486
+ def _is_computed_property(obj: object, attr_name: str) -> bool:
481
487
  obj_class = getattr(obj, "__class__", None)
482
488
 
483
489
  if not obj_class:
@@ -498,7 +504,7 @@ def _is_computed_property(obj, attr_name):
498
504
  return False
499
505
 
500
506
 
501
- def _get_members(obj):
507
+ def _get_members(obj: object) -> list[MemberProto]:
502
508
  members_for_sorting = []
503
509
 
504
510
  for attr_name in dir(obj):
@@ -38,7 +38,11 @@ _LOGGER: Final = get_logger(__name__)
38
38
 
39
39
  # When client.showErrorDetails is False, we show a generic warning in the
40
40
  # frontend when we encounter an uncaught app exception.
41
- _GENERIC_UNCAUGHT_EXCEPTION_TEXT: Final = "This app has encountered an error. The original error message is redacted to prevent data leaks. Full error details have been recorded in the logs (if you're on Streamlit Cloud, click on 'Manage app' in the lower right of your app)."
41
+ _GENERIC_UNCAUGHT_EXCEPTION_TEXT: Final = (
42
+ "This app has encountered an error. The original error message is redacted "
43
+ "to prevent data leaks. Full error details have been recorded in the logs "
44
+ "(if you're on Streamlit Cloud, click on 'Manage app' in the lower right of your app)."
45
+ )
42
46
 
43
47
 
44
48
  class ExceptionMixin:
@@ -56,13 +60,15 @@ class ExceptionMixin:
56
60
  ----------
57
61
  exception : Exception
58
62
  The exception to display.
59
- width : int or "stretch"
60
- The desired width of the exception expressed in pixels. If this is
61
- ``"stretch"`` (default), Streamlit sets the width of the exception
62
- to match the width of the parent container. Otherwise, this must be
63
- an integer. If the specified width is greater than the width of the
64
- parent container, Streamlit sets the width of the exception to
65
- match the width of the parent container.
63
+ width : "stretch" or int
64
+ The width of the exception element. This can be one of the following:
65
+
66
+ - ``"stretch"`` (default): The width of the element matches the
67
+ width of the parent container.
68
+ - An integer specifying the width in pixels: The element has a
69
+ fixed width. If the specified width is greater than the width of
70
+ the parent container, the width of the element matches the width
71
+ of the parent container.
66
72
 
67
73
  Example
68
74
  -------
@@ -228,24 +234,15 @@ def _format_syntax_error_message(exception: SyntaxError) -> str:
228
234
 
229
235
  """
230
236
  if exception.text:
231
- if exception.offset is not None:
232
- caret_indent = " " * max(exception.offset - 1, 0)
233
- else:
234
- caret_indent = ""
237
+ caret_indent = (
238
+ " " * max(exception.offset - 1, 0) if exception.offset is not None else ""
239
+ )
235
240
 
236
241
  return (
237
- 'File "%(filename)s", line %(lineno)s\n'
238
- " %(text)s\n"
239
- " %(caret_indent)s^\n"
240
- "%(errname)s: %(msg)s"
241
- % {
242
- "filename": exception.filename,
243
- "lineno": exception.lineno,
244
- "text": exception.text.rstrip(),
245
- "caret_indent": caret_indent,
246
- "errname": type(exception).__name__,
247
- "msg": exception.msg,
248
- }
242
+ f'File "{exception.filename}", line {exception.lineno}\n'
243
+ f" {exception.text.rstrip()}\n"
244
+ f" {caret_indent}^\n"
245
+ f"{type(exception).__name__}: {exception.msg}"
249
246
  )
250
247
  # If a few edge cases, SyntaxErrors don't have all these nice fields. So we
251
248
  # have a fall back here.
@@ -358,9 +355,8 @@ def _split_list(
358
355
  saw_split_point = False
359
356
 
360
357
  for item in orig_list:
361
- if not saw_split_point:
362
- if split_point(item):
363
- saw_split_point = True
358
+ if not saw_split_point and split_point(item):
359
+ saw_split_point = True
364
360
 
365
361
  if saw_split_point:
366
362
  after.append(item)
@@ -17,6 +17,13 @@ import textwrap
17
17
  from typing import TYPE_CHECKING, Literal, cast
18
18
 
19
19
  from streamlit.elements.lib.form_utils import FormData, current_form_id, is_in_form
20
+ from streamlit.elements.lib.layout_utils import (
21
+ Width,
22
+ get_height_config,
23
+ get_width_config,
24
+ validate_height,
25
+ validate_width,
26
+ )
20
27
  from streamlit.elements.lib.policies import (
21
28
  check_cache_replay_rules,
22
29
  check_session_state_rules,
@@ -67,6 +74,8 @@ class FormMixin:
67
74
  *,
68
75
  enter_to_submit: bool = True,
69
76
  border: bool = True,
77
+ width: Width = "stretch",
78
+ height: int | Literal["content"] = "content",
70
79
  ) -> DeltaGenerator:
71
80
  """Create a form that batches elements together with a "Submit" button.
72
81
 
@@ -122,6 +131,34 @@ class FormMixin:
122
131
  there's another border (e.g. because of an expander) or the form is small
123
132
  (e.g. just a text input and a submit button).
124
133
 
134
+ width : "stretch", "content", or int
135
+ The width of the form container. This can be one of the following:
136
+
137
+ - ``"stretch"`` (default): The width of the container matches the
138
+ width of the parent container.
139
+ - ``"content"``: The width of the container matches the width of its
140
+ content, but doesn't exceed the width of the parent container.
141
+ - An integer specifying the width in pixels: The container has a
142
+ fixed width. If the specified width is greater than the width of
143
+ the parent container, the width of the container matches the width
144
+ of the parent container.
145
+
146
+ height : "content" or int
147
+ The height of the form container. This can be one of the following:
148
+
149
+ - ``"content"`` (default): The height of the container matches the
150
+ height of its content.
151
+ - An integer specifying the height in pixels: The container has a
152
+ fixed height. If the content is larger than the specified
153
+ height, scrolling is enabled.
154
+
155
+ .. note::
156
+ Use scrolling containers sparingly. If you use scrolling
157
+ containers, avoid heights that exceed 500 pixels. Otherwise,
158
+ the scroll surface of the container might cover the majority of
159
+ the screen on mobile devices, which makes it hard to scroll the
160
+ rest of the app.
161
+
125
162
  Examples
126
163
  --------
127
164
  Inserting elements using ``with`` notation:
@@ -181,6 +218,10 @@ class FormMixin:
181
218
  block_proto.form.clear_on_submit = clear_on_submit
182
219
  block_proto.form.enter_to_submit = enter_to_submit
183
220
  block_proto.form.border = border
221
+ validate_width(width, allow_content=True)
222
+ block_proto.width_config.CopyFrom(get_width_config(width))
223
+ validate_height(height, allow_content=True)
224
+ block_proto.height_config.CopyFrom(get_height_config(height))
184
225
  block_dg = self.dg._block(block_proto)
185
226
 
186
227
  # Attach the form's button info to the newly-created block's
@@ -141,7 +141,7 @@ def marshall(
141
141
  engine = "dot"
142
142
  else:
143
143
  raise StreamlitAPIException(
144
- "Unhandled type for graphviz chart: %s" % type(figure_or_dot)
144
+ f"Unhandled type for graphviz chart: {type(figure_or_dot)}"
145
145
  )
146
146
 
147
147
  proto.spec = dot
@@ -19,6 +19,7 @@ from typing import TYPE_CHECKING, Literal, Union, cast
19
19
 
20
20
  from typing_extensions import TypeAlias
21
21
 
22
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
22
23
  from streamlit.errors import StreamlitAPIException
23
24
  from streamlit.proto.Heading_pb2 import Heading as HeadingProto
24
25
  from streamlit.runtime.metrics_util import gather_metrics
@@ -26,6 +27,7 @@ from streamlit.string_util import clean_text
26
27
 
27
28
  if TYPE_CHECKING:
28
29
  from streamlit.delta_generator import DeltaGenerator
30
+ from streamlit.elements.lib.layout_utils import Width
29
31
  from streamlit.type_util import SupportsStr
30
32
 
31
33
 
@@ -48,6 +50,7 @@ class HeadingMixin:
48
50
  *, # keyword-only arguments:
49
51
  help: str | None = None,
50
52
  divider: Divider = False,
53
+ width: Width = "stretch",
51
54
  ) -> DeltaGenerator:
52
55
  """Display text in header formatting.
53
56
 
@@ -76,7 +79,7 @@ class HeadingMixin:
76
79
  including the Markdown directives described in the ``body``
77
80
  parameter of ``st.markdown``.
78
81
 
79
- divider : bool or “blue”, “green”, “orange”, “red”, “violet”, “gray”/"grey", or “rainbow”
82
+ divider : bool, “blue”, “green”, “orange”, “red”, “violet”, “gray”/"grey", or “rainbow”
80
83
  Shows a colored divider below the header. If True, successive
81
84
  headers will cycle through divider colors. That is, the first
82
85
  header will have a blue line, the second header will have a
@@ -84,6 +87,18 @@ class HeadingMixin:
84
87
  the following: blue, green, orange, red, violet, gray/grey, or
85
88
  rainbow.
86
89
 
90
+ width : "stretch", "content", or int
91
+ The width of the header element. This can be one of the following:
92
+
93
+ - ``"stretch"`` (default): The width of the element matches the
94
+ width of the parent container.
95
+ - ``"content"``: The width of the element matches the width of its
96
+ content, but doesn't exceed the width of the parent container.
97
+ - An integer specifying the width in pixels: The element has a
98
+ fixed width. If the specified width is greater than the width of
99
+ the parent container, the width of the element matches the width
100
+ of the parent container.
101
+
87
102
  Examples
88
103
  --------
89
104
  >>> import streamlit as st
@@ -101,6 +116,9 @@ class HeadingMixin:
101
116
  height: 600px
102
117
 
103
118
  """
119
+ validate_width(width, allow_content=True)
120
+ layout_config = LayoutConfig(width=width)
121
+
104
122
  return self.dg._enqueue(
105
123
  "heading",
106
124
  HeadingMixin._create_heading_proto(
@@ -110,6 +128,7 @@ class HeadingMixin:
110
128
  help=help,
111
129
  divider=divider,
112
130
  ),
131
+ layout_config=layout_config,
113
132
  )
114
133
 
115
134
  @gather_metrics("subheader")
@@ -120,6 +139,7 @@ class HeadingMixin:
120
139
  *, # keyword-only arguments:
121
140
  help: str | None = None,
122
141
  divider: Divider = False,
142
+ width: Width = "stretch",
123
143
  ) -> DeltaGenerator:
124
144
  """Display text in subheader formatting.
125
145
 
@@ -156,6 +176,18 @@ class HeadingMixin:
156
176
  the following: blue, green, orange, red, violet, gray/grey, or
157
177
  rainbow.
158
178
 
179
+ width : "stretch", "content", or int
180
+ The width of the subheader element. This can be one of the following:
181
+
182
+ - ``"stretch"`` (default): The width of the element matches the
183
+ width of the parent container.
184
+ - ``"content"``: The width of the element matches the width of its
185
+ content, but doesn't exceed the width of the parent container.
186
+ - An integer specifying the width in pixels: The element has a
187
+ fixed width. If the specified width is greater than the width of
188
+ the parent container, the width of the element matches the width
189
+ of the parent container.
190
+
159
191
  Examples
160
192
  --------
161
193
  >>> import streamlit as st
@@ -173,6 +205,9 @@ class HeadingMixin:
173
205
  height: 500px
174
206
 
175
207
  """
208
+ validate_width(width, allow_content=True)
209
+ layout_config = LayoutConfig(width=width)
210
+
176
211
  return self.dg._enqueue(
177
212
  "heading",
178
213
  HeadingMixin._create_heading_proto(
@@ -182,6 +217,7 @@ class HeadingMixin:
182
217
  help=help,
183
218
  divider=divider,
184
219
  ),
220
+ layout_config=layout_config,
185
221
  )
186
222
 
187
223
  @gather_metrics("title")
@@ -191,6 +227,7 @@ class HeadingMixin:
191
227
  anchor: Anchor = None,
192
228
  *, # keyword-only arguments:
193
229
  help: str | None = None,
230
+ width: Width = "stretch",
194
231
  ) -> DeltaGenerator:
195
232
  """Display text in title formatting.
196
233
 
@@ -222,6 +259,18 @@ class HeadingMixin:
222
259
  including the Markdown directives described in the ``body``
223
260
  parameter of ``st.markdown``.
224
261
 
262
+ width : "stretch", "content", or int
263
+ The width of the title element. This can be one of the following:
264
+
265
+ - ``"stretch"`` (default): The width of the element matches the
266
+ width of the parent container.
267
+ - ``"content"``: The width of the element matches the width of its
268
+ content, but doesn't exceed the width of the parent container.
269
+ - An integer specifying the width in pixels: The element has a
270
+ fixed width. If the specified width is greater than the width of
271
+ the parent container, the width of the element matches the width
272
+ of the parent container.
273
+
225
274
  Examples
226
275
  --------
227
276
  >>> import streamlit as st
@@ -234,11 +283,15 @@ class HeadingMixin:
234
283
  height: 220px
235
284
 
236
285
  """
286
+ validate_width(width, allow_content=True)
287
+ layout_config = LayoutConfig(width=width)
288
+
237
289
  return self.dg._enqueue(
238
290
  "heading",
239
291
  HeadingMixin._create_heading_proto(
240
292
  tag=HeadingProtoTag.TITLE_TAG, body=body, anchor=anchor, help=help
241
293
  ),
294
+ layout_config=layout_config,
242
295
  )
243
296
 
244
297
  @property
@@ -262,10 +315,9 @@ class HeadingMixin:
262
315
  ]
263
316
  if divider in valid_colors:
264
317
  return cast("str", divider)
265
- else:
266
- raise StreamlitAPIException(
267
- f"Divider parameter has invalid value: `{divider}`. Please choose from: {', '.join(valid_colors)}."
268
- )
318
+ raise StreamlitAPIException(
319
+ f"Divider parameter has invalid value: `{divider}`. Please choose from: {', '.join(valid_colors)}."
320
+ )
269
321
 
270
322
  @staticmethod
271
323
  def _create_heading_proto(
@@ -287,14 +339,13 @@ class HeadingMixin:
287
339
  proto.anchor = anchor
288
340
  elif anchor is True: # type: ignore
289
341
  raise StreamlitAPIException(
290
- "Anchor parameter has invalid value: %s. "
291
- "Supported values: None, any string or False" % anchor
342
+ f"Anchor parameter has invalid value: {anchor}. "
343
+ "Supported values: None, any string or False"
292
344
  )
293
345
  else:
294
346
  raise StreamlitAPIException(
295
- "Anchor parameter has invalid type: %s. "
347
+ f"Anchor parameter has invalid type: {type(anchor).__name__}. "
296
348
  "Supported values: None, any string or False"
297
- % type(anchor).__name__
298
349
  )
299
350
 
300
351
  if help:
@@ -113,10 +113,9 @@ class HtmlMixin:
113
113
  # If true, there are only style tags - send html to the event container
114
114
  html_proto.body = html_content
115
115
  return self._event_dg._enqueue("html", html_proto)
116
- else:
117
- # Otherwise, send the html to the main container as normal
118
- html_proto.body = html_content
119
- return self.dg._enqueue("html", html_proto)
116
+ # Otherwise, send the html to the main container as normal
117
+ html_proto.body = html_content
118
+ return self.dg._enqueue("html", html_proto)
120
119
 
121
120
  @property
122
121
  def dg(self) -> DeltaGenerator: