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
streamlit/config.py CHANGED
@@ -54,6 +54,9 @@ _config_options_template: dict[str, ConfigOption] = OrderedDict()
54
54
  # Stores the current state of config options.
55
55
  _config_options: dict[str, ConfigOption] | None = None
56
56
 
57
+ # Stores the path to the main script. This is used to
58
+ # resolve config and secret files relative to the main script:
59
+ _main_script_path: str | None = None
57
60
 
58
61
  # Indicates that a config option was defined by the user.
59
62
  _USER_DEFINED: Final = "<user defined>"
@@ -77,11 +80,11 @@ class ShowErrorDetailsConfigOptions(str, Enum):
77
80
  NONE = "none"
78
81
 
79
82
  @staticmethod
80
- def is_true_variation(val: str | bool):
83
+ def is_true_variation(val: str | bool) -> bool:
81
84
  return val in ["true", "True", True]
82
85
 
83
86
  @staticmethod
84
- def is_false_variation(val: str | bool):
87
+ def is_false_variation(val: str | bool) -> bool:
85
88
  return val in ["false", "False", False]
86
89
 
87
90
  # Config options can be set from several places including the command-line and
@@ -167,7 +170,7 @@ def set_user_option(key: str, value: Any) -> None:
167
170
 
168
171
  raise StreamlitAPIException(
169
172
  f"{key} cannot be set on the fly. Set as command line option, e.g. "
170
- "streamlit run script.py --{key}, or in config.toml instead."
173
+ f"streamlit run script.py --{key}, or in config.toml instead."
171
174
  )
172
175
 
173
176
 
@@ -226,9 +229,8 @@ def get_options_for_section(section: str) -> dict[str, Any]:
226
229
 
227
230
  def _create_section(section: str, description: str) -> None:
228
231
  """Create a config section and store it globally in this module."""
229
- assert section not in _section_descriptions, (
230
- f'Cannot define section "{section}" twice.'
231
- )
232
+ if section in _section_descriptions:
233
+ raise RuntimeError(f'Cannot define section "{section}" twice.')
232
234
  _section_descriptions[section] = description
233
235
 
234
236
 
@@ -244,6 +246,7 @@ def _create_option(
244
246
  replaced_by: str | None = None,
245
247
  type_: type = str,
246
248
  sensitive: bool = False,
249
+ multiple: bool = False,
247
250
  ) -> ConfigOption:
248
251
  '''Create a ConfigOption and store it globally in this module.
249
252
 
@@ -292,14 +295,14 @@ def _create_option(
292
295
  replaced_by=replaced_by,
293
296
  type_=type_,
294
297
  sensitive=sensitive,
298
+ multiple=multiple,
295
299
  )
296
- assert option.section in _section_descriptions, (
297
- 'Section "{}" must be one of {}.'.format(
298
- option.section,
299
- ", ".join(_section_descriptions.keys()),
300
+ if option.section not in _section_descriptions:
301
+ raise RuntimeError(
302
+ f'Section "{option.section}" must be one of {", ".join(_section_descriptions.keys())}.'
300
303
  )
301
- )
302
- assert key not in _config_options_template, f'Cannot define option "{key}" twice.'
304
+ if key in _config_options_template:
305
+ raise RuntimeError(f'Cannot define option "{key}" twice.')
303
306
  _config_options_template[key] = option
304
307
  return option
305
308
 
@@ -342,13 +345,15 @@ def _delete_option(key: str) -> None:
342
345
 
343
346
  Only for use in testing.
344
347
  """
348
+ if _config_options is None:
349
+ raise RuntimeError(
350
+ "_config_options should always be populated here. This should never happen."
351
+ )
352
+
345
353
  try:
346
354
  del _config_options_template[key]
347
- assert _config_options is not None, (
348
- "_config_options should always be populated here."
349
- )
350
355
  del _config_options[key]
351
- except Exception:
356
+ except Exception: # noqa: S110
352
357
  # We don't care if the option already doesn't exist.
353
358
  pass
354
359
 
@@ -384,6 +389,7 @@ _create_option(
384
389
 
385
390
 
386
391
  @_create_option("global.developmentMode", visibility="hidden", type_=bool)
392
+ @util.memoize
387
393
  def _global_development_mode() -> bool:
388
394
  """Are we in development mode.
389
395
 
@@ -466,8 +472,7 @@ def _logger_log_level() -> str:
466
472
  """
467
473
  if get_option("global.developmentMode"):
468
474
  return "debug"
469
- else:
470
- return "info"
475
+ return "info"
471
476
 
472
477
 
473
478
  @_create_option("logger.messageFormat", type_=str)
@@ -484,8 +489,7 @@ def _logger_message_format() -> str:
484
489
  from streamlit.logger import DEFAULT_LOG_MESSAGE
485
490
 
486
491
  return DEFAULT_LOG_MESSAGE
487
- else:
488
- return "%(asctime)s %(message)s"
492
+ return "%(asctime)s %(message)s"
489
493
 
490
494
 
491
495
  @_create_option(
@@ -494,6 +498,7 @@ def _logger_message_format() -> str:
494
498
  type_=bool,
495
499
  scriptable=True,
496
500
  )
501
+ @util.memoize
497
502
  def _logger_enable_rich() -> bool:
498
503
  """
499
504
  Controls whether uncaught app exceptions are logged via the rich library.
@@ -605,8 +610,9 @@ _create_option(
605
610
  _create_option(
606
611
  "runner.postScriptGC",
607
612
  description="""
608
- Run the Python Garbage Collector after each script execution. This
609
- can help avoid excess memory use in Streamlit apps, but could
613
+ Run the Python Garbage Collector after each script execution.
614
+
615
+ This can help avoid excess memory use in Streamlit apps, but could
610
616
  introduce delay in rerunning the app script for high-memory-use
611
617
  applications.
612
618
  """,
@@ -618,11 +624,12 @@ _create_option(
618
624
  _create_option(
619
625
  "runner.fastReruns",
620
626
  description="""
621
- Handle script rerun requests immediately, rather than waiting for script
622
- execution to reach a yield point. This makes Streamlit much more
623
- responsive to user interaction, but it can lead to race conditions in
624
- apps that mutate session_state data outside of explicit session_state
625
- assignment statements.
627
+ Handle script rerun requests immediately, rather than waiting for
628
+ script execution to reach a yield point.
629
+
630
+ This makes Streamlit much more responsive to user interaction, but it
631
+ can lead to race conditions in apps that mutate session_state data
632
+ outside of explicit session_state assignment statements.
626
633
  """,
627
634
  default_val=True,
628
635
  type_=bool,
@@ -632,6 +639,7 @@ _create_option(
632
639
  "runner.enforceSerializableSessionState",
633
640
  description="""
634
641
  Raise an exception after adding unserializable data to Session State.
642
+
635
643
  Some execution environments may require serializing all data in Session
636
644
  State, so it may be useful to detect incompatibility during development,
637
645
  or when the execution environment will stop supporting it in the future.
@@ -644,8 +652,10 @@ _create_option(
644
652
  "runner.enumCoercion",
645
653
  description="""
646
654
  Adjust how certain 'options' widgets like radio, selectbox, and
647
- multiselect coerce Enum members when the Enum class gets re-defined
648
- during a script re-run. For more information, check out the docs:
655
+ multiselect coerce Enum members.
656
+
657
+ This is useful when the Enum class gets re-defined during a script
658
+ re-run. For more information, check out the docs:
649
659
  https://docs.streamlit.io/develop/concepts/design/custom-classes#enums
650
660
 
651
661
  Allowed values:
@@ -662,16 +672,34 @@ _create_option(
662
672
 
663
673
  _create_section("server", "Settings for the Streamlit server")
664
674
 
675
+
676
+ _create_option(
677
+ "server.folderWatchList",
678
+ description="""
679
+ List of directories to watch for changes.
680
+
681
+ By default, Streamlit watches files in the current working directory
682
+ and its subdirectories. Use this option to specify additional
683
+ directories to watch. Paths must be absolute.
684
+ """,
685
+ default_val=[],
686
+ multiple=True,
687
+ )
688
+
665
689
  _create_option(
666
690
  "server.folderWatchBlacklist",
667
691
  description="""
668
- List of folders that should not be watched for changes.
692
+ List of directories to ignore for changes.
669
693
 
670
- Relative paths will be taken as relative to the current working directory.
694
+ By default, Streamlit watches files in the current working directory
695
+ and its subdirectories. Use this option to specify exceptions within
696
+ watched directories. Paths can be absolute or relative to the current
697
+ working directory.
671
698
 
672
699
  Example: ['/home/user1/env', 'relative/path/to/folder']
673
700
  """,
674
701
  default_val=[],
702
+ multiple=True,
675
703
  )
676
704
 
677
705
  _create_option(
@@ -711,15 +739,12 @@ def _server_headless() -> bool:
711
739
  Default: false unless (1) we are on a Linux box where DISPLAY is unset, or
712
740
  (2) we are running in the Streamlit Atom plugin.
713
741
  """
714
- if (
742
+ # Check if we are running in Linux and DISPLAY is unset
743
+ return (
715
744
  env_util.IS_LINUX_OR_BSD
716
745
  and not os.getenv("DISPLAY")
717
746
  and not os.getenv("WAYLAND_DISPLAY")
718
- ):
719
- # We're running in Linux and DISPLAY is unset
720
- return True
721
-
722
- return False
747
+ )
723
748
 
724
749
 
725
750
  _create_option(
@@ -745,7 +770,9 @@ _create_option(
745
770
  @_create_option("server.address")
746
771
  def _server_address() -> str | None:
747
772
  """The address where the server will listen for client and browser
748
- connections. Use this if you want to bind the server to a specific address.
773
+ connections.
774
+
775
+ Use this if you want to bind the server to a specific address.
749
776
  If set, the server will only be accessible from this address, and not from
750
777
  any aliases (like localhost).
751
778
 
@@ -758,8 +785,6 @@ _create_option(
758
785
  "server.port",
759
786
  description="""
760
787
  The port where the server will listen for browser connections.
761
-
762
- Don't use port 3000 which is reserved for internal development.
763
788
  """,
764
789
  default_val=8501,
765
790
  type_=int,
@@ -803,6 +828,22 @@ _create_option(
803
828
  type_=bool,
804
829
  )
805
830
 
831
+ _create_option(
832
+ "server.corsAllowedOrigins",
833
+ description="""
834
+ Allowed list of origins.
835
+
836
+ If CORS protection is enabled (`server.enableCORS=True`), use this
837
+ option to set a list of allowed origins that the Streamlit server will
838
+ accept traffic from.
839
+
840
+ This config option does nothing if CORS protection is disabled.
841
+
842
+ Example: ['http://example.com', 'https://streamlit.io']
843
+ """,
844
+ default_val=[],
845
+ multiple=True,
846
+ )
806
847
 
807
848
  _create_option(
808
849
  "server.enableXsrfProtection",
@@ -873,9 +914,11 @@ _create_option(
873
914
  _create_option(
874
915
  "server.disconnectedSessionTTL",
875
916
  description="""
876
- TTL in seconds for sessions whose websockets have been disconnected. The server
877
- may choose to clean up session state, uploaded files, etc for a given session
878
- with no active websocket connection at any point after this time has passed.
917
+ TTL in seconds for sessions whose websockets have been disconnected.
918
+
919
+ The server may choose to clean up session state, uploaded files, etc
920
+ for a given session with no active websocket connection at any point
921
+ after this time has passed.
879
922
  """,
880
923
  default_val=120,
881
924
  type_=int,
@@ -923,8 +966,7 @@ def _browser_server_port() -> int:
923
966
  - Open the browser automatically (part of `streamlit run`).
924
967
 
925
968
  This option is for advanced use cases. To change the port of your app, use
926
- `server.Port` instead. Don't use port 3000 which is reserved for internal
927
- development.
969
+ `server.Port` instead.
928
970
 
929
971
  Default: whatever value is set in server.port.
930
972
  """
@@ -985,13 +1027,18 @@ _create_section("mapbox", "Mapbox configuration that is being used by DeckGL.")
985
1027
  _create_option(
986
1028
  "mapbox.token",
987
1029
  description="""
988
- Configure Streamlit to use a custom Mapbox
989
- token for elements like st.pydeck_chart and st.map.
990
- To get a token for yourself, create an account at
991
- https://mapbox.com. It's free (for moderate usage levels)!
1030
+ If you'd like to show maps using Mapbox rather than Carto, use this
1031
+ to pass the Mapbox API token.
992
1032
  """,
993
1033
  default_val="",
1034
+ type_=str,
994
1035
  sensitive=True,
1036
+ deprecated=True,
1037
+ deprecation_text="""
1038
+ Instead of this, you should use either the MAPBOX_API_KEY environment
1039
+ variable or PyDeck's `api_keys` argument.
1040
+ """,
1041
+ expiration_date="2026-05-01",
995
1042
  )
996
1043
 
997
1044
 
@@ -1041,6 +1088,7 @@ _create_theme_options(
1041
1088
  categories=["theme"],
1042
1089
  description="""
1043
1090
  The preset Streamlit theme that your custom theme inherits from.
1091
+
1044
1092
  This can be one of the following: "light" or "dark".
1045
1093
  """,
1046
1094
  )
@@ -1097,16 +1145,19 @@ _create_theme_options(
1097
1145
  "font",
1098
1146
  categories=["theme", CustomThemeCategories.SIDEBAR],
1099
1147
  description="""
1100
- The font family for all text, except code blocks. This can be one of
1101
- the following:
1148
+ The font family for all text, except code blocks.
1149
+
1150
+ This can be one of the following:
1102
1151
  - "sans-serif"
1103
1152
  - "serif"
1104
1153
  - "monospace"
1105
- - the `font` value for a custom font table under [[theme.fontFaces]]
1106
- - a comma-separated list of these (as a single string) to specify
1154
+ - The `family` value for a custom font table under [[theme.fontFaces]]
1155
+ - A comma-separated list of these (as a single string) to specify
1107
1156
  fallbacks
1157
+
1108
1158
  For example, you can use the following:
1109
- font = "cool-font, fallback-cool-font, sans-serif"
1159
+
1160
+ font = "cool-font, fallback-cool-font, sans-serif"
1110
1161
  """,
1111
1162
  )
1112
1163
 
@@ -1114,28 +1165,45 @@ _create_theme_options(
1114
1165
  "codeFont",
1115
1166
  categories=["theme", CustomThemeCategories.SIDEBAR],
1116
1167
  description="""
1117
- The font family to use for code (monospace) in the sidebar. This can be
1118
- one of the following:
1168
+ The font family to use for code (monospace) in the sidebar.
1169
+
1170
+ This can be one of the following:
1119
1171
  - "sans-serif"
1120
1172
  - "serif"
1121
1173
  - "monospace"
1122
- - the `font` value for a custom font table under [[theme.fontFaces]]
1123
- - a comma-separated list of these (as a single string) to specify
1174
+ - The `family` value for a custom font table under [[theme.fontFaces]]
1175
+ - A comma-separated list of these (as a single string) to specify
1124
1176
  fallbacks
1125
1177
  """,
1126
1178
  )
1127
1179
 
1180
+ _create_theme_options(
1181
+ "codeFontSize",
1182
+ categories=["theme", CustomThemeCategories.SIDEBAR],
1183
+ description="""
1184
+ Sets the font size (in pixels or rem) for code blocks and code text.
1185
+
1186
+ This applies to code blocks (ex: `st.code`), as well as font in `st.json` and `st.help`.
1187
+ It does not apply to inline code, which is set by default to 0.75em.
1188
+
1189
+ When unset, the code font size will be 0.875rem.
1190
+ """,
1191
+ )
1192
+
1128
1193
  _create_theme_options(
1129
1194
  "headingFont",
1130
1195
  categories=["theme", CustomThemeCategories.SIDEBAR],
1131
1196
  description="""
1132
- The font family to use for headings. This can be one of the following:
1197
+ The font family to use for headings.
1198
+
1199
+ This can be one of the following:
1133
1200
  - "sans-serif"
1134
1201
  - "serif"
1135
1202
  - "monospace"
1136
- - the `font` value for a custom font table under [[theme.fontFaces]]
1137
- - a comma-separated list of these (as a single string) to specify
1203
+ - The `family` value for a custom font table under [[theme.fontFaces]]
1204
+ - A comma-separated list of these (as a single string) to specify
1138
1205
  fallbacks
1206
+
1139
1207
  If no heading font is set, Streamlit uses `theme.font` for headings.
1140
1208
  """,
1141
1209
  )
@@ -1144,19 +1212,30 @@ _create_theme_options(
1144
1212
  "fontFaces",
1145
1213
  categories=["theme"],
1146
1214
  description="""
1147
- An array of fonts to use in your app. Each font in the array is a table
1148
- (dictionary) with the following three attributes: font, url, weight,
1149
- and style. To host a font with your app, enable static file serving
1150
- with `server.enableStaticServing=true`. You can define multiple
1151
- [[theme.fontFaces]] tables.
1152
-
1153
- For example, each font is defined in a [[theme.fontFaces]] table as
1154
- follows:
1155
- [[theme.fontFaces]]
1156
- font = "font_name"
1157
- url = "app/static/font_file.woff"
1158
- weight = 400
1159
- style = "normal"
1215
+ An array of fonts to use in your app.
1216
+
1217
+ Each font in the array is a table (dictionary) that can have the
1218
+ following attributes, closely resembling CSS font-face definitions:
1219
+ - family
1220
+ - url
1221
+ - weight (optional)
1222
+ - style (optional)
1223
+ - unicodeRange (optional)
1224
+
1225
+ To host a font with your app, enable static file serving with
1226
+ `server.enableStaticServing=true`.
1227
+
1228
+ You can define multiple [[theme.fontFaces]] tables, including multiple
1229
+ tables with the same family if your font is defined by multiple files.
1230
+
1231
+ For example, a font hosted with your app may have a [[theme.fontFaces]]
1232
+ table as follows:
1233
+
1234
+ [[theme.fontFaces]]
1235
+ family = "font_name"
1236
+ url = "app/static/font_file.woff"
1237
+ weight = "400"
1238
+ style = "normal"
1160
1239
  """,
1161
1240
  )
1162
1241
 
@@ -1164,11 +1243,39 @@ _create_theme_options(
1164
1243
  "baseRadius",
1165
1244
  categories=["theme", CustomThemeCategories.SIDEBAR],
1166
1245
  description="""
1167
- The radius used as basis for the corners of most UI elements. This can
1168
- be one of the following: "none", "small", "medium", "large", "full",
1169
- or the number in pixels or rem. For example, you can use "10px",
1170
- "0.5rem", or "2rem". To follow best practices, use rem instead of
1171
- pixels when specifying a numeric size.
1246
+ The radius used as basis for the corners of most UI elements.
1247
+
1248
+ This can be one of the following:
1249
+ - "none"
1250
+ - "small"
1251
+ - "medium"
1252
+ - "large"
1253
+ - "full"
1254
+ - The number in pixels or rem.
1255
+
1256
+ For example, you can use "10px", "0.5rem", or "2rem". To follow best
1257
+ practices, use rem instead of pixels when specifying a numeric size.
1258
+ """,
1259
+ )
1260
+
1261
+ _create_theme_options(
1262
+ "buttonRadius",
1263
+ categories=["theme", CustomThemeCategories.SIDEBAR],
1264
+ description="""
1265
+ The radius used as basis for the corners of buttons.
1266
+
1267
+ This can be one of the following:
1268
+ - "none"
1269
+ - "small"
1270
+ - "medium"
1271
+ - "large"
1272
+ - "full"
1273
+ - The number in pixels or rem.
1274
+
1275
+ For example, you can use "10px", "0.5rem", or "2rem". To follow best
1276
+ practices, use rem instead of pixels when specifying a numeric size.
1277
+
1278
+ If no button radius is set, Streamlit uses `theme.baseRadius` instead.
1172
1279
  """,
1173
1280
  )
1174
1281
 
@@ -1180,6 +1287,17 @@ _create_theme_options(
1180
1287
  """,
1181
1288
  )
1182
1289
 
1290
+ _create_theme_options(
1291
+ "dataframeBorderColor",
1292
+ categories=["theme", CustomThemeCategories.SIDEBAR],
1293
+ description="""
1294
+ The color of the border around dataframes and tables.
1295
+
1296
+ If no dataframe border color is set, Streamlit uses `theme.borderColor`
1297
+ instead.
1298
+ """,
1299
+ )
1300
+
1183
1301
  _create_theme_options(
1184
1302
  "showWidgetBorder",
1185
1303
  categories=["theme", CustomThemeCategories.SIDEBAR],
@@ -1193,8 +1311,11 @@ _create_theme_options(
1193
1311
  "baseFontSize",
1194
1312
  categories=["theme"],
1195
1313
  description="""
1196
- Sets the root font size (in pixels) for the app, which determines the
1197
- overall scale of text and UI elements. The default base font size is 16.
1314
+ Sets the root font size (in pixels) for the app.
1315
+
1316
+ This determines the overall scale of text and UI elements.
1317
+
1318
+ When unset, the font size will be 16px.
1198
1319
  """,
1199
1320
  type_=int,
1200
1321
  )
@@ -1213,21 +1334,17 @@ _create_theme_options(
1213
1334
 
1214
1335
  _create_section("secrets", "Secrets configuration.")
1215
1336
 
1216
- _create_option(
1217
- "secrets.files",
1218
- description="""
1219
- List of locations where secrets are searched. An entry can be a path to a
1220
- TOML file or directory path where Kubernetes style secrets are saved.
1221
- Order is important, import is first to last, so secrets in later files
1222
- will take precedence over earlier ones.
1223
- """,
1224
- default_val=[
1225
- # NOTE: The order here is important! Project-level secrets should overwrite
1226
- # global secrets.
1227
- file_util.get_streamlit_file_path("secrets.toml"),
1228
- file_util.get_project_streamlit_file_path("secrets.toml"),
1229
- ],
1230
- )
1337
+
1338
+ @_create_option("secrets.files", multiple=True)
1339
+ def _secrets_files() -> list[str]:
1340
+ """List of locations where secrets are searched.
1341
+
1342
+ An entry can be a path to a TOML file or directory path where
1343
+ Kubernetes style secrets are saved. Order is important, import is
1344
+ first to last, so secrets in later files will take precedence over
1345
+ earlier ones.
1346
+ """
1347
+ return get_config_files("secrets.toml")
1231
1348
 
1232
1349
 
1233
1350
  def get_where_defined(key: str) -> str:
@@ -1243,7 +1360,8 @@ def get_where_defined(key: str) -> str:
1243
1360
  config_options = get_config_options()
1244
1361
 
1245
1362
  if key not in config_options:
1246
- raise RuntimeError('Config key "%s" not defined.' % key)
1363
+ msg = f'Config key "{key}" not defined.'
1364
+ raise RuntimeError(msg)
1247
1365
  return config_options[key].where_defined
1248
1366
 
1249
1367
 
@@ -1289,9 +1407,10 @@ def is_manually_set(option_name: str) -> bool:
1289
1407
  def show_config() -> None:
1290
1408
  """Print all config options to the terminal."""
1291
1409
  with _config_lock:
1292
- assert _config_options is not None, (
1293
- "_config_options should always be populated here."
1294
- )
1410
+ if _config_options is None:
1411
+ raise RuntimeError(
1412
+ "_config_options should always be populated here. This should never happen."
1413
+ )
1295
1414
  config_util.show_config(_section_descriptions, _config_options)
1296
1415
 
1297
1416
 
@@ -1314,25 +1433,28 @@ def _set_option(key: str, value: Any, where_defined: str) -> None:
1314
1433
  Tells the config system where this was set.
1315
1434
 
1316
1435
  """
1317
- assert _config_options is not None, (
1318
- "_config_options should always be populated here."
1319
- )
1436
+ if _config_options is None:
1437
+ raise RuntimeError("_config_options should always be populated here.")
1438
+
1320
1439
  if key not in _config_options:
1321
1440
  # Import logger locally to prevent circular references
1322
1441
  from streamlit.logger import get_logger
1323
1442
 
1324
- LOGGER = get_logger(__name__)
1443
+ logger: Final = get_logger(__name__)
1325
1444
 
1326
- LOGGER.warning(
1327
- f'"{key}" is not a valid config option. If you previously had this config '
1328
- "option set, it may have been removed."
1445
+ logger.warning(
1446
+ '"%s" is not a valid config option. If you previously had this config '
1447
+ "option set, it may have been removed.",
1448
+ key,
1329
1449
  )
1330
1450
 
1331
1451
  else:
1332
1452
  _config_options[key].set_value(value, where_defined)
1333
1453
 
1334
1454
 
1335
- def _update_config_with_sensitive_env_var(config_options: dict[str, ConfigOption]):
1455
+ def _update_config_with_sensitive_env_var(
1456
+ config_options: dict[str, ConfigOption],
1457
+ ) -> None:
1336
1458
  """Update the config system by parsing the environment variable.
1337
1459
 
1338
1460
  This should only be called from get_config_options.
@@ -1444,9 +1566,9 @@ def _maybe_read_env_variable(value: Any) -> Any:
1444
1566
  # Import logger locally to prevent circular references
1445
1567
  from streamlit.logger import get_logger
1446
1568
 
1447
- LOGGER = get_logger(__name__)
1569
+ logger: Final = get_logger(__name__)
1448
1570
 
1449
- LOGGER.error("No environment variable called %s", var_name)
1571
+ logger.error("No environment variable called %s", var_name)
1450
1572
  else:
1451
1573
  return _maybe_convert_to_number(env_var)
1452
1574
 
@@ -1457,12 +1579,12 @@ def _maybe_convert_to_number(v: Any) -> Any:
1457
1579
  """Convert v to int or float, or leave it as is."""
1458
1580
  try:
1459
1581
  return int(v)
1460
- except Exception:
1582
+ except Exception: # noqa: S110
1461
1583
  pass
1462
1584
 
1463
1585
  try:
1464
1586
  return float(v)
1465
- except Exception:
1587
+ except Exception: # noqa: S110
1466
1588
  pass
1467
1589
 
1468
1590
  return v
@@ -1472,14 +1594,34 @@ def _maybe_convert_to_number(v: Any) -> Any:
1472
1594
  # something.
1473
1595
  _on_config_parsed = Signal(doc="Emitted when the config file is parsed.")
1474
1596
 
1475
- CONFIG_FILENAMES = [
1476
- file_util.get_streamlit_file_path("config.toml"),
1477
- file_util.get_project_streamlit_file_path("config.toml"),
1478
- ]
1597
+
1598
+ def get_config_files(file_name: str) -> list[str]:
1599
+ """Return the list of config files (e.g. config.toml or secrets.toml) to be parsed.
1600
+
1601
+ Order is important, import is first to last, so options in later files
1602
+ will take precedence over earlier ones.
1603
+ """
1604
+ # script-level config files overwrite project-level config
1605
+ # files, which in turn overwrite global config files.
1606
+ config_files = [
1607
+ file_util.get_streamlit_file_path(file_name),
1608
+ file_util.get_project_streamlit_file_path(file_name),
1609
+ ]
1610
+
1611
+ if _main_script_path is not None:
1612
+ script_level_config = file_util.get_main_script_streamlit_file_path(
1613
+ _main_script_path, file_name
1614
+ )
1615
+ if script_level_config not in config_files:
1616
+ # We need to append the script-level config file to the list
1617
+ # so that it overwrites project & global level config files:
1618
+ config_files.append(script_level_config)
1619
+
1620
+ return config_files
1479
1621
 
1480
1622
 
1481
1623
  def get_config_options(
1482
- force_reparse=False, options_from_flags: dict[str, Any] | None = None
1624
+ force_reparse: bool = False, options_from_flags: dict[str, Any] | None = None
1483
1625
  ) -> dict[str, ConfigOption]:
1484
1626
  """Create and return a dict mapping config option names to their values,
1485
1627
  returning a cached dict if possible.
@@ -1526,12 +1668,12 @@ def get_config_options(
1526
1668
 
1527
1669
  # Values set in files later in the CONFIG_FILENAMES list overwrite those
1528
1670
  # set earlier.
1529
- for filename in CONFIG_FILENAMES:
1671
+ for filename in get_config_files("config.toml"):
1530
1672
  if not os.path.exists(filename):
1531
1673
  continue
1532
1674
 
1533
- with open(filename, encoding="utf-8") as input:
1534
- file_contents = input.read()
1675
+ with open(filename, encoding="utf-8") as file:
1676
+ file_contents = file.read()
1535
1677
 
1536
1678
  _update_config_with_toml(file_contents, filename)
1537
1679
 
@@ -1546,8 +1688,8 @@ def get_config_options(
1546
1688
  # Import logger locally to prevent circular references.
1547
1689
  from streamlit.logger import get_logger
1548
1690
 
1549
- LOGGER = get_logger(__name__)
1550
- LOGGER.warning(
1691
+ logger: Final = get_logger(__name__)
1692
+ logger.warning(
1551
1693
  "An update to the [server] config option section was detected."
1552
1694
  " To have these changes be reflected, please restart streamlit."
1553
1695
  )
@@ -1561,28 +1703,31 @@ def _check_conflicts() -> None:
1561
1703
 
1562
1704
  # When using the Node server, we must always connect to 8501 (this is
1563
1705
  # hard-coded in JS). Otherwise, the browser would decide what port to
1564
- # connect to based on window.location.port, which in dev is going to
1565
- # be (3000)
1706
+ # connect to based on window.location.port, which in dev is going
1707
+ # to be 3000.
1566
1708
 
1567
1709
  # Import logger locally to prevent circular references
1568
1710
  from streamlit.logger import get_logger
1569
1711
 
1570
- LOGGER = get_logger(__name__)
1712
+ logger: Final = get_logger(__name__)
1571
1713
 
1572
1714
  if get_option("global.developmentMode"):
1573
- assert _is_unset("server.port"), (
1574
- "server.port does not work when global.developmentMode is true."
1575
- )
1715
+ if not _is_unset("server.port"):
1716
+ raise RuntimeError(
1717
+ "server.port does not work when global.developmentMode is true."
1718
+ )
1576
1719
 
1577
- assert _is_unset("browser.serverPort"), (
1578
- "browser.serverPort does not work when global.developmentMode is true."
1579
- )
1720
+ if not _is_unset("browser.serverPort"):
1721
+ raise RuntimeError(
1722
+ "browser.serverPort does not work when global.developmentMode is true."
1723
+ )
1580
1724
 
1581
1725
  # XSRF conflicts
1582
- if get_option("server.enableXsrfProtection"):
1583
- if not get_option("server.enableCORS") or get_option("global.developmentMode"):
1584
- LOGGER.warning(
1585
- """
1726
+ if get_option("server.enableXsrfProtection") and (
1727
+ not get_option("server.enableCORS") or get_option("global.developmentMode")
1728
+ ):
1729
+ logger.warning(
1730
+ """
1586
1731
  Warning: the config option 'server.enableCORS=false' is not compatible with
1587
1732
  'server.enableXsrfProtection=true'.
1588
1733
  As a result, 'server.enableCORS' is being overridden to 'true'.
@@ -1594,7 +1739,7 @@ cross-origin resource sharing.
1594
1739
 
1595
1740
  If cross origin resource sharing is required, please disable server.enableXsrfProtection.
1596
1741
  """
1597
- )
1742
+ )
1598
1743
 
1599
1744
 
1600
1745
  def _set_development_mode() -> None:
@@ -1602,8 +1747,8 @@ def _set_development_mode() -> None:
1602
1747
 
1603
1748
 
1604
1749
  def on_config_parsed(
1605
- func: Callable[[], None], force_connect=False, lock=False
1606
- ) -> Callable[[], bool]:
1750
+ func: Callable[[], None], force_connect: bool = False, lock: bool = False
1751
+ ) -> Callable[[], None]:
1607
1752
  """Wait for the config file to be parsed then call func.
1608
1753
 
1609
1754
  If the config file has already been parsed, just calls func immediately
@@ -1623,7 +1768,7 @@ def on_config_parsed(
1623
1768
 
1624
1769
  Returns
1625
1770
  -------
1626
- Callable[[], bool]
1771
+ Callable[[], None]
1627
1772
  A function that the caller can use to deregister func.
1628
1773
  """
1629
1774
 
@@ -1632,13 +1777,13 @@ def on_config_parsed(
1632
1777
  # leading to a memory leak because the Signal will keep a reference of the
1633
1778
  # callable argument. When the callable argument is an object method, then
1634
1779
  # the reference to that object won't be released.
1635
- def receiver(_):
1636
- return func_with_lock()
1780
+ def receiver(_: Any) -> None:
1781
+ func_with_lock()
1637
1782
 
1638
- def disconnect():
1639
- return _on_config_parsed.disconnect(receiver)
1783
+ def disconnect() -> None:
1784
+ _on_config_parsed.disconnect(receiver)
1640
1785
 
1641
- def func_with_lock():
1786
+ def func_with_lock() -> None:
1642
1787
  if lock:
1643
1788
  with _config_lock:
1644
1789
  func()