streamlit 1.53.1__py3-none-any.whl → 1.54.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 (309) hide show
  1. streamlit/__init__.py +1 -31
  2. streamlit/auth_util.py +91 -2
  3. streamlit/cli_util.py +3 -2
  4. streamlit/commands/echo.py +2 -2
  5. streamlit/commands/execution_control.py +1 -1
  6. streamlit/commands/logo.py +76 -24
  7. streamlit/commands/navigation.py +1 -1
  8. streamlit/components/types/base_custom_component.py +0 -2
  9. streamlit/components/v1/custom_component.py +0 -2
  10. streamlit/components/v2/bidi_component/main.py +2 -2
  11. streamlit/components/v2/component_path_utils.py +17 -29
  12. streamlit/components/v2/manifest_scanner.py +8 -3
  13. streamlit/components/v2/presentation.py +1 -1
  14. streamlit/config.py +57 -13
  15. streamlit/config_util.py +5 -5
  16. streamlit/connections/snowflake_connection.py +5 -3
  17. streamlit/dataframe_util.py +10 -10
  18. streamlit/deprecation_util.py +19 -1
  19. streamlit/elements/arrow.py +18 -8
  20. streamlit/elements/deck_gl_json_chart.py +6 -2
  21. streamlit/elements/exception.py +4 -2
  22. streamlit/elements/form.py +1 -1
  23. streamlit/elements/layouts.py +1 -1
  24. streamlit/elements/lib/built_in_chart_utils.py +36 -13
  25. streamlit/elements/lib/color_util.py +21 -2
  26. streamlit/elements/lib/column_config_utils.py +9 -7
  27. streamlit/elements/lib/dialog.py +1 -1
  28. streamlit/elements/lib/image_utils.py +5 -5
  29. streamlit/elements/lib/layout_utils.py +1 -1
  30. streamlit/elements/lib/options_selector_utils.py +72 -22
  31. streamlit/elements/lib/policies.py +1 -1
  32. streamlit/elements/lib/streamlit_plotly_theme.py +9 -11
  33. streamlit/elements/lib/utils.py +1 -1
  34. streamlit/elements/map.py +6 -6
  35. streamlit/elements/plotly_chart.py +2 -2
  36. streamlit/elements/toast.py +1 -1
  37. streamlit/elements/vega_charts.py +30 -7
  38. streamlit/elements/widgets/button.py +3 -3
  39. streamlit/elements/widgets/button_group.py +3 -3
  40. streamlit/elements/widgets/chat.py +1 -1
  41. streamlit/elements/widgets/data_editor.py +6 -6
  42. streamlit/elements/widgets/multiselect.py +1 -1
  43. streamlit/elements/widgets/number_input.py +1 -1
  44. streamlit/elements/widgets/radio.py +91 -31
  45. streamlit/elements/widgets/select_slider.py +123 -37
  46. streamlit/elements/widgets/slider.py +5 -5
  47. streamlit/elements/widgets/time_widgets.py +150 -18
  48. streamlit/elements/write.py +2 -3
  49. streamlit/env_util.py +1 -1
  50. streamlit/errors.py +2 -14
  51. streamlit/external/langchain/streamlit_callback_handler.py +1 -1
  52. streamlit/hello/dataframe_demo.py +1 -1
  53. streamlit/hello/plotting_demo.py +19 -12
  54. streamlit/path_security.py +98 -0
  55. streamlit/proto/Alert_pb2.py +2 -3
  56. streamlit/proto/AppPage_pb2.py +2 -3
  57. streamlit/proto/ArrowData_pb2.py +2 -3
  58. streamlit/proto/ArrowNamedDataSet_pb2.py +2 -3
  59. streamlit/proto/ArrowVegaLiteChart_pb2.py +2 -3
  60. streamlit/proto/Arrow_pb2.py +2 -3
  61. streamlit/proto/AudioInput_pb2.py +2 -3
  62. streamlit/proto/Audio_pb2.py +2 -3
  63. streamlit/proto/AuthRedirect_pb2.py +2 -3
  64. streamlit/proto/AutoRerun_pb2.py +2 -3
  65. streamlit/proto/BackMsg_pb2.py +2 -3
  66. streamlit/proto/Balloons_pb2.py +2 -3
  67. streamlit/proto/BidiComponent_pb2.py +2 -3
  68. streamlit/proto/Block_pb2.py +2 -3
  69. streamlit/proto/BokehChart_pb2.py +2 -3
  70. streamlit/proto/ButtonGroup_pb2.py +2 -3
  71. streamlit/proto/ButtonLikeIconPosition_pb2.py +2 -3
  72. streamlit/proto/Button_pb2.py +2 -3
  73. streamlit/proto/CameraInput_pb2.py +2 -3
  74. streamlit/proto/ChatInput_pb2.py +2 -3
  75. streamlit/proto/Checkbox_pb2.py +2 -3
  76. streamlit/proto/ClientState_pb2.py +2 -3
  77. streamlit/proto/Code_pb2.py +2 -3
  78. streamlit/proto/ColorPicker_pb2.py +2 -3
  79. streamlit/proto/Common_pb2.py +2 -3
  80. streamlit/proto/Components_pb2.py +2 -3
  81. streamlit/proto/DataFrame_pb2.py +2 -3
  82. streamlit/proto/DateInput_pb2.py +2 -3
  83. streamlit/proto/DateTimeInput_pb2.py +2 -3
  84. streamlit/proto/DeckGlJsonChart_pb2.py +2 -3
  85. streamlit/proto/Delta_pb2.py +2 -3
  86. streamlit/proto/DocString_pb2.py +2 -3
  87. streamlit/proto/DownloadButton_pb2.py +2 -3
  88. streamlit/proto/Element_pb2.py +2 -3
  89. streamlit/proto/Empty_pb2.py +2 -3
  90. streamlit/proto/Exception_pb2.py +2 -3
  91. streamlit/proto/Favicon_pb2.py +2 -3
  92. streamlit/proto/FileUploader_pb2.py +2 -3
  93. streamlit/proto/ForwardMsg_pb2.py +2 -3
  94. streamlit/proto/GapSize_pb2.py +2 -3
  95. streamlit/proto/GitInfo_pb2.py +2 -3
  96. streamlit/proto/GraphVizChart_pb2.py +2 -3
  97. streamlit/proto/Heading_pb2.py +2 -3
  98. streamlit/proto/HeightConfig_pb2.py +2 -3
  99. streamlit/proto/Html_pb2.py +2 -3
  100. streamlit/proto/IFrame_pb2.py +2 -3
  101. streamlit/proto/Image_pb2.py +2 -3
  102. streamlit/proto/Json_pb2.py +2 -3
  103. streamlit/proto/LabelVisibilityMessage_pb2.py +2 -3
  104. streamlit/proto/LinkButton_pb2.py +2 -3
  105. streamlit/proto/Logo_pb2.py +6 -5
  106. streamlit/proto/Logo_pb2.pyi +25 -1
  107. streamlit/proto/Markdown_pb2.py +2 -3
  108. streamlit/proto/Metric_pb2.py +2 -3
  109. streamlit/proto/MetricsEvent_pb2.py +2 -3
  110. streamlit/proto/MultiSelect_pb2.py +2 -3
  111. streamlit/proto/NamedDataSet_pb2.py +2 -3
  112. streamlit/proto/Navigation_pb2.py +2 -3
  113. streamlit/proto/NewSession_pb2.py +25 -24
  114. streamlit/proto/NewSession_pb2.pyi +28 -2
  115. streamlit/proto/NumberInput_pb2.py +2 -3
  116. streamlit/proto/PageConfig_pb2.py +2 -3
  117. streamlit/proto/PageInfo_pb2.py +2 -3
  118. streamlit/proto/PageLink_pb2.py +2 -3
  119. streamlit/proto/PageNotFound_pb2.py +2 -3
  120. streamlit/proto/PageProfile_pb2.py +2 -3
  121. streamlit/proto/PagesChanged_pb2.py +2 -3
  122. streamlit/proto/ParentMessage_pb2.py +2 -3
  123. streamlit/proto/PlotlyChart_pb2.py +2 -3
  124. streamlit/proto/Progress_pb2.py +2 -3
  125. streamlit/proto/Radio_pb2.py +5 -4
  126. streamlit/proto/Radio_pb2.pyi +20 -3
  127. streamlit/proto/RootContainer_pb2.py +2 -3
  128. streamlit/proto/Selectbox_pb2.py +2 -3
  129. streamlit/proto/SessionEvent_pb2.py +2 -3
  130. streamlit/proto/SessionStatus_pb2.py +2 -3
  131. streamlit/proto/Skeleton_pb2.py +2 -3
  132. streamlit/proto/Slider_pb2.py +7 -8
  133. streamlit/proto/Slider_pb2.pyi +9 -1
  134. streamlit/proto/Snow_pb2.py +2 -3
  135. streamlit/proto/Space_pb2.py +2 -3
  136. streamlit/proto/Spinner_pb2.py +2 -3
  137. streamlit/proto/TextAlignmentConfig_pb2.py +2 -3
  138. streamlit/proto/TextArea_pb2.py +2 -3
  139. streamlit/proto/TextInput_pb2.py +2 -3
  140. streamlit/proto/Text_pb2.py +2 -3
  141. streamlit/proto/TimeInput_pb2.py +2 -3
  142. streamlit/proto/Toast_pb2.py +2 -3
  143. streamlit/proto/Transient_pb2.py +2 -3
  144. streamlit/proto/VegaLiteChart_pb2.py +2 -3
  145. streamlit/proto/Video_pb2.py +2 -3
  146. streamlit/proto/WidgetStates_pb2.py +2 -3
  147. streamlit/proto/WidthConfig_pb2.py +2 -3
  148. streamlit/proto/openmetrics_data_model_pb2.py +2 -3
  149. streamlit/runtime/app_session.py +106 -60
  150. streamlit/runtime/caching/cache_data_api.py +3 -3
  151. streamlit/runtime/caching/cache_errors.py +0 -2
  152. streamlit/runtime/caching/cache_resource_api.py +1 -1
  153. streamlit/runtime/caching/cache_utils.py +2 -2
  154. streamlit/runtime/caching/hashing.py +1 -3
  155. streamlit/runtime/caching/storage/cache_storage_protocol.py +0 -3
  156. streamlit/runtime/connection_factory.py +1 -1
  157. streamlit/runtime/credentials.py +2 -2
  158. streamlit/runtime/metrics_util.py +3 -3
  159. streamlit/runtime/runtime.py +6 -6
  160. streamlit/runtime/scriptrunner/script_runner.py +17 -0
  161. streamlit/runtime/scriptrunner_utils/exceptions.py +0 -4
  162. streamlit/runtime/scriptrunner_utils/script_run_context.py +13 -31
  163. streamlit/runtime/secrets.py +3 -4
  164. streamlit/runtime/state/__init__.py +7 -1
  165. streamlit/runtime/state/common.py +13 -0
  166. streamlit/runtime/state/query_params.py +493 -24
  167. streamlit/runtime/state/session_state.py +179 -4
  168. streamlit/runtime/state/widgets.py +26 -1
  169. streamlit/runtime/stats.py +1 -10
  170. streamlit/static/index.html +1 -1
  171. streamlit/static/manifest.json +304 -304
  172. streamlit/static/static/js/{ErrorOutline.esm.CScZvf44.js → ErrorOutline.esm.BWk6F-Tz.js} +1 -1
  173. streamlit/static/static/js/{FileDownload.esm.COCxTZxP.js → FileDownload.esm.AllYUuOW.js} +1 -1
  174. streamlit/static/static/js/{FileHelper.Bhs-iVRI.js → FileHelper.BvVTNdmy.js} +1 -1
  175. streamlit/static/static/js/{FormClearHelper.CA_5b-Ut.js → FormClearHelper.C__r5Llk.js} +1 -1
  176. streamlit/static/static/js/{InputInstructions.Bzb0MCfv.js → InputInstructions.DOtkdOMV.js} +1 -1
  177. streamlit/static/static/js/Particles.DCsqQZlE.js +1 -0
  178. streamlit/static/static/js/{ProgressBar.DyQNhVsJ.js → ProgressBar.DLCRvt4m.js} +2 -2
  179. streamlit/static/static/js/{StreamlitSyntaxHighlighter.BOkJThtV.js → StreamlitSyntaxHighlighter.CYFWoZHb.js} +1 -1
  180. streamlit/static/static/js/{TableChart.esm.a60nntBC.js → TableChart.esm.D6ydHcIm.js} +1 -1
  181. streamlit/static/static/js/Toolbar.BHDNzWBx.js +1 -0
  182. streamlit/static/static/js/{WidgetLabelHelpIconInline.BjIku2ic.js → WidgetLabelHelpIconInline.DEXBrVlc.js} +1 -1
  183. streamlit/static/static/js/{base-input.avGkArOc.js → base-input.TSQjctlq.js} +4 -4
  184. streamlit/static/static/js/{checkbox.Q8mCuqps.js → checkbox.BKgfzJZV.js} +1 -1
  185. streamlit/static/static/js/{createDownloadLinkElement.CfqHRpxo.js → createDownloadLinkElement.CG7nr2a4.js} +1 -1
  186. streamlit/static/static/js/{data-grid-overlay-editor.PuoMl3yV.js → data-grid-overlay-editor.ChXO__lP.js} +1 -1
  187. streamlit/static/static/js/{downloader.CjG2csSm.js → downloader.DJ3R_zWA.js} +1 -1
  188. streamlit/static/static/js/embed.u3PPfLkw.js +193 -0
  189. streamlit/static/static/js/{es6.CQD6uUK7.js → es6.C5Mfy8nd.js} +2 -2
  190. streamlit/static/static/js/{formatNumber.CtjUO-if.js → formatNumber.CMRgW9EJ.js} +1 -1
  191. streamlit/static/static/js/{iconPosition.7Qt6oUiI.js → iconPosition.B4EEXI3E.js} +1 -1
  192. streamlit/static/static/js/{iframeResizer.contentWindow._oj2Xh0v.js → iframeResizer.contentWindow.WSvOiTW0.js} +1 -1
  193. streamlit/static/static/js/index.-FOBV3nz.js +1 -0
  194. streamlit/static/static/js/{index.BuBkymZd.js → index.-NF8OSF5.js} +1 -1
  195. streamlit/static/static/js/{index.B-XrnnK6.js → index.4cBg8kn5.js} +1 -1
  196. streamlit/static/static/js/{index.B_ylV_tl.js → index.B0pzzCsH.js} +1 -1
  197. streamlit/static/static/js/{index.BhJwyXH6.js → index.BID6ND5j.js} +2 -2
  198. streamlit/static/static/js/index.BMp5bGjh.js +1 -0
  199. streamlit/static/static/js/{index.Cptu1tS-.js → index.BQcmlvas.js} +1 -1
  200. streamlit/static/static/js/{index.DXQ_Fvpt.js → index.BRcmclgI.js} +1 -1
  201. streamlit/static/static/js/index.BaUZR4IG.js +1 -0
  202. streamlit/static/static/js/{index.CMBgAPh6.js → index.BbMJj4PN.js} +1 -1
  203. streamlit/static/static/js/{index.CVRgrLT-.js → index.BdCTJtq3.js} +2 -2
  204. streamlit/static/static/js/index.BdETLMuI.js +1 -0
  205. streamlit/static/static/js/index.BnKMWhs1.js +1 -0
  206. streamlit/static/static/js/index.Br1kXwQW.js +2 -0
  207. streamlit/static/static/js/{index.XGft6-dq.js → index.Bt2olRE4.js} +1 -1
  208. streamlit/static/static/js/{index.B2fAYU1N.js → index.Bxwsv5T8.js} +1 -1
  209. streamlit/static/static/js/index.C4KskYz6.js +1 -0
  210. streamlit/static/static/js/{index.DZE_91Ym.js → index.C6bmbXk0.js} +1 -1
  211. streamlit/static/static/js/{index.Egabyb7u.js → index.CEfKfbta.js} +1 -1
  212. streamlit/static/static/js/index.CIuaA8q0.js +2 -0
  213. streamlit/static/static/js/{index.DVtfSohT.js → index.CV1sObFX.js} +1 -1
  214. streamlit/static/static/js/{index.BlJhnb4M.js → index.CbR6dgaV.js} +1 -1
  215. streamlit/static/static/js/index.Cq6szKqJ.js +1 -0
  216. streamlit/static/static/js/index.CyouXqCz.js +1 -0
  217. streamlit/static/static/js/{index.B5wmZkRW.js → index.D1NUgMFI.js} +1 -1
  218. streamlit/static/static/js/{index.euRMkmNi.js → index.D7SWG4Om.js} +1 -1
  219. streamlit/static/static/js/{index.Bg-9YNUa.js → index.DAYPEwLI.js} +1 -1
  220. streamlit/static/static/js/index.DKS75Vfg.js +11 -0
  221. streamlit/static/static/js/{index.CIizdLeb.js → index.DOXrMIxB.js} +1 -1
  222. streamlit/static/static/js/{index.BRegnbUa.js → index.DOzYX8yS.js} +3 -3
  223. streamlit/static/static/js/{index.BksGMsW0.js → index.DRFMYcC4.js} +4 -4
  224. streamlit/static/static/js/{index.B8PovXCX.js → index.Divl5FCY.js} +1 -1
  225. streamlit/static/static/js/{index.DxQuXlXH.js → index.DjAJ_CUa.js} +1 -1
  226. streamlit/static/static/js/{index.BrRuSP42.js → index.Dncue2pm.js} +33 -33
  227. streamlit/static/static/js/{index.DSTThs-t.js → index.Drusyo5m.js} +47 -47
  228. streamlit/static/static/js/{index.BOafPwIE.js → index.DuUyDGnP.js} +1 -1
  229. streamlit/static/static/js/{index.D1bkwsLT.js → index.DvgT2rB2.js} +223 -223
  230. streamlit/static/static/js/{index.BmDXWfgx.js → index.DzutABu5.js} +2 -2
  231. streamlit/static/static/js/index.Dzw2iPzi.js +3 -0
  232. streamlit/static/static/js/{index.DJsqD2Sc.js → index.FsTmxLbT.js} +1 -1
  233. streamlit/static/static/js/{index.BOTEMJfV.js → index.OIwPqGYN.js} +1 -1
  234. streamlit/static/static/js/{index.CBqST2Yj.js → index.RXLN7YFT.js} +2 -2
  235. streamlit/static/static/js/{index.Ft2Zxbhr.js → index.YYb2u0jk.js} +2 -2
  236. streamlit/static/static/js/{index.BWCFtBS4.js → index.h8ejt-W3.js} +1 -1
  237. streamlit/static/static/js/{index.KuLql7H0.js → index.lFMCi9am.js} +1 -1
  238. streamlit/static/static/js/{index.D8t7R4QQ.js → index.pOgf4cEj.js} +1 -1
  239. streamlit/static/static/js/{index.CsoN0h7K.js → index.s_E0s7LB.js} +51 -51
  240. streamlit/static/static/js/{index.BVX_bqnf.js → index.xLCbzoqj.js} +1 -1
  241. streamlit/static/static/js/{input.Cf97CQME.js → input.BLG7kWaj.js} +2 -2
  242. streamlit/static/static/js/{main.Ccuk53yQ.js → main.D_CmqChN.js} +1 -1
  243. streamlit/static/static/js/{memory.Bng6Ij0g.js → memory.T8u9KqIQ.js} +1 -1
  244. streamlit/static/static/js/{number-overlay-editor.CFLv-CWC.js → number-overlay-editor.BKBSXkAM.js} +2 -2
  245. streamlit/static/static/js/{pandasStylerUtils.C2hcAKiv.js → pandasStylerUtils.B4tLYMwS.js} +1 -1
  246. streamlit/static/static/js/{sandbox.BXdeD-wA.js → sandbox.jRlkcPem.js} +1 -1
  247. streamlit/static/static/js/{styled-components.Br04Ogac.js → styled-components.D2QhNwzd.js} +1 -1
  248. streamlit/static/static/js/{throttle.mI9ItGre.js → throttle.Cyw_V0Dq.js} +1 -1
  249. streamlit/static/static/js/{timepicker.poFdB0sd.js → timepicker.PzyuDDWl.js} +1 -1
  250. streamlit/static/static/js/{toConsumableArray.92-fANS-.js → toConsumableArray.gE9fMkLj.js} +1 -1
  251. streamlit/static/static/js/uniqueId.B1GeHnT1.js +1 -0
  252. streamlit/static/static/js/{useBasicWidgetState.DzKGLAv_.js → useBasicWidgetState.DFklfao0.js} +1 -1
  253. streamlit/static/static/js/{useIntlLocale.BMma2iiY.js → useIntlLocale.C3tUGWTU.js} +8 -8
  254. streamlit/static/static/js/{useTextInputAutoExpand.DQbIhdma.js → useTextInputAutoExpand.D9nU_y-e.js} +1 -1
  255. streamlit/static/static/js/useUpdateUiValue.ClTdrkJN.js +1 -0
  256. streamlit/static/static/js/{useWaveformController.AH0ggRyc.js → useWaveformController.lzTbjMW2.js} +1 -1
  257. streamlit/static/static/js/{withCalculatedWidth.G5xJ-MbS.js → withCalculatedWidth.Dxs9I5Oe.js} +1 -1
  258. streamlit/static/static/js/{withFullScreenWrapper.rdRu6zZ4.js → withFullScreenWrapper.DfpAcJxf.js} +1 -1
  259. streamlit/string_util.py +2 -2
  260. streamlit/testing/v1/app_test.py +1 -1
  261. streamlit/testing/v1/element_tree.py +33 -20
  262. streamlit/type_util.py +2 -2
  263. streamlit/url_util.py +2 -2
  264. streamlit/user_info.py +2 -41
  265. streamlit/util.py +1 -1
  266. streamlit/watcher/event_based_path_watcher.py +37 -7
  267. streamlit/watcher/path_watcher.py +61 -2
  268. streamlit/watcher/util.py +26 -10
  269. streamlit/web/bootstrap.py +16 -4
  270. streamlit/web/cli.py +1 -4
  271. streamlit/web/server/app_discovery.py +2 -1
  272. streamlit/web/server/app_static_file_handler.py +9 -0
  273. streamlit/web/server/bidi_component_request_handler.py +4 -4
  274. streamlit/web/server/component_file_utils.py +14 -6
  275. streamlit/web/server/component_request_handler.py +2 -2
  276. streamlit/web/server/oauth_authlib_routes.py +14 -42
  277. streamlit/web/server/server.py +1 -1
  278. streamlit/web/server/server_util.py +23 -1
  279. streamlit/web/server/starlette/starlette_app.py +7 -1
  280. streamlit/web/server/starlette/starlette_auth_routes.py +94 -16
  281. streamlit/web/server/starlette/starlette_path_security_middleware.py +97 -0
  282. streamlit/web/server/starlette/starlette_routes.py +16 -9
  283. streamlit/web/server/starlette/starlette_server.py +2 -2
  284. streamlit/web/server/starlette/starlette_static_routes.py +14 -4
  285. streamlit/web/server/stats_request_handler.py +1 -3
  286. {streamlit-1.53.1.dist-info → streamlit-1.54.0.dist-info}/METADATA +10 -25
  287. {streamlit-1.53.1.dist-info → streamlit-1.54.0.dist-info}/RECORD +290 -290
  288. {streamlit-1.53.1.dist-info → streamlit-1.54.0.dist-info}/WHEEL +1 -1
  289. streamlit/commands/experimental_query_params.py +0 -169
  290. streamlit/static/static/js/Particles.ix5_l22I.js +0 -1
  291. streamlit/static/static/js/Toolbar.CxkcuBQ8.js +0 -1
  292. streamlit/static/static/js/embed.DZ-CLCPz.js +0 -195
  293. streamlit/static/static/js/index.B6ZAXv47.js +0 -1
  294. streamlit/static/static/js/index.BDm-Ia27.js +0 -1
  295. streamlit/static/static/js/index.BeCZLkzg.js +0 -1
  296. streamlit/static/static/js/index.BuEBeckn.js +0 -11
  297. streamlit/static/static/js/index.CL2eCR01.js +0 -1
  298. streamlit/static/static/js/index.CdLlbsiN.js +0 -1
  299. streamlit/static/static/js/index.CwIIk90V.js +0 -1
  300. streamlit/static/static/js/index.DDk0U8rh.js +0 -2
  301. streamlit/static/static/js/index.DNB79dOd.js +0 -3
  302. streamlit/static/static/js/index.DNj5S4tY.js +0 -1
  303. streamlit/static/static/js/index.DOY0ZriT.js +0 -2
  304. streamlit/static/static/js/index.r0gCrMFP.js +0 -1
  305. streamlit/static/static/js/uniqueId.BUj-C6GA.js +0 -1
  306. streamlit/static/static/js/useUpdateUiValue.Bk5OIXup.js +0 -1
  307. streamlit-1.53.1.data/scripts/streamlit.cmd +0 -16
  308. {streamlit-1.53.1.dist-info → streamlit-1.54.0.dist-info}/entry_points.txt +0 -0
  309. {streamlit-1.53.1.dist-info → streamlit-1.54.0.dist-info}/top_level.txt +0 -0
streamlit/__init__.py CHANGED
@@ -60,7 +60,6 @@ _os.environ["MPLBACKEND"] = "Agg"
60
60
  # Must be at the top, to avoid circular dependency.
61
61
  from streamlit import logger as _logger
62
62
  from streamlit import config as _config
63
- from streamlit.deprecation_util import deprecate_func_name as _deprecate_func_name
64
63
  from streamlit.version import STREAMLIT_VERSION_STRING as _STREAMLIT_VERSION_STRING
65
64
 
66
65
  # Give the package a version.
@@ -112,14 +111,9 @@ from streamlit.runtime.state import (
112
111
  )
113
112
  from streamlit.user_info import (
114
113
  UserInfoProxy as _UserInfoProxy,
115
- DeprecatedUserInfoProxy as _DeprecatedUserInfoProxy,
116
114
  login as _login,
117
115
  logout as _logout,
118
116
  )
119
- from streamlit.commands.experimental_query_params import (
120
- get_query_params as _get_query_params,
121
- set_query_params as _set_query_params,
122
- )
123
117
 
124
118
  import streamlit.column_config as _column_config
125
119
 
@@ -280,32 +274,8 @@ logout = _logout
280
274
  # User
281
275
  user = _UserInfoProxy()
282
276
 
283
- # Experimental APIs
284
- experimental_user = _DeprecatedUserInfoProxy()
285
-
286
- _EXPERIMENTAL_QUERY_PARAMS_DEPRECATE_MSG = (
287
- "Refer to our [docs page](https://docs.streamlit.io/develop/api-reference/caching-and-state/st.query_params) "
288
- "for more information."
289
- )
290
-
291
- experimental_get_query_params = _deprecate_func_name(
292
- _get_query_params,
293
- "experimental_get_query_params",
294
- "2024-04-11",
295
- _EXPERIMENTAL_QUERY_PARAMS_DEPRECATE_MSG,
296
- name_override="query_params",
297
- )
298
- experimental_set_query_params = _deprecate_func_name(
299
- _set_query_params,
300
- "experimental_set_query_params",
301
- "2024-04-11",
302
- _EXPERIMENTAL_QUERY_PARAMS_DEPRECATE_MSG,
303
- name_override="query_params",
304
- )
305
-
306
-
307
277
  # make it possible to call streamlit.components.v1.html etc. by importing it here
308
278
  # import in the very end to avoid partially-initialized module import errors, because
309
279
  # streamlit.components.v1 also uses some streamlit imports
310
- import streamlit.components.v1
280
+ import streamlit.components.v1 # noqa: F401
311
281
  import streamlit.components.v2 # noqa: F401
streamlit/auth_util.py CHANGED
@@ -19,7 +19,7 @@ import re
19
19
  from collections.abc import Callable, Mapping
20
20
  from datetime import datetime, timedelta, timezone
21
21
  from typing import TYPE_CHECKING, Any, Final, TypedDict, cast
22
- from urllib.parse import urlparse
22
+ from urllib.parse import urlencode, urlparse
23
23
 
24
24
  from streamlit import config
25
25
  from streamlit.errors import StreamlitAuthError
@@ -148,6 +148,95 @@ def get_redirect_uri(auth_section: AttrDict) -> str | None:
148
148
  return redirect_uri_parsed.geturl()
149
149
 
150
150
 
151
+ def get_validated_redirect_uri() -> str | None:
152
+ """Get the redirect_uri from secrets, validating it ends with /oauth2callback.
153
+
154
+ This is used for logout flows where we need a validated redirect URI
155
+ that matches the OAuth callback path.
156
+
157
+ Returns
158
+ -------
159
+ str | None
160
+ The validated redirect URI, or None if not configured or invalid.
161
+ """
162
+ auth_section = get_secrets_auth_section()
163
+ if not auth_section:
164
+ return None
165
+
166
+ redirect_uri = get_redirect_uri(auth_section)
167
+ if not redirect_uri:
168
+ return None
169
+
170
+ if not redirect_uri.endswith("/oauth2callback"):
171
+ _LOGGER.warning("Redirect URI does not end with /oauth2callback")
172
+ return None
173
+
174
+ return redirect_uri
175
+
176
+
177
+ def get_origin_from_redirect_uri() -> str | None:
178
+ """Extract the origin (scheme + host) from the configured redirect_uri.
179
+
180
+ Returns
181
+ -------
182
+ str | None
183
+ The origin in format "scheme://host:port", or None if not configured.
184
+ """
185
+ auth_section = get_secrets_auth_section()
186
+ if not auth_section:
187
+ return None
188
+
189
+ redirect_uri = get_redirect_uri(auth_section)
190
+ if not redirect_uri:
191
+ return None
192
+
193
+ redirect_uri_parsed = urlparse(redirect_uri)
194
+ return f"{redirect_uri_parsed.scheme}://{redirect_uri_parsed.netloc}"
195
+
196
+
197
+ def build_logout_url(
198
+ end_session_endpoint: str,
199
+ client_id: str,
200
+ post_logout_redirect_uri: str,
201
+ id_token: str | None = None,
202
+ ) -> str:
203
+ """Build an OIDC logout URL with the required parameters.
204
+
205
+ Parameters
206
+ ----------
207
+ end_session_endpoint
208
+ The OIDC provider's end_session_endpoint URL.
209
+ client_id
210
+ The OAuth client ID.
211
+ post_logout_redirect_uri
212
+ The URI to redirect to after logout.
213
+ id_token
214
+ Optional ID token to include as id_token_hint for the logout request.
215
+
216
+ Returns
217
+ -------
218
+ str
219
+ The complete logout URL with query parameters.
220
+ """
221
+ from urllib.parse import parse_qsl
222
+
223
+ logout_params: dict[str, str] = {
224
+ "client_id": client_id,
225
+ "post_logout_redirect_uri": post_logout_redirect_uri,
226
+ }
227
+
228
+ if id_token:
229
+ logout_params["id_token_hint"] = id_token
230
+
231
+ # Per OIDC spec, end_session_endpoint should be a clean URL without query params,
232
+ # but we handle existing params defensively for non-standard providers.
233
+ parsed = urlparse(end_session_endpoint)
234
+ existing_params = dict(parse_qsl(parsed.query))
235
+ merged_params = {**existing_params, **logout_params}
236
+ new_query = urlencode(merged_params)
237
+ return parsed._replace(query=new_query).geturl()
238
+
239
+
151
240
  def encode_provider_token(provider: str) -> str:
152
241
  """Returns a signed JWT token with the provider and expiration time."""
153
242
  try:
@@ -376,7 +465,7 @@ def get_cookie_with_chunks(
376
465
  chunk_name = f"{cookie_name}_{i + 1}"
377
466
  chunk_value = get_single_cookie_fn(chunk_name)
378
467
  if chunk_value is None:
379
- _LOGGER.exception("Missing chunk %d for cookie '%s'", i + 1, cookie_name)
468
+ _LOGGER.error("Missing chunk %d for cookie '%s'", i + 1, cookie_name)
380
469
  return None
381
470
  chunks.append(chunk_value)
382
471
 
streamlit/cli_util.py CHANGED
@@ -17,7 +17,6 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import os
20
- import subprocess
21
20
  from typing import Any
22
21
 
23
22
  from streamlit import env_util, errors
@@ -60,7 +59,9 @@ def _open_browser_with_webbrowser(url: str) -> None:
60
59
 
61
60
  def _open_browser_with_command(command: str, url: str) -> None:
62
61
  cmd_line = [command, url]
63
- with open(os.devnull, "w") as devnull:
62
+ with open(os.devnull, "w", encoding="utf-8") as devnull:
63
+ import subprocess # noqa: S404
64
+
64
65
  subprocess.Popen(cmd_line, stdout=devnull, stderr=subprocess.STDOUT) # noqa: S603
65
66
 
66
67
 
@@ -26,8 +26,8 @@ from streamlit.runtime.metrics_util import gather_metrics
26
26
  if TYPE_CHECKING:
27
27
  from collections.abc import Generator, Iterable
28
28
 
29
- _SPACES_RE = re.compile("\\s*")
30
- _EMPTY_LINE_RE = re.compile("\\s*\n")
29
+ _SPACES_RE = re.compile(r"\s*")
30
+ _EMPTY_LINE_RE = re.compile(r"\s*\n")
31
31
 
32
32
 
33
33
  @gather_metrics("echo")
@@ -158,7 +158,7 @@ def rerun( # type: ignore[misc]
158
158
 
159
159
  """
160
160
 
161
- if scope not in ["app", "fragment"]:
161
+ if scope not in {"app", "fragment"}:
162
162
  raise StreamlitAPIException(
163
163
  f"'{scope}'is not a valid rerun scope. Valid scopes are 'app' and 'fragment'."
164
164
  )
@@ -23,8 +23,10 @@ from streamlit.elements.lib.image_utils import AtomicImage, image_to_url
23
23
  from streamlit.elements.lib.layout_utils import LayoutConfig
24
24
  from streamlit.errors import StreamlitAPIException
25
25
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
26
+ from streamlit.proto.Logo_pb2 import Logo as LogoProto
26
27
  from streamlit.runtime.metrics_util import gather_metrics
27
28
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
29
+ from streamlit.string_util import is_emoji, validate_material_icon
28
30
 
29
31
 
30
32
  def _invalid_logo_text(field_name: str) -> str:
@@ -35,13 +37,59 @@ def _invalid_logo_text(field_name: str) -> str:
35
37
  )
36
38
 
37
39
 
40
+ def _process_logo_image(
41
+ image: AtomicImage | str, image_id: str
42
+ ) -> tuple[LogoProto.ImageType.ValueType, str]:
43
+ """Detects the image type and prepares the image data for the frontend.
44
+
45
+ Parameters
46
+ ----------
47
+ image :
48
+ The image that was provided by the user. Can be an image file,
49
+ emoji, or material icon string.
50
+ image_id : str
51
+ The image ID used when serving local images via the media file manager.
52
+
53
+ Returns
54
+ -------
55
+ tuple[ImageType, str]
56
+ The detected image type and the prepared image data.
57
+
58
+ Raises
59
+ ------
60
+ StreamlitAPIException
61
+ If the image is an empty string or a plain text string that is not
62
+ a valid file path, URL, emoji, or material icon.
63
+ """
64
+ ImageType = LogoProto.ImageType # noqa: N806
65
+
66
+ # Check if it's a material icon
67
+ if isinstance(image, str) and image.startswith(":material"):
68
+ return ImageType.ICON, validate_material_icon(image)
69
+
70
+ # Check if it's an emoji
71
+ if isinstance(image, str) and is_emoji(image):
72
+ return ImageType.EMOJI, image
73
+
74
+ # Otherwise, treat it as an image file
75
+ image_url = image_to_url(
76
+ image,
77
+ layout_config=LayoutConfig(width="content"),
78
+ clamp=False,
79
+ channels="RGB",
80
+ output_format="auto",
81
+ image_id=image_id,
82
+ )
83
+ return ImageType.IMAGE, image_url
84
+
85
+
38
86
  @gather_metrics("logo")
39
87
  def logo(
40
- image: AtomicImage,
88
+ image: AtomicImage | str,
41
89
  *, # keyword-only args:
42
90
  size: Literal["small", "medium", "large"] = "medium",
43
91
  link: str | None = None,
44
- icon_image: AtomicImage | None = None,
92
+ icon_image: AtomicImage | str | None = None,
45
93
  ) -> None:
46
94
  r"""
47
95
  Renders a logo in the upper-left corner of your app and its sidebar.
@@ -60,12 +108,26 @@ def logo(
60
108
 
61
109
  Parameters
62
110
  ----------
63
- image: Anything supported by st.image (except list)
111
+ image: Anything supported by st.image (except list) or str
64
112
  The image to display in the upper-left corner of your app and its
65
- sidebar. This can be any of the types supported by |st.image|_ except
66
- a list. If ``icon_image`` is also provided, then Streamlit will only
113
+ sidebar. If ``icon_image`` is also provided, then Streamlit will only
67
114
  display ``image`` in the sidebar.
68
115
 
116
+ ``image`` can be any of the types supported by |st.image|_ except
117
+ a list. Additionally, the following strings are valid:
118
+
119
+ - A single-character emoji. For example, you can set ``image="🏠"``
120
+ or ``image="🚀"``. Emoji short codes are not supported.
121
+
122
+ - An icon from the Material Symbols library (rounded style) in the
123
+ format ``":material/icon_name:"`` where "icon_name" is the name
124
+ of the icon in snake case.
125
+
126
+ For example, ``image=":material/home:"`` will display the
127
+ Home icon. Find additional icons in the `Material Symbols \
128
+ <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
129
+ font library.
130
+
69
131
  Streamlit scales the image to a max height set by ``size`` and a max
70
132
  width to fit within the sidebar.
71
133
 
@@ -84,10 +146,10 @@ def logo(
84
146
  The external URL to open when a user clicks on the logo. The URL must
85
147
  start with "\http://" or "\https://". If ``link`` is ``None`` (default),
86
148
  the logo will not include a hyperlink.
87
- icon_image: Anything supported by st.image (except list) or None
149
+ icon_image: Anything supported by st.image (except list), str, or None
88
150
  An optional, typically smaller image to replace ``image`` in the
89
151
  upper-left corner when the sidebar is closed. This can be any of the
90
- types supported by ``st.image`` except a list. If ``icon_image`` is
152
+ types allowed for the ``image`` parameter. If ``icon_image`` is
91
153
  ``None`` (default), Streamlit will always display ``image`` in the
92
154
  upper-left corner, regardless of whether the sidebar is open or closed.
93
155
  Otherwise, Streamlit will render ``icon_image`` in the upper-left
@@ -143,15 +205,9 @@ def logo(
143
205
  fwd_msg = ForwardMsg()
144
206
 
145
207
  try:
146
- image_url = image_to_url(
147
- image,
148
- layout_config=LayoutConfig(width="content"),
149
- clamp=False,
150
- channels="RGB",
151
- output_format="auto",
152
- image_id="logo",
153
- )
154
- fwd_msg.logo.image = image_url
208
+ image_type, image_value = _process_logo_image(image, "logo")
209
+ fwd_msg.logo.image = image_value
210
+ fwd_msg.logo.image_type = image_type
155
211
  except Exception as ex:
156
212
  raise StreamlitAPIException(_invalid_logo_text("image")) from ex
157
213
 
@@ -167,15 +223,11 @@ def logo(
167
223
 
168
224
  if icon_image:
169
225
  try:
170
- icon_image_url = image_to_url(
171
- icon_image,
172
- layout_config=LayoutConfig(width="content"),
173
- clamp=False,
174
- channels="RGB",
175
- output_format="auto",
176
- image_id="icon-image",
226
+ icon_image_type, icon_image_value = _process_logo_image(
227
+ icon_image, "icon-image"
177
228
  )
178
- fwd_msg.logo.icon_image = icon_image_url
229
+ fwd_msg.logo.icon_image = icon_image_value
230
+ fwd_msg.logo.icon_image_type = icon_image_type
179
231
  except Exception as ex:
180
232
  raise StreamlitAPIException(_invalid_logo_text("icon_image")) from ex
181
233
 
@@ -292,7 +292,7 @@ def navigation(
292
292
 
293
293
  """
294
294
  # Validate position parameter
295
- if not isinstance(position, str) or position not in ["sidebar", "hidden", "top"]:
295
+ if not isinstance(position, str) or position not in {"sidebar", "hidden", "top"}:
296
296
  raise StreamlitAPIException(
297
297
  f'Invalid position "{position}". '
298
298
  'The position parameter must be one of "sidebar", "hidden", or "top".'
@@ -28,8 +28,6 @@ if TYPE_CHECKING:
28
28
  class MarshallComponentException(StreamlitAPIException):
29
29
  """Class for exceptions generated during custom component marshalling."""
30
30
 
31
- pass
32
-
33
31
 
34
32
  class BaseCustomComponent(ABC):
35
33
  """Interface for CustomComponents."""
@@ -40,8 +40,6 @@ if TYPE_CHECKING:
40
40
  class MarshallComponentException(StreamlitAPIException):
41
41
  """Class for exceptions generated during custom component marshalling."""
42
42
 
43
- pass
44
-
45
43
 
46
44
  class CustomComponent(BaseCustomComponent):
47
45
  """A Custom Component declaration."""
@@ -480,7 +480,7 @@ class BidiComponentMixin:
480
480
  deserializer=serde.deserialize,
481
481
  serializer=serde.serialize,
482
482
  ctx=ctx,
483
- callbacks=callbacks_by_event if callbacks_by_event else None,
483
+ callbacks=callbacks_by_event or None,
484
484
  value_type="json_value",
485
485
  presenter=presenter,
486
486
  )
@@ -495,7 +495,7 @@ class BidiComponentMixin:
495
495
  deserializer=deserialize_trigger_list, # always returns list or None
496
496
  serializer=lambda v: json.dumps(v), # send dict as JSON
497
497
  ctx=ctx,
498
- callbacks=callbacks_by_event if callbacks_by_event else None,
498
+ callbacks=callbacks_by_event or None,
499
499
  value_type="json_trigger_value",
500
500
  )
501
501
 
@@ -22,12 +22,12 @@ outside of a declared package root.
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
- import os
26
25
  from pathlib import Path
27
26
  from typing import Final
28
27
 
29
28
  from streamlit.errors import StreamlitComponentRegistryError
30
29
  from streamlit.logger import get_logger
30
+ from streamlit.path_security import is_unsafe_path_pattern
31
31
 
32
32
  _LOGGER: Final = get_logger(__name__)
33
33
 
@@ -132,7 +132,12 @@ class ComponentPathUtils:
132
132
 
133
133
  @staticmethod
134
134
  def _assert_relative_no_traversal(path: str, *, label: str) -> None:
135
- """Raise if ``path`` is absolute or contains ``..`` segments.
135
+ """Raise if ``path`` is absolute, contains traversal, or has unsafe patterns.
136
+
137
+ This method uses the shared ``is_unsafe_path_pattern`` function to ensure
138
+ consistent security checks across the codebase. The shared function also
139
+ checks for additional patterns like null bytes, forward-slash UNC paths,
140
+ and drive-relative paths (e.g., ``C:foo``).
136
141
 
137
142
  Parameters
138
143
  ----------
@@ -141,34 +146,17 @@ class ComponentPathUtils:
141
146
  label : str
142
147
  Human-readable label used in error messages (e.g., "component paths").
143
148
  """
144
- # Absolute path checks (POSIX, Windows drive-letter, UNC)
145
- is_windows_drive_abs = (
146
- len(path) >= 3
147
- and path[0].isalpha()
148
- and path[1] == ":"
149
- and path[2] in ("/", "\\")
150
- )
151
- is_unc_abs = path.startswith("\\\\")
152
-
153
- # Consider rooted backslash paths "\\dir" as absolute on Windows-like inputs
154
- is_rooted_backslash = path.startswith("\\") and not is_unc_abs
155
-
156
- if (
157
- os.path.isabs(path)
158
- or is_windows_drive_abs
159
- or is_unc_abs
160
- or is_rooted_backslash
161
- ):
162
- raise StreamlitComponentRegistryError(
163
- f"Absolute paths are not allowed in {label}: {path}"
164
- )
165
-
166
- # Segment-based traversal detection to avoid false positives (e.g. "file..js")
167
- normalized = path.replace("\\", "/")
168
- segments = [seg for seg in normalized.split("/") if seg != ""]
169
- if any(seg == ".." for seg in segments):
149
+ if is_unsafe_path_pattern(path):
150
+ # Determine appropriate error message based on pattern.
151
+ # Use segment-based check to avoid false positives like "file..js"
152
+ normalized = path.replace("\\", "/")
153
+ segments = [seg for seg in normalized.split("/") if seg]
154
+ if ".." in segments:
155
+ raise StreamlitComponentRegistryError(
156
+ f"Path traversal attempts are not allowed in {label}: {path}"
157
+ )
170
158
  raise StreamlitComponentRegistryError(
171
- f"Path traversal attempts are not allowed in {label}: {path}"
159
+ f"Unsafe paths are not allowed in {label}: {path}"
172
160
  )
173
161
 
174
162
  @staticmethod
@@ -187,8 +187,13 @@ def _is_likely_streamlit_component_package(
187
187
  bool
188
188
  True if the package might contain streamlit components, False otherwise.
189
189
  """
190
- # Get package metadata
191
- name = dist.name.lower()
190
+ dist_name = dist.name
191
+ if not isinstance(dist_name, str) or not dist_name:
192
+ # We do not expect a distribution to be missing its name, be defensive
193
+ # and fail closed to prevent runtime issues.
194
+ return False
195
+
196
+ name = dist_name.lower()
192
197
  summary = dist.metadata["Summary"].lower() if "Summary" in dist.metadata else ""
193
198
 
194
199
  # Filter 1: Package name suggests streamlit component
@@ -386,7 +391,7 @@ def _validate_pyproject_for_package(
386
391
  canonical_package = packaging_utils.canonicalize_name(package_name)
387
392
 
388
393
  # Check if project name matches either the distribution name or the package name
389
- return canonical_project in (canonical_dist, canonical_package)
394
+ return canonical_project in {canonical_dist, canonical_package}
390
395
 
391
396
  # If we can't determine ownership, be conservative and reject it
392
397
  return False
@@ -127,7 +127,7 @@ def make_bidi_component_presenter(
127
127
  # st.session_state[component_user_key][name] = value. Using a
128
128
  # dict subclass ensures pretty-printing and JSON serialization
129
129
  # behave as expected for st.write and logs.
130
- class _WriteThrough(dict[str, object]):
130
+ class _WriteThrough(dict[str, object]): # noqa: FURB189
131
131
  def __init__(self, data: dict[str, object]) -> None:
132
132
  super().__init__(data)
133
133
 
streamlit/config.py CHANGED
@@ -99,11 +99,11 @@ class ShowErrorDetailsConfigOptions(str, Enum):
99
99
 
100
100
  @staticmethod
101
101
  def is_true_variation(val: str | bool) -> bool:
102
- return val in ["true", "True", True]
102
+ return val in {"true", "True", True}
103
103
 
104
104
  @staticmethod
105
105
  def is_false_variation(val: str | bool) -> bool:
106
- return val in ["false", "False", False]
106
+ return val in {"false", "False", False}
107
107
 
108
108
  # Config options can be set from several places including the command-line and
109
109
  # the user's script. Legacy config options (true/false) will have type string
@@ -617,6 +617,19 @@ _create_option(
617
617
  scriptable=True,
618
618
  )
619
619
 
620
+ _create_option(
621
+ "client.showErrorLinks",
622
+ description="""
623
+ Controls whether to show external help links (Google, ChatGPT) in
624
+ error displays. The following values are valid:
625
+ - "auto" (default): Links are shown only on localhost.
626
+ - True: Links are shown on all domains.
627
+ - False: Links are never shown.
628
+ """,
629
+ default_val="auto",
630
+ type_=str,
631
+ )
632
+
620
633
  # Config Section: Runner #
621
634
 
622
635
  _create_section("runner", "Settings for how Streamlit executes your script")
@@ -1077,9 +1090,11 @@ def _browser_server_port() -> int:
1077
1090
 
1078
1091
 
1079
1092
  _SSL_PRODUCTION_WARNING = [
1080
- "DO NOT USE THIS OPTION IN A PRODUCTION ENVIRONMENT. It has not gone through "
1081
- "security audits or performance tests. For a production environment, we "
1082
- "recommend performing SSL termination through a load balancer or reverse proxy."
1093
+ (
1094
+ "DO NOT USE THIS OPTION IN A PRODUCTION ENVIRONMENT. It has not gone through "
1095
+ "security audits or performance tests. For a production environment, we "
1096
+ "recommend performing SSL termination through a load balancer or reverse proxy."
1097
+ )
1083
1098
  ]
1084
1099
 
1085
1100
  _create_option(
@@ -2279,6 +2294,35 @@ _create_theme_options(
2279
2294
  """,
2280
2295
  )
2281
2296
 
2297
+ _create_theme_options(
2298
+ "chartDivergingColors",
2299
+ categories=["theme"],
2300
+ description="""
2301
+ An array of ten colors to use for diverging chart data.
2302
+
2303
+ The ten colors create a diverging color scale, typically used for data
2304
+ with a meaningful midpoint. These colors apply to Plotly, Altair, and
2305
+ Vega-Lite charts.
2306
+
2307
+ Invalid color strings are skipped. If there are not exactly ten
2308
+ valid colors specified, Streamlit uses a default set of colors.
2309
+
2310
+ The default colors are:
2311
+ [
2312
+ "#7d353b", #red100
2313
+ "#bd4043", #red90
2314
+ "#ff4b4b", #red70
2315
+ "#ff8c8c", #red50
2316
+ "#ffc7c7", #red30
2317
+ "#a6dcff", #blue30
2318
+ "#60b4ff", #blue50
2319
+ "#1c83e1", #blue70
2320
+ "#0054a3", #blue90
2321
+ "#004280", #blue100
2322
+ ]
2323
+ """,
2324
+ )
2325
+
2282
2326
  # Config Section: Secrets #
2283
2327
 
2284
2328
  _create_section("secrets", "Secrets configuration.")
@@ -2347,10 +2391,10 @@ def is_manually_set(option_name: str) -> bool:
2347
2391
  True if the option has been set by the user.
2348
2392
 
2349
2393
  """
2350
- return get_where_defined(option_name) not in (
2394
+ return get_where_defined(option_name) not in {
2351
2395
  ConfigOption.DEFAULT_DEFINITION,
2352
2396
  ConfigOption.STREAMLIT_DEFINITION,
2353
- )
2397
+ }
2354
2398
 
2355
2399
 
2356
2400
  def show_config() -> None:
@@ -2433,19 +2477,19 @@ def _is_valid_theme_section(section_path: str) -> bool:
2433
2477
 
2434
2478
  # theme.sidebar/light/dark is valid (2 parts: "theme" + section)
2435
2479
  if len(parts) == 2:
2436
- return parts[1] in [
2480
+ return parts[1] in {
2437
2481
  CustomThemeCategories.SIDEBAR.value,
2438
2482
  CustomThemeCategories.LIGHT.value,
2439
2483
  CustomThemeCategories.DARK.value,
2440
- ]
2484
+ }
2441
2485
 
2442
2486
  # theme.light.sidebar/theme.dark.sidebar are the only valid 3-part patterns
2443
2487
  if len(parts) == 3:
2444
2488
  # Only allow light/dark as the middle level, with sidebar as the final level
2445
- if parts[1] in [
2489
+ if parts[1] in {
2446
2490
  CustomThemeCategories.LIGHT.value,
2447
2491
  CustomThemeCategories.DARK.value,
2448
- ]:
2492
+ }:
2449
2493
  return parts[2] == CustomThemeCategories.SIDEBAR.value
2450
2494
  # sidebar cannot have nested sections (theme.sidebar.light/dark)
2451
2495
  return False
@@ -2517,11 +2561,11 @@ def _update_config_with_toml(raw_toml: str, where_defined: str) -> None:
2517
2561
  for name, value in section_data.items():
2518
2562
  option_name = f"{section_path}.{name}"
2519
2563
  # Only check for nested sections when we're already in a theme section
2520
- if section_path.startswith("theme") and name in [
2564
+ if section_path.startswith("theme") and name in {
2521
2565
  CustomThemeCategories.SIDEBAR.value,
2522
2566
  CustomThemeCategories.LIGHT.value,
2523
2567
  CustomThemeCategories.DARK.value,
2524
- ]:
2568
+ }:
2525
2569
  # Validate the theme section before processing
2526
2570
  if not _is_valid_theme_section(option_name):
2527
2571
  raise StreamlitInvalidThemeSectionError(