streamlit 1.45.1__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 (335) hide show
  1. streamlit/__init__.py +5 -1
  2. streamlit/auth_util.py +12 -12
  3. streamlit/cli_util.py +4 -3
  4. streamlit/column_config.py +11 -9
  5. streamlit/commands/echo.py +6 -4
  6. streamlit/commands/execution_control.py +33 -32
  7. streamlit/commands/experimental_query_params.py +2 -2
  8. streamlit/commands/logo.py +9 -4
  9. streamlit/commands/navigation.py +61 -18
  10. streamlit/commands/page_config.py +57 -47
  11. streamlit/components/types/base_custom_component.py +7 -7
  12. streamlit/components/v1/component_registry.py +7 -3
  13. streamlit/components/v1/components.py +1 -1
  14. streamlit/components/v1/custom_component.py +8 -8
  15. streamlit/config.py +289 -144
  16. streamlit/config_option.py +19 -15
  17. streamlit/config_util.py +29 -23
  18. streamlit/connections/__init__.py +2 -2
  19. streamlit/connections/base_connection.py +5 -5
  20. streamlit/connections/snowflake_connection.py +13 -11
  21. streamlit/connections/snowpark_connection.py +3 -3
  22. streamlit/connections/sql_connection.py +20 -18
  23. streamlit/connections/util.py +2 -2
  24. streamlit/cursor.py +6 -6
  25. streamlit/dataframe_util.py +52 -52
  26. streamlit/delta_generator.py +46 -48
  27. streamlit/delta_generator_singletons.py +3 -3
  28. streamlit/deprecation_util.py +6 -6
  29. streamlit/elements/alert.py +37 -29
  30. streamlit/elements/arrow.py +40 -22
  31. streamlit/elements/code.py +46 -13
  32. streamlit/elements/deck_gl_json_chart.py +38 -27
  33. streamlit/elements/dialog_decorator.py +3 -4
  34. streamlit/elements/doc_string.py +64 -58
  35. streamlit/elements/exception.py +23 -27
  36. streamlit/elements/form.py +41 -0
  37. streamlit/elements/graphviz_chart.py +1 -1
  38. streamlit/elements/heading.py +60 -9
  39. streamlit/elements/html.py +3 -4
  40. streamlit/elements/image.py +8 -9
  41. streamlit/elements/json.py +21 -2
  42. streamlit/elements/layouts.py +120 -31
  43. streamlit/elements/lib/built_in_chart_utils.py +96 -73
  44. streamlit/elements/lib/color_util.py +3 -3
  45. streamlit/elements/lib/column_config_utils.py +2 -4
  46. streamlit/elements/lib/column_types.py +14 -8
  47. streamlit/elements/lib/dialog.py +9 -5
  48. streamlit/elements/lib/image_utils.py +39 -40
  49. streamlit/elements/lib/js_number.py +4 -4
  50. streamlit/elements/lib/layout_utils.py +65 -1
  51. streamlit/elements/lib/mutable_status_container.py +14 -3
  52. streamlit/elements/lib/options_selector_utils.py +22 -12
  53. streamlit/elements/lib/pandas_styler_utils.py +25 -21
  54. streamlit/elements/lib/policies.py +6 -5
  55. streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
  56. streamlit/elements/lib/subtitle_utils.py +6 -9
  57. streamlit/elements/lib/utils.py +20 -5
  58. streamlit/elements/map.py +32 -56
  59. streamlit/elements/markdown.py +101 -12
  60. streamlit/elements/media.py +78 -21
  61. streamlit/elements/metric.py +32 -16
  62. streamlit/elements/plotly_chart.py +15 -15
  63. streamlit/elements/progress.py +33 -15
  64. streamlit/elements/spinner.py +31 -6
  65. streamlit/elements/text.py +21 -1
  66. streamlit/elements/toast.py +1 -2
  67. streamlit/elements/vega_charts.py +54 -23
  68. streamlit/elements/widgets/audio_input.py +24 -7
  69. streamlit/elements/widgets/button.py +26 -19
  70. streamlit/elements/widgets/button_group.py +10 -15
  71. streamlit/elements/widgets/camera_input.py +27 -7
  72. streamlit/elements/widgets/chat.py +91 -38
  73. streamlit/elements/widgets/checkbox.py +45 -4
  74. streamlit/elements/widgets/color_picker.py +40 -17
  75. streamlit/elements/widgets/data_editor.py +76 -37
  76. streamlit/elements/widgets/file_uploader.py +42 -13
  77. streamlit/elements/widgets/multiselect.py +7 -10
  78. streamlit/elements/widgets/number_input.py +123 -47
  79. streamlit/elements/widgets/radio.py +59 -13
  80. streamlit/elements/widgets/select_slider.py +35 -30
  81. streamlit/elements/widgets/selectbox.py +56 -9
  82. streamlit/elements/widgets/slider.py +190 -99
  83. streamlit/elements/widgets/text_widgets.py +54 -8
  84. streamlit/elements/widgets/time_widgets.py +53 -14
  85. streamlit/elements/write.py +5 -8
  86. streamlit/env_util.py +2 -7
  87. streamlit/error_util.py +16 -9
  88. streamlit/errors.py +69 -48
  89. streamlit/external/langchain/streamlit_callback_handler.py +10 -5
  90. streamlit/file_util.py +27 -10
  91. streamlit/git_util.py +29 -24
  92. streamlit/hello/animation_demo.py +9 -9
  93. streamlit/hello/dataframe_demo.py +5 -5
  94. streamlit/hello/hello.py +1 -0
  95. streamlit/hello/mapping_demo.py +7 -8
  96. streamlit/hello/plotting_demo.py +3 -3
  97. streamlit/hello/streamlit_app.py +28 -26
  98. streamlit/hello/utils.py +2 -1
  99. streamlit/logger.py +10 -11
  100. streamlit/navigation/page.py +11 -8
  101. streamlit/proto/Audio_pb2.py +4 -3
  102. streamlit/proto/Audio_pb2.pyi +8 -1
  103. streamlit/proto/Block_pb2.py +38 -29
  104. streamlit/proto/Block_pb2.pyi +72 -4
  105. streamlit/proto/ClientState_pb2.py +4 -4
  106. streamlit/proto/ClientState_pb2.pyi +7 -2
  107. streamlit/proto/Code_pb2.py +4 -2
  108. streamlit/proto/Code_pb2.pyi +1 -0
  109. streamlit/proto/DataFrame_pb2.pyi +1 -1
  110. streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
  111. streamlit/proto/Element_pb2.py +5 -3
  112. streamlit/proto/Element_pb2.pyi +20 -3
  113. streamlit/proto/GapSize_pb2.py +29 -0
  114. streamlit/proto/GapSize_pb2.pyi +70 -0
  115. streamlit/proto/HeightConfig_pb2.py +27 -0
  116. streamlit/proto/HeightConfig_pb2.pyi +48 -0
  117. streamlit/proto/NamedDataSet_pb2.pyi +1 -1
  118. streamlit/proto/Navigation_pb2.py +3 -3
  119. streamlit/proto/Navigation_pb2.pyi +4 -0
  120. streamlit/proto/NewSession_pb2.py +18 -16
  121. streamlit/proto/NewSession_pb2.pyi +29 -3
  122. streamlit/proto/PageConfig_pb2.py +7 -7
  123. streamlit/proto/PageConfig_pb2.pyi +21 -1
  124. streamlit/proto/Video_pb2.py +8 -7
  125. streamlit/proto/Video_pb2.pyi +8 -1
  126. streamlit/proto/WidthConfig_pb2.py +2 -2
  127. streamlit/proto/WidthConfig_pb2.pyi +15 -1
  128. streamlit/runtime/__init__.py +1 -1
  129. streamlit/runtime/app_session.py +53 -40
  130. streamlit/runtime/caching/__init__.py +9 -9
  131. streamlit/runtime/caching/cache_data_api.py +36 -30
  132. streamlit/runtime/caching/cache_errors.py +4 -4
  133. streamlit/runtime/caching/cache_resource_api.py +8 -8
  134. streamlit/runtime/caching/cache_utils.py +15 -14
  135. streamlit/runtime/caching/cached_message_replay.py +14 -8
  136. streamlit/runtime/caching/hashing.py +91 -97
  137. streamlit/runtime/caching/legacy_cache_api.py +2 -2
  138. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
  139. streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
  140. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +12 -14
  141. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -6
  142. streamlit/runtime/connection_factory.py +36 -36
  143. streamlit/runtime/context.py +58 -9
  144. streamlit/runtime/credentials.py +29 -40
  145. streamlit/runtime/forward_msg_queue.py +11 -11
  146. streamlit/runtime/fragment.py +7 -7
  147. streamlit/runtime/media_file_manager.py +3 -4
  148. streamlit/runtime/memory_media_file_storage.py +6 -5
  149. streamlit/runtime/memory_uploaded_file_manager.py +2 -2
  150. streamlit/runtime/metrics_util.py +11 -12
  151. streamlit/runtime/pages_manager.py +4 -6
  152. streamlit/runtime/runtime.py +8 -6
  153. streamlit/runtime/runtime_util.py +7 -6
  154. streamlit/runtime/scriptrunner/__init__.py +4 -4
  155. streamlit/runtime/scriptrunner/exec_code.py +12 -5
  156. streamlit/runtime/scriptrunner/magic.py +16 -12
  157. streamlit/runtime/scriptrunner/script_cache.py +1 -1
  158. streamlit/runtime/scriptrunner/script_runner.py +53 -29
  159. streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
  160. streamlit/runtime/scriptrunner_utils/script_requests.py +7 -4
  161. streamlit/runtime/scriptrunner_utils/script_run_context.py +10 -23
  162. streamlit/runtime/secrets.py +40 -35
  163. streamlit/runtime/session_manager.py +2 -1
  164. streamlit/runtime/state/__init__.py +5 -5
  165. streamlit/runtime/state/common.py +2 -2
  166. streamlit/runtime/state/query_params.py +13 -15
  167. streamlit/runtime/state/query_params_proxy.py +17 -13
  168. streamlit/runtime/state/safe_session_state.py +2 -2
  169. streamlit/runtime/state/session_state.py +52 -34
  170. streamlit/runtime/stats.py +2 -2
  171. streamlit/runtime/uploaded_file_manager.py +1 -1
  172. streamlit/runtime/websocket_session_manager.py +10 -6
  173. streamlit/source_util.py +8 -6
  174. streamlit/static/index.html +3 -17
  175. streamlit/static/manifest.json +1180 -0
  176. streamlit/static/static/css/{index.DqDwtg6_.css → index.CJVRHjQZ.css} +1 -1
  177. streamlit/static/static/js/{ErrorOutline.esm.DU9IrB3M.js → ErrorOutline.esm.6PVAQvlT.js} +1 -1
  178. streamlit/static/static/js/{FileDownload.esm.P9rKwKo8.js → FileDownload.esm.BZQHC61b.js} +1 -1
  179. streamlit/static/static/js/{FileHelper.D7RMkx0e.js → FileHelper.Bn1VShMJ.js} +5 -5
  180. streamlit/static/static/js/{FormClearHelper.B67tgll0.js → FormClearHelper.CsFEiTNN.js} +1 -1
  181. streamlit/static/static/js/{Hooks.ncTJktu9.js → Hooks.DguOHQL1.js} +1 -1
  182. streamlit/static/static/js/{InputInstructions.D-Y8geDN.js → InputInstructions.CTYn2BJQ.js} +1 -1
  183. streamlit/static/static/js/{ProgressBar.B-kexwwD.js → ProgressBar.CPOGBKCi.js} +2 -2
  184. streamlit/static/static/js/{RenderInPortalIfExists.BgaoZgep.js → RenderInPortalIfExists.BYu_CZaF.js} +1 -1
  185. streamlit/static/static/js/Toolbar.gXKw7ANv.js +1 -0
  186. streamlit/static/static/js/UploadFileInfo.0DCkpDDf.js +6 -0
  187. streamlit/static/static/js/{base-input.BoAa1U94.js → base-input.DBYPj91R.js} +4 -4
  188. streamlit/static/static/js/{checkbox.Z6iSfe5F.js → checkbox.BUm2vnNv.js} +2 -2
  189. streamlit/static/static/js/{createSuper.B4oGDYRm.js → createSuper.KD4RuZ-W.js} +1 -1
  190. streamlit/static/static/js/{data-grid-overlay-editor.msYws2Ou.js → data-grid-overlay-editor.CUwpDfvI.js} +1 -1
  191. streamlit/static/static/js/{downloader.kc14n2Hv.js → downloader.CkDtclup.js} +1 -1
  192. streamlit/static/static/js/{es6.CxQz807-.js → es6.Dlcvh_r0.js} +2 -2
  193. streamlit/static/static/js/{iframeResizer.contentWindow.B19u0ONI.js → iframeResizer.contentWindow.DOXlFfve.js} +1 -1
  194. streamlit/static/static/js/{index.BGga-hcS.js → index.B0cuGMAB.js} +25 -25
  195. streamlit/static/static/js/index.BCWTclSV.js +73 -0
  196. streamlit/static/static/js/index.BJY_fap7.js +1 -0
  197. streamlit/static/static/js/index.BL3l6dnk.js +1 -0
  198. streamlit/static/static/js/{index.BFz9U2y0.js → index.BMZzRZjB.js} +1 -1
  199. streamlit/static/static/js/{index.-5ruC9At.js → index.BOzUTGDe.js} +1 -1
  200. streamlit/static/static/js/index.BYI5iO-o.js +1 -0
  201. streamlit/static/static/js/index.BYo0ywlm.js +783 -0
  202. streamlit/static/static/js/{index.CmTAF0dM.js → index.BYz9btsY.js} +1 -1
  203. streamlit/static/static/js/{index.BHGGDa8K.js → index.CCVzQz0Z.js} +2 -2
  204. streamlit/static/static/js/index.CD6FydK9.js +1 -0
  205. streamlit/static/static/js/index.CDYEqgC8.js +2 -0
  206. streamlit/static/static/js/{index.BRXmLIsC.js → index.CMP9c4xA.js} +1 -1
  207. streamlit/static/static/js/index.CN30QAPD.js +1 -0
  208. streamlit/static/static/js/{index.LaIasviC.js → index.CNqWQkTe.js} +1 -1
  209. streamlit/static/static/js/index.CaxS67Xz.js +1 -0
  210. streamlit/static/static/js/{index.xNQq3Ei5.js → index.CbsT4sGW.js} +1 -1
  211. streamlit/static/static/js/index.ChAVlxpQ.js +1 -0
  212. streamlit/static/static/js/{index.BqfdT8-Q.js → index.ClLMMmDd.js} +1 -1
  213. streamlit/static/static/js/{index.BHXxWdde.js → index.D-O9rQmV.js} +1 -1
  214. streamlit/static/static/js/{index.9V1KdxfP.js → index.D4k7VZZL.js} +1 -1
  215. streamlit/static/static/js/index.DLBi0Ar1.js +1 -0
  216. streamlit/static/static/js/index.DVq5XmJo.js +197 -0
  217. streamlit/static/static/js/{index.BoigZiu7.js → index.DZKmKXWw.js} +1 -1
  218. streamlit/static/static/js/index.DkaVx80F.js +1 -0
  219. streamlit/static/static/js/index.Dr968Klx.js +1 -0
  220. streamlit/static/static/js/{index.BpILzHf_.js → index.DtUYLn9j.js} +20 -20
  221. streamlit/static/static/js/index.DwjYSyhs.js +1 -0
  222. streamlit/static/static/js/index.DzrImxu4.js +1 -0
  223. streamlit/static/static/js/index.HyGsn4VM.js +1 -0
  224. streamlit/static/static/js/index.OwxC65od.js +12 -0
  225. streamlit/static/static/js/index.PZs7VZkC.js +1 -0
  226. streamlit/static/static/js/index.Voiqpj4q.js +1 -0
  227. streamlit/static/static/js/index.bSROvR-J.js +3 -0
  228. streamlit/static/static/js/index.oT9GD3l4.js +1 -0
  229. streamlit/static/static/js/{index.DeB9iKFW.js → index.qb-yAPH6.js} +255 -255
  230. streamlit/static/static/js/index.rJFy_Ygy.js +2 -0
  231. streamlit/static/static/js/{input.DsCfafm0.js → input.CwQtEnFN.js} +2 -2
  232. streamlit/static/static/js/{memory.nY_lMTtu.js → memory.C5XaFIjR.js} +1 -1
  233. streamlit/static/static/js/{mergeWith.B_7zmsM4.js → mergeWith.DzwwH6AG.js} +1 -1
  234. streamlit/static/static/js/{number-overlay-editor.CSeVhHRU.js → number-overlay-editor.Dx0XqCkD.js} +1 -1
  235. streamlit/static/static/js/{possibleConstructorReturn.nNhsvgRd.js → possibleConstructorReturn.CVfSu9Ws.js} +1 -1
  236. streamlit/static/static/js/{sandbox.Cgm3iuL6.js → sandbox.BT0gdMXk.js} +1 -1
  237. streamlit/static/static/js/{textarea.BR8rlyih.js → textarea.DNCbrtbM.js} +2 -2
  238. streamlit/static/static/js/{timepicker.w4XhAenH.js → timepicker.4UYJD9Ts.js} +1 -1
  239. streamlit/static/static/js/{toConsumableArray.CgkEPBwD.js → toConsumableArray.DUmnaVWV.js} +1 -1
  240. streamlit/static/static/js/{uniqueId.j-1rlNNH.js → uniqueId.DUvh-GL8.js} +1 -1
  241. streamlit/static/static/js/{useBasicWidgetState.zXY9CjFS.js → useBasicWidgetState.Cwd7-jJa.js} +1 -1
  242. streamlit/static/static/js/useOnInputChange.DvemQrOM.js +1 -0
  243. streamlit/static/static/js/{withFullScreenWrapper.Ov13692o.js → withFullScreenWrapper.CiQ10ByU.js} +1 -1
  244. streamlit/static/static/media/SourceCodeVF-Italic.ttf.Ba1oaZG1.woff2 +0 -0
  245. streamlit/static/static/media/SourceCodeVF-Upright.ttf.BjWn63N-.woff2 +0 -0
  246. streamlit/static/static/media/SourceSansVF-Italic.ttf.Bt9VkdQ3.woff2 +0 -0
  247. streamlit/static/static/media/SourceSansVF-Upright.ttf.BsWL4Kly.woff2 +0 -0
  248. streamlit/static/static/media/SourceSerifVariable-Italic.ttf.CVdzAtxO.woff2 +0 -0
  249. streamlit/static/static/media/SourceSerifVariable-Roman.ttf.mdpVL9bi.woff2 +0 -0
  250. streamlit/string_util.py +14 -19
  251. streamlit/temporary_directory.py +13 -4
  252. streamlit/testing/v1/app_test.py +15 -10
  253. streamlit/testing/v1/element_tree.py +157 -178
  254. streamlit/testing/v1/local_script_runner.py +11 -15
  255. streamlit/testing/v1/util.py +11 -4
  256. streamlit/type_util.py +8 -12
  257. streamlit/url_util.py +1 -1
  258. streamlit/user_info.py +6 -5
  259. streamlit/util.py +25 -1
  260. streamlit/vendor/pympler/asizeof.py +3 -2
  261. streamlit/watcher/event_based_path_watcher.py +15 -1
  262. streamlit/watcher/folder_black_list.py +2 -2
  263. streamlit/watcher/local_sources_watcher.py +64 -18
  264. streamlit/watcher/path_watcher.py +6 -10
  265. streamlit/watcher/polling_path_watcher.py +8 -7
  266. streamlit/watcher/util.py +7 -6
  267. streamlit/web/bootstrap.py +16 -14
  268. streamlit/web/cli.py +52 -45
  269. streamlit/web/server/__init__.py +7 -3
  270. streamlit/web/server/app_static_file_handler.py +1 -1
  271. streamlit/web/server/authlib_tornado_integration.py +9 -4
  272. streamlit/web/server/browser_websocket_handler.py +8 -2
  273. streamlit/web/server/component_request_handler.py +14 -10
  274. streamlit/web/server/media_file_handler.py +14 -7
  275. streamlit/web/server/oauth_authlib_routes.py +41 -9
  276. streamlit/web/server/oidc_mixin.py +35 -17
  277. streamlit/web/server/routes.py +32 -22
  278. streamlit/web/server/server.py +6 -18
  279. streamlit/web/server/server_util.py +19 -9
  280. streamlit/web/server/stats_request_handler.py +7 -5
  281. streamlit/web/server/upload_file_request_handler.py +22 -19
  282. streamlit/web/server/websocket_headers.py +1 -1
  283. {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/METADATA +4 -4
  284. streamlit-1.46.0.dist-info/RECORD +559 -0
  285. {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/WHEEL +1 -1
  286. streamlit/elements/lib/event_utils.py +0 -39
  287. streamlit/static/static/js/Toolbar.D9RUZv9G.js +0 -1
  288. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
  289. streamlit/static/static/js/index.8jhZBWF2.js +0 -3
  290. streamlit/static/static/js/index.BCx3C6e_.js +0 -1
  291. streamlit/static/static/js/index.BRuTz_S4.js +0 -1
  292. streamlit/static/static/js/index.Bcru_ti-.js +0 -1
  293. streamlit/static/static/js/index.Bl1FMJRd.js +0 -1
  294. streamlit/static/static/js/index.C1z8KpLA.js +0 -779
  295. streamlit/static/static/js/index.C32I2PUe.js +0 -2
  296. streamlit/static/static/js/index.C5GnDRB7.js +0 -1
  297. streamlit/static/static/js/index.CG4qPaaW.js +0 -2
  298. streamlit/static/static/js/index.C_msmT1u.js +0 -1
  299. streamlit/static/static/js/index.CbeNTdd6.js +0 -1
  300. streamlit/static/static/js/index.CnGQVJcw.js +0 -12
  301. streamlit/static/static/js/index.CopVVq4l.js +0 -1
  302. streamlit/static/static/js/index.CtXupx4d.js +0 -197
  303. streamlit/static/static/js/index.DGmCchO7.js +0 -1
  304. streamlit/static/static/js/index.DH6zBk0e.js +0 -1
  305. streamlit/static/static/js/index.DHVlVWsm.js +0 -1
  306. streamlit/static/static/js/index.DRKIVBoi.js +0 -1
  307. streamlit/static/static/js/index.DUd-lFXx.js +0 -73
  308. streamlit/static/static/js/index.D_uRBA4B.js +0 -1
  309. streamlit/static/static/js/index.QHNfgPJd.js +0 -1
  310. streamlit/static/static/js/index.a-RJocYL.js +0 -1
  311. streamlit/static/static/js/index.cvz4B1gy.js +0 -1
  312. streamlit/static/static/js/index.t--hEgTQ.js +0 -6
  313. streamlit/static/static/js/useOnInputChange.z04u96A8.js +0 -1
  314. streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
  315. streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
  316. streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
  317. streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
  318. streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
  319. streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
  320. streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
  321. streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
  322. streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
  323. streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
  324. streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
  325. streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
  326. streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
  327. streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
  328. streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
  329. streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
  330. streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
  331. streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
  332. streamlit-1.45.1.dist-info/RECORD +0 -568
  333. {streamlit-1.45.1.data → streamlit-1.46.0.data}/scripts/streamlit.cmd +0 -0
  334. {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/entry_points.txt +0 -0
  335. {streamlit-1.45.1.dist-info → streamlit-1.46.0.dist-info}/top_level.txt +0 -0
@@ -38,14 +38,13 @@ def _get_session_id() -> str:
38
38
  # "streamlit run myscript.py". In which case the session ID doesn't
39
39
  # matter and can just be a constant, as there's only ever "session".
40
40
  return "dontcare"
41
- else:
42
- return ctx.session_id
41
+ return ctx.session_id
43
42
 
44
43
 
45
44
  class MediaFileMetadata:
46
45
  """Metadata that the MediaFileManager needs for each file it manages."""
47
46
 
48
- def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA):
47
+ def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA) -> None:
49
48
  self._kind = kind
50
49
  self._is_marked_for_delete = False
51
50
 
@@ -80,7 +79,7 @@ class MediaFileManager:
80
79
  we should address it at some point.)
81
80
  """
82
81
 
83
- def __init__(self, storage: MediaFileStorage):
82
+ def __init__(self, storage: MediaFileStorage) -> None:
84
83
  self._storage = storage
85
84
 
86
85
  # Dict of [file_id -> MediaFileMetadata]
@@ -89,7 +89,7 @@ class MemoryFile(NamedTuple):
89
89
 
90
90
 
91
91
  class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
92
- def __init__(self, media_endpoint: str):
92
+ def __init__(self, media_endpoint: str) -> None:
93
93
  """Create a new MemoryMediaFileStorage instance.
94
94
 
95
95
  Parameters
@@ -110,10 +110,11 @@ class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
110
110
  ) -> str:
111
111
  """Add a file to the manager and return its ID."""
112
112
  file_data: bytes
113
- if isinstance(path_or_data, str):
114
- file_data = self._read_file(path_or_data)
115
- else:
116
- file_data = path_or_data
113
+ file_data = (
114
+ self._read_file(path_or_data)
115
+ if isinstance(path_or_data, str)
116
+ else path_or_data
117
+ )
117
118
 
118
119
  # Because our file_ids are stable, if we already have a file with the
119
120
  # given ID, we don't need to create a new one.
@@ -35,7 +35,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
35
35
  This class can be used safely from multiple threads simultaneously.
36
36
  """
37
37
 
38
- def __init__(self, upload_endpoint: str):
38
+ def __init__(self, upload_endpoint: str) -> None:
39
39
  self.file_storage: dict[str, dict[str, UploadedFileRec]] = defaultdict(dict)
40
40
  self.endpoint = upload_endpoint
41
41
 
@@ -92,7 +92,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
92
92
 
93
93
  self.file_storage[session_id][file.file_id] = file
94
94
 
95
- def remove_file(self, session_id, file_id):
95
+ def remove_file(self, session_id: str, file_id: str) -> None:
96
96
  """Remove file with given file_id associated with a given session."""
97
97
  session_storage = self.file_storage[session_id]
98
98
  session_storage.pop(file_id, None)
@@ -201,8 +201,8 @@ def _get_machine_id_v4() -> str:
201
201
  stable_id = None
202
202
 
203
203
  if os.path.exists(filepath):
204
- with file_util.streamlit_read(filepath) as input:
205
- stable_id = input.read()
204
+ with file_util.streamlit_read(filepath) as file:
205
+ stable_id = file.read()
206
206
 
207
207
  if not stable_id:
208
208
  stable_id = str(uuid.uuid4())
@@ -228,7 +228,7 @@ class Installation:
228
228
  cls._instance = Installation()
229
229
  return cls._instance
230
230
 
231
- def __init__(self):
231
+ def __init__(self) -> None:
232
232
  self.installation_id_v3 = str(
233
233
  uuid.uuid5(uuid.NAMESPACE_DNS, _get_machine_id_v3())
234
234
  )
@@ -239,7 +239,7 @@ class Installation:
239
239
  return util.repr_(self)
240
240
 
241
241
  @property
242
- def installation_id(self):
242
+ def installation_id(self) -> str:
243
243
  return self.installation_id_v3
244
244
 
245
245
 
@@ -284,7 +284,7 @@ def _get_arg_metadata(arg: object) -> str | None:
284
284
 
285
285
 
286
286
  def _get_command_telemetry(
287
- _command_func: Callable[..., Any], _command_name: str, *args, **kwargs
287
+ _command_func: Callable[..., Any], _command_name: str, *args: Any, **kwargs: Any
288
288
  ) -> Command:
289
289
  """Get telemetry information for the given callable and its arguments."""
290
290
  arg_keywords = inspect.getfullargspec(_command_func).args
@@ -391,12 +391,11 @@ def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
391
391
  )
392
392
 
393
393
  return wrapper
394
- else:
395
- # To make mypy type narrow F | None -> F
396
- non_optional_func = func
394
+ # To make mypy type narrow F | None -> F
395
+ non_optional_func = func
397
396
 
398
397
  @wraps(non_optional_func)
399
- def wrapped_func(*args, **kwargs):
398
+ def wrapped_func(*args: Any, **kwargs: Any) -> Any:
400
399
  from timeit import default_timer as timer
401
400
 
402
401
  exec_start = timer()
@@ -442,12 +441,12 @@ def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
442
441
  _LOGGER.debug("Failed to collect command telemetry", exc_info=ex)
443
442
  try:
444
443
  result = non_optional_func(*args, **kwargs)
445
- except RerunException as ex:
444
+ except RerunException:
446
445
  # Duplicated from below, because static analysis tools get confused
447
446
  # by deferring the rethrow.
448
447
  if tracking_activated and command_telemetry:
449
448
  command_telemetry.time = to_microseconds(timer() - exec_start)
450
- raise ex
449
+ raise
451
450
  finally:
452
451
  # Activate tracking again if command executes without any exceptions
453
452
  # we only want to do that if this command has set the
@@ -488,7 +487,7 @@ def create_page_profile_message(
488
487
  # Collect all config options that have been manually set
489
488
  config_options: set[str] = set()
490
489
  if config._config_options:
491
- for option_name in config._config_options.keys():
490
+ for option_name in config._config_options:
492
491
  if not config.is_manually_set(option_name):
493
492
  # We only care about manually defined options
494
493
  continue
@@ -38,8 +38,8 @@ class PagesManager:
38
38
  self,
39
39
  main_script_path: ScriptPath,
40
40
  script_cache: ScriptCache | None = None,
41
- **kwargs,
42
- ):
41
+ **kwargs: Any,
42
+ ) -> None:
43
43
  self._main_script_path = main_script_path
44
44
  self._main_script_hash: PageHash = calc_md5(main_script_path)
45
45
  self._script_cache = script_cache
@@ -99,9 +99,7 @@ class PagesManager:
99
99
  self._intended_page_script_hash = page_script_hash
100
100
  self._intended_page_name = page_name
101
101
 
102
- def get_initial_active_script(
103
- self, page_script_hash: PageHash, page_name: PageName
104
- ) -> PageInfo | None:
102
+ def get_initial_active_script(self, page_script_hash: PageHash) -> PageInfo | None:
105
103
  return {
106
104
  # We always run the main script in V2 as it's the common code
107
105
  "script_path": self.main_script_path,
@@ -137,7 +135,7 @@ class PagesManager:
137
135
  self.intended_page_script_hash,
138
136
  self._pages.get(fallback_page_hash, None),
139
137
  )
140
- elif self.intended_page_name:
138
+ if self.intended_page_name:
141
139
  # If a user navigates directly to a non-main page of an app, the
142
140
  # the page name can identify the page script to run
143
141
  return next(
@@ -167,7 +167,7 @@ class Runtime:
167
167
  """
168
168
  return cls._instance is not None
169
169
 
170
- def __init__(self, config: RuntimeConfig):
170
+ def __init__(self, config: RuntimeConfig) -> None:
171
171
  """Create a Runtime instance. It won't be started yet.
172
172
 
173
173
  Runtime is *not* thread-safe. Its public methods are generally
@@ -313,7 +313,7 @@ class Runtime:
313
313
 
314
314
  async_objs = self._get_async_objs()
315
315
 
316
- def stop_on_eventloop():
316
+ def stop_on_eventloop() -> None:
317
317
  if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
318
318
  return
319
319
 
@@ -374,9 +374,11 @@ class Runtime:
374
374
  -----
375
375
  Threading: UNSAFE. Must be called on the eventloop thread.
376
376
  """
377
- assert not (existing_session_id and session_id_override), (
378
- "Only one of existing_session_id and session_id_override should be set!"
379
- )
377
+ if existing_session_id and session_id_override:
378
+ raise RuntimeError(
379
+ "Only one of existing_session_id and session_id_override should be set. "
380
+ "This should never happen."
381
+ )
380
382
 
381
383
  if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
382
384
  raise RuntimeStoppedError(f"Can't connect_session (state={self._state})")
@@ -596,7 +598,7 @@ class Runtime:
596
598
  elif self._state == RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED:
597
599
  pass
598
600
  else:
599
- raise RuntimeError(f"Bad Runtime state at start: {self._state}")
601
+ raise RuntimeError(f"Bad Runtime state at start: {self._state}") # noqa: TRY301
600
602
 
601
603
  # Signal that we're started and ready to accept sessions
602
604
  async_objs.started.set_result(None)
@@ -31,7 +31,7 @@ _LOGGER: Final = getLogger(__name__)
31
31
  class MessageSizeError(MarkdownFormattedException):
32
32
  """Exception raised when a websocket message is larger than the configured limit."""
33
33
 
34
- def __init__(self, failed_msg_str: Any):
34
+ def __init__(self, failed_msg_str: Any) -> None:
35
35
  msg = self._get_message(failed_msg_str)
36
36
  super().__init__(msg)
37
37
 
@@ -39,7 +39,8 @@ class MessageSizeError(MarkdownFormattedException):
39
39
  # This needs to have zero indentation otherwise the markdown will render incorrectly.
40
40
  return (
41
41
  f"""
42
- **Data of size {len(failed_msg_str) / 1e6:.1f} MB exceeds the message size limit of {get_max_message_size_bytes() / 1e6} MB.**
42
+ **Data of size {len(failed_msg_str) / 1e6:.1f} MB exceeds the message size limit of
43
+ {get_max_message_size_bytes() / 1e6} MB.**
43
44
 
44
45
  This is often caused by a large chart or dataframe. Please decrease the amount of data sent
45
46
  to the browser, or increase the limit by setting the config option `server.maxMessageSize`.
@@ -54,7 +55,7 @@ of the client's browser and the Streamlit server._
54
55
  class BadDurationStringError(StreamlitAPIException):
55
56
  """Raised when a bad duration argument string is passed."""
56
57
 
57
- def __init__(self, duration: str):
58
+ def __init__(self, duration: str) -> None:
58
59
  MarkdownFormattedException.__init__(
59
60
  self,
60
61
  "TTL string doesn't look right. It should be formatted as"
@@ -74,12 +75,12 @@ def serialize_forward_msg(msg: ForwardMsg) -> bytes:
74
75
  if len(msg_str) > get_max_message_size_bytes():
75
76
  # Overwrite the offending ForwardMsg.delta with an error to display.
76
77
  # This assumes that the size limit wasn't exceeded due to metadata.
77
- import streamlit.elements.exception as exception
78
+ from streamlit.elements import exception
78
79
 
79
80
  msg_size_error = MessageSizeError(msg_str)
80
81
  _LOGGER.warning(
81
- "Websocket message size limit exceeded. "
82
- f"Showing error to the user: {msg_size_error}"
82
+ "Websocket message size limit exceeded. Showing error to the user: %s",
83
+ msg_size_error,
83
84
  )
84
85
  exception.marshall(msg.delta.new_element.exception, msg_size_error)
85
86
  # Deactivate caching for this error message:
@@ -27,12 +27,12 @@ from streamlit.runtime.scriptrunner_utils.script_run_context import (
27
27
 
28
28
  __all__ = [
29
29
  "RerunData",
30
- "ScriptRunContext",
31
- "add_script_run_ctx",
32
- "get_script_run_ctx",
33
- "enqueue_message",
34
30
  "RerunException",
31
+ "ScriptRunContext",
35
32
  "ScriptRunner",
36
33
  "ScriptRunnerEvent",
37
34
  "StopException",
35
+ "add_script_run_ctx",
36
+ "enqueue_message",
37
+ "get_script_run_ctx",
38
38
  ]
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import sys
18
- from typing import TYPE_CHECKING, Any, Callable
18
+ from typing import TYPE_CHECKING, Any, Callable, Literal
19
19
 
20
20
  from streamlit import util
21
21
  from streamlit.delta_generator_singletons import (
@@ -30,30 +30,37 @@ from streamlit.runtime.scriptrunner_utils.exceptions import (
30
30
  )
31
31
 
32
32
  if TYPE_CHECKING:
33
+ from types import TracebackType
34
+
33
35
  from streamlit.runtime.scriptrunner_utils.script_requests import RerunData
34
36
  from streamlit.runtime.scriptrunner_utils.script_run_context import ScriptRunContext
35
37
 
36
38
 
37
- class modified_sys_path:
39
+ class modified_sys_path: # noqa: N801
38
40
  """A context for prepending a directory to sys.path for a second.
39
41
 
40
42
  Code inspired by IPython:
41
43
  Source: https://github.com/ipython/ipython/blob/master/IPython/utils/syspathcontext.py#L42
42
44
  """
43
45
 
44
- def __init__(self, main_script_path: str):
46
+ def __init__(self, main_script_path: str) -> None:
45
47
  self._main_script_path = main_script_path
46
48
  self._added_path = False
47
49
 
48
50
  def __repr__(self) -> str:
49
51
  return util.repr_(self)
50
52
 
51
- def __enter__(self):
53
+ def __enter__(self) -> None:
52
54
  if self._main_script_path not in sys.path:
53
55
  sys.path.insert(0, self._main_script_path)
54
56
  self._added_path = True
55
57
 
56
- def __exit__(self, type, value, traceback):
58
+ def __exit__(
59
+ self,
60
+ typ: type[BaseException] | None,
61
+ exc: BaseException | None,
62
+ tb: TracebackType | None,
63
+ ) -> Literal[False]:
57
64
  if self._added_path:
58
65
  try:
59
66
  sys.path.remove(self._main_script_path)
@@ -21,8 +21,7 @@ from typing import Any, Final
21
21
  from streamlit import config
22
22
 
23
23
  # When a Streamlit app is magicified, we insert a `magic_funcs` import near the top of
24
- # its module's AST:
25
- # import streamlit.runtime.scriptrunner.magic_funcs as __streamlitmagic__
24
+ # its module's AST: import streamlit.runtime.scriptrunner.magic_funcs as __streamlitmagic__
26
25
  MAGIC_MODULE_NAME: Final = "__streamlitmagic__"
27
26
 
28
27
 
@@ -59,7 +58,7 @@ def _modify_ast_subtree(
59
58
  body_attr: str = "body",
60
59
  is_root: bool = False,
61
60
  file_ends_in_semicolon: bool = False,
62
- ):
61
+ ) -> None:
63
62
  """Parses magic commands and modifies the given AST (sub)tree."""
64
63
 
65
64
  body = getattr(tree, body_attr)
@@ -162,7 +161,7 @@ def _insert_import_statement(tree: Any) -> None:
162
161
  tree.body.insert(0, st_import)
163
162
 
164
163
 
165
- def _build_st_import_statement():
164
+ def _build_st_import_statement() -> ast.Import:
166
165
  """Build AST node for `import magic_funcs as __streamlitmagic__`."""
167
166
  return ast.Import(
168
167
  names=[
@@ -174,7 +173,7 @@ def _build_st_import_statement():
174
173
  )
175
174
 
176
175
 
177
- def _build_st_write_call(nodes):
176
+ def _build_st_write_call(nodes: list[Any]) -> ast.Call:
178
177
  """Build AST node for `__streamlitmagic__.transparent_write(*nodes)`."""
179
178
  return ast.Call(
180
179
  func=ast.Attribute(
@@ -188,8 +187,13 @@ def _build_st_write_call(nodes):
188
187
 
189
188
 
190
189
  def _get_st_write_from_expr(
191
- node, i, parent_type, is_root, is_last_expr, file_ends_in_semicolon
192
- ):
190
+ node: Any,
191
+ i: int,
192
+ parent_type: Any,
193
+ is_root: bool,
194
+ is_last_expr: bool,
195
+ file_ends_in_semicolon: bool,
196
+ ) -> ast.Call | None:
193
197
  # Don't wrap function calls
194
198
  # (Unless the function call happened at the end of the root node, AND
195
199
  # magic.displayLastExprIfNoSemicolon is True. This allows us to support notebook-like
@@ -217,17 +221,17 @@ def _get_st_write_from_expr(
217
221
  return None
218
222
 
219
223
  # If tuple, call st.write(*the_tuple). This allows us to add a comma at the end of a
220
- # statement to turn it into an expression that should be st-written. Ex:
221
- # "np.random.randn(1000, 2),"
224
+ # statement to turn it into an expression that should be
225
+ # st-written. Ex: "np.random.randn(1000, 2),"
222
226
  args = node.value.elts if type(node.value) is ast.Tuple else [node.value]
223
227
  return _build_st_write_call(args)
224
228
 
225
229
 
226
- def _is_string_constant_node(node) -> bool:
230
+ def _is_string_constant_node(node: Any) -> bool:
227
231
  return isinstance(node, ast.Constant) and isinstance(node.value, str)
228
232
 
229
233
 
230
- def _is_docstring_node(node, node_index, parent_type) -> bool:
234
+ def _is_docstring_node(node: Any, node_index: int, parent_type: Any) -> bool:
231
235
  return (
232
236
  node_index == 0
233
237
  and _is_string_constant_node(node)
@@ -235,7 +239,7 @@ def _is_docstring_node(node, node_index, parent_type) -> bool:
235
239
  )
236
240
 
237
241
 
238
- def _does_file_end_in_semicolon(tree, code: str) -> bool:
242
+ def _does_file_end_in_semicolon(tree: Any, code: str) -> bool:
239
243
  file_ends_in_semicolon = False
240
244
 
241
245
  # Avoid spending time with this operation if magic.displayLastExprIfNoSemicolon is
@@ -26,7 +26,7 @@ from streamlit.source_util import open_python_file
26
26
  class ScriptCache:
27
27
  """Thread-safe cache of Python script bytecode."""
28
28
 
29
- def __init__(self):
29
+ def __init__(self) -> None:
30
30
  # Mapping of script_path: bytecode
31
31
  self._cache: dict[str, Any] = {}
32
32
  self._lock = threading.Lock()
@@ -62,6 +62,8 @@ from streamlit.runtime.state import (
62
62
  from streamlit.source_util import page_sort_key
63
63
 
64
64
  if TYPE_CHECKING:
65
+ from collections.abc import Generator
66
+
65
67
  from streamlit.runtime.fragment import FragmentStorage
66
68
  from streamlit.runtime.scriptrunner.script_cache import ScriptCache
67
69
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
@@ -121,36 +123,35 @@ it in the future.
121
123
  # is designed to leverage our original v1 version of multi-page apps. This
122
124
  # function will be called to run the script in lieu of the main script. This
123
125
  # function simulates the v1 setup using the modern v2 commands (st.navigation)
124
- def _mpa_v1(main_script_path: str):
126
+ def _mpa_v1(main_script_path: str) -> None:
125
127
  from pathlib import Path
126
128
 
127
129
  from streamlit.commands.navigation import PageType, _navigation
128
130
  from streamlit.navigation.page import StreamlitPage
129
131
 
130
132
  # Select the folder that should be used for the pages:
131
- MAIN_SCRIPT_PATH = Path(main_script_path).resolve()
132
- PAGES_FOLDER = MAIN_SCRIPT_PATH.parent / "pages"
133
+ resolved_main_script_path: Final = Path(main_script_path).resolve()
134
+ pages_folder: Final = resolved_main_script_path.parent / "pages"
133
135
 
134
136
  # Read out the my_pages folder and create a page for every script:
135
- pages = PAGES_FOLDER.glob("*.py")
136
137
  pages = sorted(
137
138
  [
138
139
  page
139
- for page in pages
140
+ for page in pages_folder.glob("*.py")
140
141
  if page.name.endswith(".py")
141
142
  and not page.name.startswith(".")
142
- and not page.name == "__init__.py"
143
+ and page.name != "__init__.py"
143
144
  ],
144
145
  key=page_sort_key,
145
146
  )
146
147
 
147
148
  # Use this script as the main page and
148
- main_page = StreamlitPage(MAIN_SCRIPT_PATH, default=True)
149
+ main_page = StreamlitPage(resolved_main_script_path, default=True)
149
150
  all_pages = [main_page] + [
150
- StreamlitPage(PAGES_FOLDER / page.name) for page in pages
151
+ StreamlitPage(pages_folder / page.name) for page in pages
151
152
  ]
152
153
  # Initialize the navigation with all the pages:
153
- position: Literal["sidebar", "hidden"] = (
154
+ position: Literal["sidebar", "hidden", "top"] = (
154
155
  "hidden"
155
156
  if config.get_option("client.showSidebarNavigation") is False
156
157
  else "sidebar"
@@ -176,7 +177,7 @@ class ScriptRunner:
176
177
  user_info: dict[str, str | bool | None],
177
178
  fragment_storage: FragmentStorage,
178
179
  pages_manager: PagesManager,
179
- ):
180
+ ) -> None:
180
181
  """Initialize the ScriptRunner.
181
182
 
182
183
  (The ScriptRunner won't start executing until start() is called.)
@@ -261,7 +262,7 @@ class ScriptRunner:
261
262
  # _maybe_handle_execution_control_request.
262
263
  self._execing = False
263
264
 
264
- # This is initialized in start()
265
+ # This is initialized in the start() method
265
266
  self._script_thread: threading.Thread | None = None
266
267
 
267
268
  def __repr__(self) -> str:
@@ -297,7 +298,7 @@ class ScriptRunner:
297
298
 
298
299
  """
299
300
  if self._script_thread is not None:
300
- raise Exception("ScriptRunner was already started")
301
+ raise RuntimeError("ScriptRunner was already started")
301
302
 
302
303
  self._script_thread = threading.Thread(
303
304
  target=self._run_script_thread,
@@ -321,7 +322,10 @@ class ScriptRunner:
321
322
  If there is no ScriptRunContext for the current thread.
322
323
 
323
324
  """
324
- assert self._is_in_script_thread()
325
+ if not self._is_in_script_thread():
326
+ raise RuntimeError(
327
+ "ScriptRunner._get_script_run_ctx must be called from the script thread."
328
+ )
325
329
 
326
330
  ctx = get_script_run_ctx()
327
331
  if ctx is None:
@@ -341,7 +345,10 @@ class ScriptRunner:
341
345
  When the ScriptRequestQueue is empty, or when a SHUTDOWN request is
342
346
  dequeued, this function will exit and its thread will terminate.
343
347
  """
344
- assert self._is_in_script_thread()
348
+ if not self._is_in_script_thread():
349
+ raise RuntimeError(
350
+ "ScriptRunner._run_script_thread must be called from the script thread."
351
+ )
345
352
 
346
353
  _LOGGER.debug("Beginning script thread")
347
354
 
@@ -371,13 +378,18 @@ class ScriptRunner:
371
378
  self._run_script(request.rerun_data)
372
379
  request = self._requests.on_scriptrunner_ready()
373
380
 
374
- assert request.type == ScriptRequestType.STOP
381
+ if request.type != ScriptRequestType.STOP:
382
+ raise RuntimeError(
383
+ f"Unrecognized ScriptRequestType: {request.type}. This should never happen."
384
+ )
375
385
 
376
386
  # Send a SHUTDOWN event before exiting, so some state can be saved
377
387
  # for use in a future script run when not triggered by the client.
378
388
  client_state = ClientState()
379
389
  client_state.query_string = ctx.query_string
380
390
  client_state.page_script_hash = ctx.page_script_hash
391
+ if ctx.context_info:
392
+ client_state.context_info.CopyFrom(ctx.context_info)
381
393
  self.on_event.send(
382
394
  self, event=ScriptRunnerEvent.SHUTDOWN, client_state=client_state
383
395
  )
@@ -433,11 +445,14 @@ class ScriptRunner:
433
445
  if request.type == ScriptRequestType.RERUN:
434
446
  raise RerunException(request.rerun_data)
435
447
 
436
- assert request.type == ScriptRequestType.STOP
448
+ if request.type != ScriptRequestType.STOP:
449
+ raise RuntimeError(
450
+ f"Unrecognized ScriptRequestType: {request.type}. This should never happen."
451
+ )
437
452
  raise StopException()
438
453
 
439
454
  @contextmanager
440
- def _set_execing_flag(self):
455
+ def _set_execing_flag(self) -> Generator[None, None, None]:
441
456
  """A context for setting the ScriptRunner._execing flag.
442
457
 
443
458
  Used by _maybe_handle_execution_control_request to ensure that
@@ -461,7 +476,10 @@ class ScriptRunner:
461
476
 
462
477
  """
463
478
 
464
- assert self._is_in_script_thread()
479
+ if not self._is_in_script_thread():
480
+ raise RuntimeError(
481
+ "ScriptRunner._run_script must be called from the script thread."
482
+ )
465
483
 
466
484
  # An explicit loop instead of recursion to avoid stack overflows
467
485
  while True:
@@ -480,7 +498,7 @@ class ScriptRunner:
480
498
  rerun_data.page_script_hash, rerun_data.page_name
481
499
  )
482
500
  active_script = self._pages_manager.get_initial_active_script(
483
- rerun_data.page_script_hash, rerun_data.page_name
501
+ rerun_data.page_script_hash
484
502
  )
485
503
  main_page_info = self._pages_manager.get_main_page()
486
504
 
@@ -585,7 +603,12 @@ class ScriptRunner:
585
603
  # assume is the main script directory.
586
604
  module.__dict__["__file__"] = script_path
587
605
 
588
- def code_to_exec(code=code, module=module, ctx=ctx, rerun_data=rerun_data):
606
+ def code_to_exec(
607
+ code: str = code,
608
+ module: types.ModuleType = module,
609
+ ctx: ScriptRunContext = ctx,
610
+ rerun_data: RerunData = rerun_data,
611
+ ) -> None:
589
612
  with (
590
613
  modified_sys_path(self._main_script_path),
591
614
  self._set_execing_flag(),
@@ -606,7 +629,7 @@ class ScriptRunner:
606
629
  )
607
630
  wrapped_fragment()
608
631
 
609
- except FragmentStorageKeyError:
632
+ except FragmentStorageKeyError: # noqa: PERF203
610
633
  # This can happen if the fragment_id is removed from the
611
634
  # storage before the script runner gets to it. In this
612
635
  # case, the fragment is simply skipped.
@@ -618,20 +641,21 @@ class ScriptRunner:
618
641
  # (see https://github.com/streamlit/streamlit/issues/9080).
619
642
  if not rerun_data.is_auto_rerun:
620
643
  _LOGGER.warning(
621
- f"Couldn't find fragment with id {fragment_id}."
644
+ "Couldn't find fragment with id %s."
622
645
  " This can happen if the fragment does not"
623
646
  " exist anymore when this request is processed,"
624
647
  " for example because a full app rerun happened"
625
648
  " that did not register the fragment."
626
649
  " Usually this doesn't happen or no action is"
627
- " required, so its mainly for debugging."
650
+ " required, so its mainly for debugging.",
651
+ fragment_id,
628
652
  )
629
- except (RerunException, StopException) as e:
653
+ except (RerunException, StopException):
630
654
  # The wrapped_fragment function is executed
631
655
  # inside of a exec_func_with_error_handling call, so
632
656
  # there is a correct handler for these exceptions.
633
- raise e
634
- except Exception:
657
+ raise
658
+ except Exception: # noqa: S110
635
659
  # Ignore exceptions raised by fragments here as we don't
636
660
  # want to stop the execution of other fragments. The
637
661
  # error itself is already rendered within the wrapped
@@ -642,7 +666,7 @@ class ScriptRunner:
642
666
  if PagesManager.uses_pages_directory:
643
667
  _mpa_v1(self._main_script_path)
644
668
  else:
645
- exec(code, module.__dict__)
669
+ exec(code, module.__dict__) # noqa: S102
646
670
  self._fragment_storage.clear(
647
671
  new_fragment_ids=ctx.new_fragment_ids
648
672
  )
@@ -739,7 +763,7 @@ def _clean_problem_modules() -> None:
739
763
  try:
740
764
  keras = sys.modules["keras"]
741
765
  keras.backend.clear_session()
742
- except Exception:
766
+ except Exception: # noqa: S110
743
767
  # We don't want to crash the app if we can't clear the Keras session.
744
768
  pass
745
769
 
@@ -747,7 +771,7 @@ def _clean_problem_modules() -> None:
747
771
  try:
748
772
  plt = sys.modules["matplotlib.pyplot"]
749
773
  plt.close("all")
750
- except Exception:
774
+ except Exception: # noqa: S110
751
775
  # We don't want to crash the app if we can't close matplotlib
752
776
  pass
753
777
 
@@ -34,7 +34,7 @@ class StopException(ScriptControlException):
34
34
  class RerunException(ScriptControlException):
35
35
  """Silently stop and rerun the user's script."""
36
36
 
37
- def __init__(self, rerun_data: RerunData):
37
+ def __init__(self, rerun_data: RerunData) -> None:
38
38
  """Construct a RerunException.
39
39
 
40
40
  Parameters