streamlit-nightly 1.43.2.dev20250307__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 (563) hide show
  1. streamlit/__init__.py +306 -0
  2. streamlit/__main__.py +20 -0
  3. streamlit/auth_util.py +218 -0
  4. streamlit/cli_util.py +105 -0
  5. streamlit/column_config.py +56 -0
  6. streamlit/commands/__init__.py +13 -0
  7. streamlit/commands/echo.py +126 -0
  8. streamlit/commands/execution_control.py +238 -0
  9. streamlit/commands/experimental_query_params.py +169 -0
  10. streamlit/commands/logo.py +189 -0
  11. streamlit/commands/navigation.py +385 -0
  12. streamlit/commands/page_config.py +311 -0
  13. streamlit/components/__init__.py +13 -0
  14. streamlit/components/lib/__init__.py +13 -0
  15. streamlit/components/lib/local_component_registry.py +84 -0
  16. streamlit/components/types/__init__.py +13 -0
  17. streamlit/components/types/base_component_registry.py +99 -0
  18. streamlit/components/types/base_custom_component.py +150 -0
  19. streamlit/components/v1/__init__.py +31 -0
  20. streamlit/components/v1/component_arrow.py +141 -0
  21. streamlit/components/v1/component_registry.py +130 -0
  22. streamlit/components/v1/components.py +38 -0
  23. streamlit/components/v1/custom_component.py +243 -0
  24. streamlit/config.py +1513 -0
  25. streamlit/config_option.py +311 -0
  26. streamlit/config_util.py +177 -0
  27. streamlit/connections/__init__.py +28 -0
  28. streamlit/connections/base_connection.py +174 -0
  29. streamlit/connections/snowflake_connection.py +562 -0
  30. streamlit/connections/snowpark_connection.py +213 -0
  31. streamlit/connections/sql_connection.py +425 -0
  32. streamlit/connections/util.py +97 -0
  33. streamlit/cursor.py +210 -0
  34. streamlit/dataframe_util.py +1416 -0
  35. streamlit/delta_generator.py +602 -0
  36. streamlit/delta_generator_singletons.py +204 -0
  37. streamlit/deprecation_util.py +209 -0
  38. streamlit/development.py +21 -0
  39. streamlit/elements/__init__.py +13 -0
  40. streamlit/elements/alert.py +234 -0
  41. streamlit/elements/arrow.py +962 -0
  42. streamlit/elements/balloons.py +47 -0
  43. streamlit/elements/bokeh_chart.py +133 -0
  44. streamlit/elements/code.py +114 -0
  45. streamlit/elements/deck_gl_json_chart.py +546 -0
  46. streamlit/elements/dialog_decorator.py +267 -0
  47. streamlit/elements/doc_string.py +558 -0
  48. streamlit/elements/empty.py +130 -0
  49. streamlit/elements/exception.py +331 -0
  50. streamlit/elements/form.py +354 -0
  51. streamlit/elements/graphviz_chart.py +150 -0
  52. streamlit/elements/heading.py +302 -0
  53. streamlit/elements/html.py +105 -0
  54. streamlit/elements/iframe.py +191 -0
  55. streamlit/elements/image.py +196 -0
  56. streamlit/elements/json.py +139 -0
  57. streamlit/elements/layouts.py +879 -0
  58. streamlit/elements/lib/__init__.py +13 -0
  59. streamlit/elements/lib/built_in_chart_utils.py +1157 -0
  60. streamlit/elements/lib/color_util.py +263 -0
  61. streamlit/elements/lib/column_config_utils.py +542 -0
  62. streamlit/elements/lib/column_types.py +2188 -0
  63. streamlit/elements/lib/dialog.py +147 -0
  64. streamlit/elements/lib/dicttools.py +154 -0
  65. streamlit/elements/lib/event_utils.py +37 -0
  66. streamlit/elements/lib/file_uploader_utils.py +66 -0
  67. streamlit/elements/lib/form_utils.py +77 -0
  68. streamlit/elements/lib/image_utils.py +441 -0
  69. streamlit/elements/lib/js_number.py +105 -0
  70. streamlit/elements/lib/mutable_status_container.py +183 -0
  71. streamlit/elements/lib/options_selector_utils.py +250 -0
  72. streamlit/elements/lib/pandas_styler_utils.py +274 -0
  73. streamlit/elements/lib/policies.py +194 -0
  74. streamlit/elements/lib/streamlit_plotly_theme.py +207 -0
  75. streamlit/elements/lib/subtitle_utils.py +176 -0
  76. streamlit/elements/lib/utils.py +250 -0
  77. streamlit/elements/map.py +508 -0
  78. streamlit/elements/markdown.py +277 -0
  79. streamlit/elements/media.py +793 -0
  80. streamlit/elements/metric.py +301 -0
  81. streamlit/elements/plotly_chart.py +546 -0
  82. streamlit/elements/progress.py +156 -0
  83. streamlit/elements/pyplot.py +194 -0
  84. streamlit/elements/snow.py +47 -0
  85. streamlit/elements/spinner.py +113 -0
  86. streamlit/elements/text.py +76 -0
  87. streamlit/elements/toast.py +98 -0
  88. streamlit/elements/vega_charts.py +1984 -0
  89. streamlit/elements/widgets/__init__.py +13 -0
  90. streamlit/elements/widgets/audio_input.py +310 -0
  91. streamlit/elements/widgets/button.py +1123 -0
  92. streamlit/elements/widgets/button_group.py +1008 -0
  93. streamlit/elements/widgets/camera_input.py +263 -0
  94. streamlit/elements/widgets/chat.py +647 -0
  95. streamlit/elements/widgets/checkbox.py +352 -0
  96. streamlit/elements/widgets/color_picker.py +265 -0
  97. streamlit/elements/widgets/data_editor.py +983 -0
  98. streamlit/elements/widgets/file_uploader.py +486 -0
  99. streamlit/elements/widgets/multiselect.py +338 -0
  100. streamlit/elements/widgets/number_input.py +545 -0
  101. streamlit/elements/widgets/radio.py +407 -0
  102. streamlit/elements/widgets/select_slider.py +437 -0
  103. streamlit/elements/widgets/selectbox.py +366 -0
  104. streamlit/elements/widgets/slider.py +880 -0
  105. streamlit/elements/widgets/text_widgets.py +628 -0
  106. streamlit/elements/widgets/time_widgets.py +970 -0
  107. streamlit/elements/write.py +574 -0
  108. streamlit/emojis.py +34 -0
  109. streamlit/env_util.py +61 -0
  110. streamlit/error_util.py +105 -0
  111. streamlit/errors.py +452 -0
  112. streamlit/external/__init__.py +13 -0
  113. streamlit/external/langchain/__init__.py +23 -0
  114. streamlit/external/langchain/streamlit_callback_handler.py +406 -0
  115. streamlit/file_util.py +247 -0
  116. streamlit/git_util.py +173 -0
  117. streamlit/hello/__init__.py +13 -0
  118. streamlit/hello/animation_demo.py +82 -0
  119. streamlit/hello/dataframe_demo.py +71 -0
  120. streamlit/hello/hello.py +37 -0
  121. streamlit/hello/mapping_demo.py +114 -0
  122. streamlit/hello/plotting_demo.py +55 -0
  123. streamlit/hello/streamlit_app.py +55 -0
  124. streamlit/hello/utils.py +28 -0
  125. streamlit/logger.py +130 -0
  126. streamlit/material_icon_names.py +25 -0
  127. streamlit/navigation/__init__.py +13 -0
  128. streamlit/navigation/page.py +302 -0
  129. streamlit/net_util.py +125 -0
  130. streamlit/platform.py +33 -0
  131. streamlit/proto/Alert_pb2.py +29 -0
  132. streamlit/proto/Alert_pb2.pyi +90 -0
  133. streamlit/proto/AppPage_pb2.py +27 -0
  134. streamlit/proto/AppPage_pb2.pyi +64 -0
  135. streamlit/proto/ArrowNamedDataSet_pb2.py +28 -0
  136. streamlit/proto/ArrowNamedDataSet_pb2.pyi +57 -0
  137. streamlit/proto/ArrowVegaLiteChart_pb2.py +29 -0
  138. streamlit/proto/ArrowVegaLiteChart_pb2.pyi +84 -0
  139. streamlit/proto/Arrow_pb2.py +33 -0
  140. streamlit/proto/Arrow_pb2.pyi +188 -0
  141. streamlit/proto/AudioInput_pb2.py +28 -0
  142. streamlit/proto/AudioInput_pb2.pyi +58 -0
  143. streamlit/proto/Audio_pb2.py +27 -0
  144. streamlit/proto/Audio_pb2.pyi +58 -0
  145. streamlit/proto/AuthRedirect_pb2.py +27 -0
  146. streamlit/proto/AuthRedirect_pb2.pyi +41 -0
  147. streamlit/proto/AutoRerun_pb2.py +27 -0
  148. streamlit/proto/AutoRerun_pb2.pyi +45 -0
  149. streamlit/proto/BackMsg_pb2.py +29 -0
  150. streamlit/proto/BackMsg_pb2.pyi +105 -0
  151. streamlit/proto/Balloons_pb2.py +27 -0
  152. streamlit/proto/Balloons_pb2.pyi +43 -0
  153. streamlit/proto/Block_pb2.py +53 -0
  154. streamlit/proto/Block_pb2.pyi +322 -0
  155. streamlit/proto/BokehChart_pb2.py +27 -0
  156. streamlit/proto/BokehChart_pb2.pyi +49 -0
  157. streamlit/proto/ButtonGroup_pb2.py +36 -0
  158. streamlit/proto/ButtonGroup_pb2.pyi +169 -0
  159. streamlit/proto/Button_pb2.py +27 -0
  160. streamlit/proto/Button_pb2.pyi +71 -0
  161. streamlit/proto/CameraInput_pb2.py +28 -0
  162. streamlit/proto/CameraInput_pb2.pyi +58 -0
  163. streamlit/proto/ChatInput_pb2.py +31 -0
  164. streamlit/proto/ChatInput_pb2.pyi +111 -0
  165. streamlit/proto/Checkbox_pb2.py +30 -0
  166. streamlit/proto/Checkbox_pb2.pyi +90 -0
  167. streamlit/proto/ClientState_pb2.py +30 -0
  168. streamlit/proto/ClientState_pb2.pyi +90 -0
  169. streamlit/proto/Code_pb2.py +27 -0
  170. streamlit/proto/Code_pb2.pyi +55 -0
  171. streamlit/proto/ColorPicker_pb2.py +28 -0
  172. streamlit/proto/ColorPicker_pb2.pyi +67 -0
  173. streamlit/proto/Common_pb2.py +51 -0
  174. streamlit/proto/Common_pb2.pyi +293 -0
  175. streamlit/proto/Components_pb2.py +35 -0
  176. streamlit/proto/Components_pb2.pyi +172 -0
  177. streamlit/proto/DataFrame_pb2.py +56 -0
  178. streamlit/proto/DataFrame_pb2.pyi +397 -0
  179. streamlit/proto/DateInput_pb2.py +28 -0
  180. streamlit/proto/DateInput_pb2.pyi +83 -0
  181. streamlit/proto/DeckGlJsonChart_pb2.py +29 -0
  182. streamlit/proto/DeckGlJsonChart_pb2.pyi +102 -0
  183. streamlit/proto/Delta_pb2.py +31 -0
  184. streamlit/proto/Delta_pb2.pyi +74 -0
  185. streamlit/proto/DocString_pb2.py +29 -0
  186. streamlit/proto/DocString_pb2.pyi +93 -0
  187. streamlit/proto/DownloadButton_pb2.py +27 -0
  188. streamlit/proto/DownloadButton_pb2.pyi +70 -0
  189. streamlit/proto/Element_pb2.py +78 -0
  190. streamlit/proto/Element_pb2.pyi +312 -0
  191. streamlit/proto/Empty_pb2.py +27 -0
  192. streamlit/proto/Empty_pb2.pyi +36 -0
  193. streamlit/proto/Exception_pb2.py +27 -0
  194. streamlit/proto/Exception_pb2.pyi +72 -0
  195. streamlit/proto/Favicon_pb2.py +27 -0
  196. streamlit/proto/Favicon_pb2.pyi +40 -0
  197. streamlit/proto/FileUploader_pb2.py +28 -0
  198. streamlit/proto/FileUploader_pb2.pyi +78 -0
  199. streamlit/proto/ForwardMsg_pb2.py +53 -0
  200. streamlit/proto/ForwardMsg_pb2.pyi +293 -0
  201. streamlit/proto/GitInfo_pb2.py +29 -0
  202. streamlit/proto/GitInfo_pb2.pyi +83 -0
  203. streamlit/proto/GraphVizChart_pb2.py +27 -0
  204. streamlit/proto/GraphVizChart_pb2.pyi +53 -0
  205. streamlit/proto/Heading_pb2.py +27 -0
  206. streamlit/proto/Heading_pb2.pyi +56 -0
  207. streamlit/proto/Html_pb2.py +27 -0
  208. streamlit/proto/Html_pb2.pyi +42 -0
  209. streamlit/proto/IFrame_pb2.py +27 -0
  210. streamlit/proto/IFrame_pb2.pyi +59 -0
  211. streamlit/proto/Image_pb2.py +29 -0
  212. streamlit/proto/Image_pb2.pyi +84 -0
  213. streamlit/proto/Json_pb2.py +27 -0
  214. streamlit/proto/Json_pb2.pyi +53 -0
  215. streamlit/proto/LabelVisibilityMessage_pb2.py +29 -0
  216. streamlit/proto/LabelVisibilityMessage_pb2.pyi +68 -0
  217. streamlit/proto/LinkButton_pb2.py +27 -0
  218. streamlit/proto/LinkButton_pb2.pyi +58 -0
  219. streamlit/proto/Logo_pb2.py +27 -0
  220. streamlit/proto/Logo_pb2.pyi +51 -0
  221. streamlit/proto/Markdown_pb2.py +29 -0
  222. streamlit/proto/Markdown_pb2.pyi +86 -0
  223. streamlit/proto/Metric_pb2.py +32 -0
  224. streamlit/proto/Metric_pb2.pyi +101 -0
  225. streamlit/proto/MetricsEvent_pb2.py +30 -0
  226. streamlit/proto/MetricsEvent_pb2.pyi +200 -0
  227. streamlit/proto/MultiSelect_pb2.py +28 -0
  228. streamlit/proto/MultiSelect_pb2.pyi +81 -0
  229. streamlit/proto/NamedDataSet_pb2.py +28 -0
  230. streamlit/proto/NamedDataSet_pb2.pyi +59 -0
  231. streamlit/proto/Navigation_pb2.py +30 -0
  232. streamlit/proto/Navigation_pb2.pyi +84 -0
  233. streamlit/proto/NewSession_pb2.py +51 -0
  234. streamlit/proto/NewSession_pb2.pyi +481 -0
  235. streamlit/proto/NumberInput_pb2.py +30 -0
  236. streamlit/proto/NumberInput_pb2.pyi +121 -0
  237. streamlit/proto/PageConfig_pb2.py +33 -0
  238. streamlit/proto/PageConfig_pb2.pyi +126 -0
  239. streamlit/proto/PageInfo_pb2.py +27 -0
  240. streamlit/proto/PageInfo_pb2.pyi +43 -0
  241. streamlit/proto/PageLink_pb2.py +27 -0
  242. streamlit/proto/PageLink_pb2.pyi +63 -0
  243. streamlit/proto/PageNotFound_pb2.py +27 -0
  244. streamlit/proto/PageNotFound_pb2.pyi +42 -0
  245. streamlit/proto/PageProfile_pb2.py +31 -0
  246. streamlit/proto/PageProfile_pb2.pyi +127 -0
  247. streamlit/proto/PagesChanged_pb2.py +28 -0
  248. streamlit/proto/PagesChanged_pb2.pyi +48 -0
  249. streamlit/proto/ParentMessage_pb2.py +27 -0
  250. streamlit/proto/ParentMessage_pb2.pyi +46 -0
  251. streamlit/proto/PlotlyChart_pb2.py +31 -0
  252. streamlit/proto/PlotlyChart_pb2.pyi +131 -0
  253. streamlit/proto/Progress_pb2.py +27 -0
  254. streamlit/proto/Progress_pb2.pyi +43 -0
  255. streamlit/proto/Radio_pb2.py +28 -0
  256. streamlit/proto/Radio_pb2.pyi +84 -0
  257. streamlit/proto/RootContainer_pb2.py +27 -0
  258. streamlit/proto/RootContainer_pb2.pyi +56 -0
  259. streamlit/proto/Selectbox_pb2.py +28 -0
  260. streamlit/proto/Selectbox_pb2.pyi +80 -0
  261. streamlit/proto/SessionEvent_pb2.py +28 -0
  262. streamlit/proto/SessionEvent_pb2.pyi +62 -0
  263. streamlit/proto/SessionStatus_pb2.py +27 -0
  264. streamlit/proto/SessionStatus_pb2.pyi +57 -0
  265. streamlit/proto/Skeleton_pb2.py +29 -0
  266. streamlit/proto/Skeleton_pb2.pyi +71 -0
  267. streamlit/proto/Slider_pb2.py +32 -0
  268. streamlit/proto/Slider_pb2.pyi +142 -0
  269. streamlit/proto/Snow_pb2.py +27 -0
  270. streamlit/proto/Snow_pb2.pyi +43 -0
  271. streamlit/proto/Spinner_pb2.py +27 -0
  272. streamlit/proto/Spinner_pb2.pyi +49 -0
  273. streamlit/proto/TextArea_pb2.py +28 -0
  274. streamlit/proto/TextArea_pb2.pyi +80 -0
  275. streamlit/proto/TextInput_pb2.py +30 -0
  276. streamlit/proto/TextInput_pb2.pyi +107 -0
  277. streamlit/proto/Text_pb2.py +27 -0
  278. streamlit/proto/Text_pb2.pyi +46 -0
  279. streamlit/proto/TimeInput_pb2.py +28 -0
  280. streamlit/proto/TimeInput_pb2.pyi +74 -0
  281. streamlit/proto/Toast_pb2.py +27 -0
  282. streamlit/proto/Toast_pb2.pyi +45 -0
  283. streamlit/proto/VegaLiteChart_pb2.py +29 -0
  284. streamlit/proto/VegaLiteChart_pb2.pyi +71 -0
  285. streamlit/proto/Video_pb2.py +31 -0
  286. streamlit/proto/Video_pb2.pyi +117 -0
  287. streamlit/proto/WidgetStates_pb2.py +31 -0
  288. streamlit/proto/WidgetStates_pb2.pyi +126 -0
  289. streamlit/proto/__init__.py +15 -0
  290. streamlit/proto/openmetrics_data_model_pb2.py +60 -0
  291. streamlit/proto/openmetrics_data_model_pb2.pyi +522 -0
  292. streamlit/py.typed +0 -0
  293. streamlit/runtime/__init__.py +50 -0
  294. streamlit/runtime/app_session.py +982 -0
  295. streamlit/runtime/caching/__init__.py +98 -0
  296. streamlit/runtime/caching/cache_data_api.py +665 -0
  297. streamlit/runtime/caching/cache_errors.py +142 -0
  298. streamlit/runtime/caching/cache_resource_api.py +527 -0
  299. streamlit/runtime/caching/cache_type.py +33 -0
  300. streamlit/runtime/caching/cache_utils.py +523 -0
  301. streamlit/runtime/caching/cached_message_replay.py +290 -0
  302. streamlit/runtime/caching/hashing.py +637 -0
  303. streamlit/runtime/caching/legacy_cache_api.py +169 -0
  304. streamlit/runtime/caching/storage/__init__.py +29 -0
  305. streamlit/runtime/caching/storage/cache_storage_protocol.py +239 -0
  306. streamlit/runtime/caching/storage/dummy_cache_storage.py +60 -0
  307. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +145 -0
  308. streamlit/runtime/caching/storage/local_disk_cache_storage.py +223 -0
  309. streamlit/runtime/connection_factory.py +436 -0
  310. streamlit/runtime/context.py +280 -0
  311. streamlit/runtime/credentials.py +364 -0
  312. streamlit/runtime/forward_msg_cache.py +296 -0
  313. streamlit/runtime/forward_msg_queue.py +240 -0
  314. streamlit/runtime/fragment.py +477 -0
  315. streamlit/runtime/media_file_manager.py +234 -0
  316. streamlit/runtime/media_file_storage.py +143 -0
  317. streamlit/runtime/memory_media_file_storage.py +181 -0
  318. streamlit/runtime/memory_session_storage.py +77 -0
  319. streamlit/runtime/memory_uploaded_file_manager.py +138 -0
  320. streamlit/runtime/metrics_util.py +486 -0
  321. streamlit/runtime/pages_manager.py +165 -0
  322. streamlit/runtime/runtime.py +792 -0
  323. streamlit/runtime/runtime_util.py +106 -0
  324. streamlit/runtime/script_data.py +46 -0
  325. streamlit/runtime/scriptrunner/__init__.py +38 -0
  326. streamlit/runtime/scriptrunner/exec_code.py +159 -0
  327. streamlit/runtime/scriptrunner/magic.py +273 -0
  328. streamlit/runtime/scriptrunner/magic_funcs.py +32 -0
  329. streamlit/runtime/scriptrunner/script_cache.py +89 -0
  330. streamlit/runtime/scriptrunner/script_runner.py +756 -0
  331. streamlit/runtime/scriptrunner_utils/__init__.py +19 -0
  332. streamlit/runtime/scriptrunner_utils/exceptions.py +48 -0
  333. streamlit/runtime/scriptrunner_utils/script_requests.py +307 -0
  334. streamlit/runtime/scriptrunner_utils/script_run_context.py +287 -0
  335. streamlit/runtime/secrets.py +534 -0
  336. streamlit/runtime/session_manager.py +394 -0
  337. streamlit/runtime/state/__init__.py +41 -0
  338. streamlit/runtime/state/common.py +191 -0
  339. streamlit/runtime/state/query_params.py +205 -0
  340. streamlit/runtime/state/query_params_proxy.py +218 -0
  341. streamlit/runtime/state/safe_session_state.py +138 -0
  342. streamlit/runtime/state/session_state.py +772 -0
  343. streamlit/runtime/state/session_state_proxy.py +153 -0
  344. streamlit/runtime/state/widgets.py +135 -0
  345. streamlit/runtime/stats.py +109 -0
  346. streamlit/runtime/uploaded_file_manager.py +148 -0
  347. streamlit/runtime/websocket_session_manager.py +167 -0
  348. streamlit/source_util.py +98 -0
  349. streamlit/static/favicon.png +0 -0
  350. streamlit/static/index.html +61 -0
  351. streamlit/static/static/css/index.Bmkmz40k.css +1 -0
  352. streamlit/static/static/css/index.DpJG_94W.css +1 -0
  353. streamlit/static/static/css/index.DzuxGC_t.css +1 -0
  354. streamlit/static/static/js/FileDownload.esm.Bp9m5jrx.js +1 -0
  355. streamlit/static/static/js/FileHelper.D_3pbilj.js +5 -0
  356. streamlit/static/static/js/FormClearHelper.Ct2rwLXo.js +1 -0
  357. streamlit/static/static/js/Hooks.BKdzj5MJ.js +1 -0
  358. streamlit/static/static/js/InputInstructions.DB3QGNJP.js +1 -0
  359. streamlit/static/static/js/ProgressBar.D40A5xc2.js +2 -0
  360. streamlit/static/static/js/RenderInPortalIfExists.DLUCooTN.js +1 -0
  361. streamlit/static/static/js/Toolbar.BiGGIQun.js +1 -0
  362. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +1 -0
  363. streamlit/static/static/js/base-input.CQBQT24M.js +4 -0
  364. streamlit/static/static/js/checkbox.Buj8gd_M.js +9 -0
  365. streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +1 -0
  366. streamlit/static/static/js/createSuper.CesK3I23.js +1 -0
  367. streamlit/static/static/js/data-grid-overlay-editor.B69OOFM4.js +1 -0
  368. streamlit/static/static/js/downloader.BZQhlBNT.js +1 -0
  369. streamlit/static/static/js/es6.D9Zhqujy.js +2 -0
  370. streamlit/static/static/js/iframeResizer.contentWindow.CAzcBpCC.js +1 -0
  371. streamlit/static/static/js/index.08vcOOvb.js +1 -0
  372. streamlit/static/static/js/index.0uqKfJUS.js +1 -0
  373. streamlit/static/static/js/index.B02M5u69.js +203 -0
  374. streamlit/static/static/js/index.B7mcZKMx.js +1 -0
  375. streamlit/static/static/js/index.BAQDHFA_.js +1 -0
  376. streamlit/static/static/js/index.BI60cMVr.js +2 -0
  377. streamlit/static/static/js/index.BLug2inK.js +1 -0
  378. streamlit/static/static/js/index.BM6TMY8g.js +2 -0
  379. streamlit/static/static/js/index.BZ9p1t7G.js +1 -0
  380. streamlit/static/static/js/index.BZqa87a1.js +2 -0
  381. streamlit/static/static/js/index.BcsRUzZZ.js +1 -0
  382. streamlit/static/static/js/index.BgVMiY_P.js +197 -0
  383. streamlit/static/static/js/index.BtuGy7By.js +6 -0
  384. streamlit/static/static/js/index.BuDuBmrs.js +1 -0
  385. streamlit/static/static/js/index.BvXU2oKV.js +1 -0
  386. streamlit/static/static/js/index.BxcwPacT.js +73 -0
  387. streamlit/static/static/js/index.CWX8KB81.js +1 -0
  388. streamlit/static/static/js/index.CXzZTo_q.js +1 -0
  389. streamlit/static/static/js/index.CcRWp_KL.js +1 -0
  390. streamlit/static/static/js/index.Cd-_xe55.js +3 -0
  391. streamlit/static/static/js/index.CdG2PXln.js +4537 -0
  392. streamlit/static/static/js/index.CjXvXmcP.js +1 -0
  393. streamlit/static/static/js/index.D1HZENZx.js +776 -0
  394. streamlit/static/static/js/index.D21Efo64.js +1617 -0
  395. streamlit/static/static/js/index.D9WgGVBx.js +7 -0
  396. streamlit/static/static/js/index.DEcsHtvb.js +12 -0
  397. streamlit/static/static/js/index.DFeMfr_K.js +1 -0
  398. streamlit/static/static/js/index.DHFBoItz.js +1 -0
  399. streamlit/static/static/js/index.D_PrBKnJ.js +3 -0
  400. streamlit/static/static/js/index.DmuRkekN.js +3855 -0
  401. streamlit/static/static/js/index.Do6eY8sf.js +1 -0
  402. streamlit/static/static/js/index.Dz3lP2P-.js +1 -0
  403. streamlit/static/static/js/index.Dz_UqF-s.js +1 -0
  404. streamlit/static/static/js/index.GkSUsPhJ.js +1 -0
  405. streamlit/static/static/js/index.H1U1IC_d.js +3 -0
  406. streamlit/static/static/js/index.g6p_4DPr.js +1 -0
  407. streamlit/static/static/js/index.g9x_GKss.js +1 -0
  408. streamlit/static/static/js/index.zo9jm08y.js +1 -0
  409. streamlit/static/static/js/input.DnaFglHq.js +2 -0
  410. streamlit/static/static/js/inputUtils.CQWz5UKz.js +1 -0
  411. streamlit/static/static/js/memory.Crb9x4-F.js +1 -0
  412. streamlit/static/static/js/mergeWith.ouAz0sK3.js +1 -0
  413. streamlit/static/static/js/number-overlay-editor._UaN-O48.js +9 -0
  414. streamlit/static/static/js/possibleConstructorReturn.CtGjGFHz.js +1 -0
  415. streamlit/static/static/js/sandbox.CBybYOhV.js +1 -0
  416. streamlit/static/static/js/sprintf.D7DtBTRn.js +1 -0
  417. streamlit/static/static/js/textarea.Cb_uJt5U.js +2 -0
  418. streamlit/static/static/js/threshold.DjX0wlsa.js +1 -0
  419. streamlit/static/static/js/timepicker.DKT7pfoF.js +4 -0
  420. streamlit/static/static/js/timer.CAwTRJ_g.js +1 -0
  421. streamlit/static/static/js/toConsumableArray.05Ikp13-.js +3 -0
  422. streamlit/static/static/js/uniqueId.D2FMWUEI.js +1 -0
  423. streamlit/static/static/js/useBasicWidgetState.urnZLANY.js +1 -0
  424. streamlit/static/static/js/useOnInputChange.BOKIIdJ1.js +1 -0
  425. streamlit/static/static/js/value.CgPGBV_l.js +1 -0
  426. streamlit/static/static/js/withFullScreenWrapper.C_N8J0Xx.js +1 -0
  427. streamlit/static/static/media/KaTeX_AMS-Regular.BQhdFMY1.woff2 +0 -0
  428. streamlit/static/static/media/KaTeX_AMS-Regular.DMm9YOAa.woff +0 -0
  429. streamlit/static/static/media/KaTeX_AMS-Regular.DRggAlZN.ttf +0 -0
  430. streamlit/static/static/media/KaTeX_Caligraphic-Bold.ATXxdsX0.ttf +0 -0
  431. streamlit/static/static/media/KaTeX_Caligraphic-Bold.BEiXGLvX.woff +0 -0
  432. streamlit/static/static/media/KaTeX_Caligraphic-Bold.Dq_IR9rO.woff2 +0 -0
  433. streamlit/static/static/media/KaTeX_Caligraphic-Regular.CTRA-rTL.woff +0 -0
  434. streamlit/static/static/media/KaTeX_Caligraphic-Regular.Di6jR-x-.woff2 +0 -0
  435. streamlit/static/static/media/KaTeX_Caligraphic-Regular.wX97UBjC.ttf +0 -0
  436. streamlit/static/static/media/KaTeX_Fraktur-Bold.BdnERNNW.ttf +0 -0
  437. streamlit/static/static/media/KaTeX_Fraktur-Bold.BsDP51OF.woff +0 -0
  438. streamlit/static/static/media/KaTeX_Fraktur-Bold.CL6g_b3V.woff2 +0 -0
  439. streamlit/static/static/media/KaTeX_Fraktur-Regular.CB_wures.ttf +0 -0
  440. streamlit/static/static/media/KaTeX_Fraktur-Regular.CTYiF6lA.woff2 +0 -0
  441. streamlit/static/static/media/KaTeX_Fraktur-Regular.Dxdc4cR9.woff +0 -0
  442. streamlit/static/static/media/KaTeX_Main-Bold.Cx986IdX.woff2 +0 -0
  443. streamlit/static/static/media/KaTeX_Main-Bold.Jm3AIy58.woff +0 -0
  444. streamlit/static/static/media/KaTeX_Main-Bold.waoOVXN0.ttf +0 -0
  445. streamlit/static/static/media/KaTeX_Main-BoldItalic.DxDJ3AOS.woff2 +0 -0
  446. streamlit/static/static/media/KaTeX_Main-BoldItalic.DzxPMmG6.ttf +0 -0
  447. streamlit/static/static/media/KaTeX_Main-BoldItalic.SpSLRI95.woff +0 -0
  448. streamlit/static/static/media/KaTeX_Main-Italic.3WenGoN9.ttf +0 -0
  449. streamlit/static/static/media/KaTeX_Main-Italic.BMLOBm91.woff +0 -0
  450. streamlit/static/static/media/KaTeX_Main-Italic.NWA7e6Wa.woff2 +0 -0
  451. streamlit/static/static/media/KaTeX_Main-Regular.B22Nviop.woff2 +0 -0
  452. streamlit/static/static/media/KaTeX_Main-Regular.Dr94JaBh.woff +0 -0
  453. streamlit/static/static/media/KaTeX_Main-Regular.ypZvNtVU.ttf +0 -0
  454. streamlit/static/static/media/KaTeX_Math-BoldItalic.B3XSjfu4.ttf +0 -0
  455. streamlit/static/static/media/KaTeX_Math-BoldItalic.CZnvNsCZ.woff2 +0 -0
  456. streamlit/static/static/media/KaTeX_Math-BoldItalic.iY-2wyZ7.woff +0 -0
  457. streamlit/static/static/media/KaTeX_Math-Italic.DA0__PXp.woff +0 -0
  458. streamlit/static/static/media/KaTeX_Math-Italic.flOr_0UB.ttf +0 -0
  459. streamlit/static/static/media/KaTeX_Math-Italic.t53AETM-.woff2 +0 -0
  460. streamlit/static/static/media/KaTeX_SansSerif-Bold.CFMepnvq.ttf +0 -0
  461. streamlit/static/static/media/KaTeX_SansSerif-Bold.D1sUS0GD.woff2 +0 -0
  462. streamlit/static/static/media/KaTeX_SansSerif-Bold.DbIhKOiC.woff +0 -0
  463. streamlit/static/static/media/KaTeX_SansSerif-Italic.C3H0VqGB.woff2 +0 -0
  464. streamlit/static/static/media/KaTeX_SansSerif-Italic.DN2j7dab.woff +0 -0
  465. streamlit/static/static/media/KaTeX_SansSerif-Italic.YYjJ1zSn.ttf +0 -0
  466. streamlit/static/static/media/KaTeX_SansSerif-Regular.BNo7hRIc.ttf +0 -0
  467. streamlit/static/static/media/KaTeX_SansSerif-Regular.CS6fqUqJ.woff +0 -0
  468. streamlit/static/static/media/KaTeX_SansSerif-Regular.DDBCnlJ7.woff2 +0 -0
  469. streamlit/static/static/media/KaTeX_Script-Regular.C5JkGWo-.ttf +0 -0
  470. streamlit/static/static/media/KaTeX_Script-Regular.D3wIWfF6.woff2 +0 -0
  471. streamlit/static/static/media/KaTeX_Script-Regular.D5yQViql.woff +0 -0
  472. streamlit/static/static/media/KaTeX_Size1-Regular.C195tn64.woff +0 -0
  473. streamlit/static/static/media/KaTeX_Size1-Regular.Dbsnue_I.ttf +0 -0
  474. streamlit/static/static/media/KaTeX_Size1-Regular.mCD8mA8B.woff2 +0 -0
  475. streamlit/static/static/media/KaTeX_Size2-Regular.B7gKUWhC.ttf +0 -0
  476. streamlit/static/static/media/KaTeX_Size2-Regular.Dy4dx90m.woff2 +0 -0
  477. streamlit/static/static/media/KaTeX_Size2-Regular.oD1tc_U0.woff +0 -0
  478. streamlit/static/static/media/KaTeX_Size3-Regular.CTq5MqoE.woff +0 -0
  479. streamlit/static/static/media/KaTeX_Size3-Regular.DgpXs0kz.ttf +0 -0
  480. streamlit/static/static/media/KaTeX_Size4-Regular.BF-4gkZK.woff +0 -0
  481. streamlit/static/static/media/KaTeX_Size4-Regular.DWFBv043.ttf +0 -0
  482. streamlit/static/static/media/KaTeX_Size4-Regular.Dl5lxZxV.woff2 +0 -0
  483. streamlit/static/static/media/KaTeX_Typewriter-Regular.C0xS9mPB.woff +0 -0
  484. streamlit/static/static/media/KaTeX_Typewriter-Regular.CO6r4hn1.woff2 +0 -0
  485. streamlit/static/static/media/KaTeX_Typewriter-Regular.D3Ib7_Hf.ttf +0 -0
  486. streamlit/static/static/media/MaterialSymbols-Rounded.DcZbplWk.woff2 +0 -0
  487. streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
  488. streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
  489. streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
  490. streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
  491. streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
  492. streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
  493. streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
  494. streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
  495. streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
  496. streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
  497. streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
  498. streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
  499. streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
  500. streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
  501. streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
  502. streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
  503. streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
  504. streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
  505. streamlit/static/static/media/balloon-0.Czj7AKwE.png +0 -0
  506. streamlit/static/static/media/balloon-1.CNvFFrND.png +0 -0
  507. streamlit/static/static/media/balloon-2.DTvC6B1t.png +0 -0
  508. streamlit/static/static/media/balloon-3.CgSk4tbL.png +0 -0
  509. streamlit/static/static/media/balloon-4.mbtFrzxf.png +0 -0
  510. streamlit/static/static/media/balloon-5.CSwkUfRA.png +0 -0
  511. streamlit/static/static/media/fireworks.B4d-_KUe.gif +0 -0
  512. streamlit/static/static/media/flake-0.DgWaVvm5.png +0 -0
  513. streamlit/static/static/media/flake-1.B2r5AHMK.png +0 -0
  514. streamlit/static/static/media/flake-2.BnWSExPC.png +0 -0
  515. streamlit/static/static/media/snowflake.JU2jBHL8.svg +11 -0
  516. streamlit/string_util.py +203 -0
  517. streamlit/temporary_directory.py +56 -0
  518. streamlit/testing/__init__.py +13 -0
  519. streamlit/testing/v1/__init__.py +17 -0
  520. streamlit/testing/v1/app_test.py +1050 -0
  521. streamlit/testing/v1/element_tree.py +2083 -0
  522. streamlit/testing/v1/local_script_runner.py +180 -0
  523. streamlit/testing/v1/util.py +53 -0
  524. streamlit/time_util.py +75 -0
  525. streamlit/type_util.py +460 -0
  526. streamlit/url_util.py +122 -0
  527. streamlit/user_info.py +519 -0
  528. streamlit/util.py +72 -0
  529. streamlit/vendor/__init__.py +0 -0
  530. streamlit/vendor/pympler/__init__.py +0 -0
  531. streamlit/vendor/pympler/asizeof.py +2869 -0
  532. streamlit/version.py +18 -0
  533. streamlit/watcher/__init__.py +28 -0
  534. streamlit/watcher/event_based_path_watcher.py +406 -0
  535. streamlit/watcher/folder_black_list.py +82 -0
  536. streamlit/watcher/local_sources_watcher.py +233 -0
  537. streamlit/watcher/path_watcher.py +185 -0
  538. streamlit/watcher/polling_path_watcher.py +124 -0
  539. streamlit/watcher/util.py +207 -0
  540. streamlit/web/__init__.py +13 -0
  541. streamlit/web/bootstrap.py +353 -0
  542. streamlit/web/cache_storage_manager_config.py +38 -0
  543. streamlit/web/cli.py +369 -0
  544. streamlit/web/server/__init__.py +26 -0
  545. streamlit/web/server/app_static_file_handler.py +93 -0
  546. streamlit/web/server/authlib_tornado_integration.py +60 -0
  547. streamlit/web/server/browser_websocket_handler.py +246 -0
  548. streamlit/web/server/component_request_handler.py +116 -0
  549. streamlit/web/server/media_file_handler.py +141 -0
  550. streamlit/web/server/oauth_authlib_routes.py +176 -0
  551. streamlit/web/server/oidc_mixin.py +108 -0
  552. streamlit/web/server/routes.py +295 -0
  553. streamlit/web/server/server.py +479 -0
  554. streamlit/web/server/server_util.py +161 -0
  555. streamlit/web/server/stats_request_handler.py +95 -0
  556. streamlit/web/server/upload_file_request_handler.py +137 -0
  557. streamlit/web/server/websocket_headers.py +56 -0
  558. streamlit_nightly-1.43.2.dev20250307.data/scripts/streamlit.cmd +16 -0
  559. streamlit_nightly-1.43.2.dev20250307.dist-info/METADATA +207 -0
  560. streamlit_nightly-1.43.2.dev20250307.dist-info/RECORD +563 -0
  561. streamlit_nightly-1.43.2.dev20250307.dist-info/WHEEL +5 -0
  562. streamlit_nightly-1.43.2.dev20250307.dist-info/entry_points.txt +2 -0
  563. streamlit_nightly-1.43.2.dev20250307.dist-info/top_level.txt +1 -0
@@ -0,0 +1,792 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import asyncio
18
+ import time
19
+ import traceback
20
+ from dataclasses import dataclass, field
21
+ from enum import Enum
22
+ from typing import TYPE_CHECKING, Final, NamedTuple
23
+
24
+ from streamlit import config
25
+ from streamlit.components.lib.local_component_registry import LocalComponentRegistry
26
+ from streamlit.logger import get_logger
27
+ from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
28
+ from streamlit.runtime.app_session import AppSession
29
+ from streamlit.runtime.caching import (
30
+ get_data_cache_stats_provider,
31
+ get_resource_cache_stats_provider,
32
+ )
33
+ from streamlit.runtime.caching.storage.local_disk_cache_storage import (
34
+ LocalDiskCacheStorageManager,
35
+ )
36
+ from streamlit.runtime.forward_msg_cache import (
37
+ ForwardMsgCache,
38
+ create_reference_msg,
39
+ populate_hash_if_needed,
40
+ )
41
+ from streamlit.runtime.media_file_manager import MediaFileManager
42
+ from streamlit.runtime.memory_session_storage import MemorySessionStorage
43
+ from streamlit.runtime.runtime_util import is_cacheable_msg
44
+ from streamlit.runtime.script_data import ScriptData
45
+ from streamlit.runtime.scriptrunner.script_cache import ScriptCache
46
+ from streamlit.runtime.session_manager import (
47
+ ActiveSessionInfo,
48
+ SessionClient,
49
+ SessionClientDisconnectedError,
50
+ SessionManager,
51
+ SessionStorage,
52
+ )
53
+ from streamlit.runtime.state import (
54
+ SCRIPT_RUN_WITHOUT_ERRORS_KEY,
55
+ SessionStateStatProvider,
56
+ )
57
+ from streamlit.runtime.stats import StatsManager
58
+ from streamlit.runtime.websocket_session_manager import WebsocketSessionManager
59
+
60
+ if TYPE_CHECKING:
61
+ from collections.abc import Awaitable
62
+
63
+ from streamlit.components.types.base_component_registry import BaseComponentRegistry
64
+ from streamlit.proto.BackMsg_pb2 import BackMsg
65
+ from streamlit.runtime.caching.storage import CacheStorageManager
66
+ from streamlit.runtime.media_file_storage import MediaFileStorage
67
+ from streamlit.runtime.uploaded_file_manager import UploadedFileManager
68
+
69
+ # Wait for the script run result for 60s and if no result is available give up
70
+ SCRIPT_RUN_CHECK_TIMEOUT: Final = 60
71
+
72
+ _LOGGER: Final = get_logger(__name__)
73
+
74
+
75
+ class RuntimeStoppedError(Exception):
76
+ """Raised by operations on a Runtime instance that is stopped."""
77
+
78
+
79
+ @dataclass(frozen=True)
80
+ class RuntimeConfig:
81
+ """Config options for StreamlitRuntime."""
82
+
83
+ # The filesystem path of the Streamlit script to run.
84
+ script_path: str
85
+
86
+ # DEPRECATED: We need to keep this field around for compatibility reasons, but we no
87
+ # longer use this anywhere.
88
+ command_line: str | None
89
+
90
+ # The storage backend for Streamlit's MediaFileManager.
91
+ media_file_storage: MediaFileStorage
92
+
93
+ # The upload file manager
94
+ uploaded_file_manager: UploadedFileManager
95
+
96
+ # The cache storage backend for Streamlit's st.cache_data.
97
+ cache_storage_manager: CacheStorageManager = field(
98
+ default_factory=LocalDiskCacheStorageManager
99
+ )
100
+
101
+ # The ComponentRegistry instance to use.
102
+ component_registry: BaseComponentRegistry = field(
103
+ default_factory=LocalComponentRegistry
104
+ )
105
+
106
+ # The SessionManager class to be used.
107
+ session_manager_class: type[SessionManager] = WebsocketSessionManager
108
+
109
+ # The SessionStorage instance for the SessionManager to use.
110
+ session_storage: SessionStorage = field(default_factory=MemorySessionStorage)
111
+
112
+ # True if the command used to start Streamlit was `streamlit hello`.
113
+ is_hello: bool = False
114
+
115
+ # TODO(vdonato): Eventually add a new fragment_storage_class field enabling the code
116
+ # creating a new Streamlit Runtime to configure the FragmentStorage instances
117
+ # created by each new AppSession. We choose not to do this for now to avoid adding
118
+ # additional complexity to RuntimeConfig/SessionManager/etc when it's unlikely
119
+ # we'll have a custom implementation of this class anytime soon.
120
+
121
+
122
+ class RuntimeState(Enum):
123
+ INITIAL = "INITIAL"
124
+ NO_SESSIONS_CONNECTED = "NO_SESSIONS_CONNECTED"
125
+ ONE_OR_MORE_SESSIONS_CONNECTED = "ONE_OR_MORE_SESSIONS_CONNECTED"
126
+ STOPPING = "STOPPING"
127
+ STOPPED = "STOPPED"
128
+
129
+
130
+ class AsyncObjects(NamedTuple):
131
+ """Container for all asyncio objects that Runtime manages.
132
+ These cannot be initialized until the Runtime's eventloop is assigned.
133
+ """
134
+
135
+ # The eventloop that Runtime is running on.
136
+ eventloop: asyncio.AbstractEventLoop
137
+
138
+ # Set after Runtime.stop() is called. Never cleared.
139
+ must_stop: asyncio.Event
140
+
141
+ # Set when a client connects; cleared when we have no connected clients.
142
+ has_connection: asyncio.Event
143
+
144
+ # Set after a ForwardMsg is enqueued; cleared when we flush ForwardMsgs.
145
+ need_send_data: asyncio.Event
146
+
147
+ # Completed when the Runtime has started.
148
+ started: asyncio.Future[None]
149
+
150
+ # Completed when the Runtime has stopped.
151
+ stopped: asyncio.Future[None]
152
+
153
+
154
+ class Runtime:
155
+ _instance: Runtime | None = None
156
+
157
+ @classmethod
158
+ def instance(cls) -> Runtime:
159
+ """Return the singleton Runtime instance. Raise an Error if the
160
+ Runtime hasn't been created yet.
161
+ """
162
+ if cls._instance is None:
163
+ raise RuntimeError("Runtime hasn't been created!")
164
+ return cls._instance
165
+
166
+ @classmethod
167
+ def exists(cls) -> bool:
168
+ """True if the singleton Runtime instance has been created.
169
+
170
+ When a Streamlit app is running in "raw mode" - that is, when the
171
+ app is run via `python app.py` instead of `streamlit run app.py` -
172
+ the Runtime will not exist, and various Streamlit functions need
173
+ to adapt.
174
+ """
175
+ return cls._instance is not None
176
+
177
+ def __init__(self, config: RuntimeConfig):
178
+ """Create a Runtime instance. It won't be started yet.
179
+
180
+ Runtime is *not* thread-safe. Its public methods are generally
181
+ safe to call only on the same thread that its event loop runs on.
182
+
183
+ Parameters
184
+ ----------
185
+ config
186
+ Config options.
187
+ """
188
+ if Runtime._instance is not None:
189
+ raise RuntimeError("Runtime instance already exists!")
190
+ Runtime._instance = self
191
+
192
+ # Will be created when we start.
193
+ self._async_objs: AsyncObjects | None = None
194
+
195
+ # The task that runs our main loop. We need to save a reference
196
+ # to it so that it doesn't get garbage collected while running.
197
+ self._loop_coroutine_task: asyncio.Task[None] | None = None
198
+
199
+ self._main_script_path = config.script_path
200
+ self._is_hello = config.is_hello
201
+
202
+ self._state = RuntimeState.INITIAL
203
+
204
+ # Initialize managers
205
+ self._component_registry = config.component_registry
206
+ self._message_cache = ForwardMsgCache()
207
+ self._uploaded_file_mgr = config.uploaded_file_manager
208
+ self._media_file_mgr = MediaFileManager(storage=config.media_file_storage)
209
+ self._cache_storage_manager = config.cache_storage_manager
210
+ self._script_cache = ScriptCache()
211
+
212
+ self._session_mgr = config.session_manager_class(
213
+ session_storage=config.session_storage,
214
+ uploaded_file_manager=self._uploaded_file_mgr,
215
+ script_cache=self._script_cache,
216
+ message_enqueued_callback=self._enqueued_some_message,
217
+ )
218
+
219
+ self._stats_mgr = StatsManager()
220
+ self._stats_mgr.register_provider(get_data_cache_stats_provider())
221
+ self._stats_mgr.register_provider(get_resource_cache_stats_provider())
222
+ self._stats_mgr.register_provider(self._message_cache)
223
+ self._stats_mgr.register_provider(self._uploaded_file_mgr)
224
+ self._stats_mgr.register_provider(SessionStateStatProvider(self._session_mgr))
225
+
226
+ @property
227
+ def state(self) -> RuntimeState:
228
+ return self._state
229
+
230
+ @property
231
+ def component_registry(self) -> BaseComponentRegistry:
232
+ return self._component_registry
233
+
234
+ @property
235
+ def message_cache(self) -> ForwardMsgCache:
236
+ return self._message_cache
237
+
238
+ @property
239
+ def uploaded_file_mgr(self) -> UploadedFileManager:
240
+ return self._uploaded_file_mgr
241
+
242
+ @property
243
+ def cache_storage_manager(self) -> CacheStorageManager:
244
+ return self._cache_storage_manager
245
+
246
+ @property
247
+ def media_file_mgr(self) -> MediaFileManager:
248
+ return self._media_file_mgr
249
+
250
+ @property
251
+ def stats_mgr(self) -> StatsManager:
252
+ return self._stats_mgr
253
+
254
+ @property
255
+ def stopped(self) -> Awaitable[None]:
256
+ """A Future that completes when the Runtime's run loop has exited."""
257
+ return self._get_async_objs().stopped
258
+
259
+ # NOTE: A few Runtime methods listed as threadsafe (get_client and
260
+ # is_active_session) currently rely on the implementation detail that
261
+ # WebsocketSessionManager's get_active_session_info and is_active_session methods
262
+ # happen to be threadsafe. This may change with future SessionManager implementations,
263
+ # at which point we'll need to formalize our thread safety rules for each
264
+ # SessionManager method.
265
+ def get_client(self, session_id: str) -> SessionClient | None:
266
+ """Get the SessionClient for the given session_id, or None
267
+ if no such session exists.
268
+
269
+ Notes
270
+ -----
271
+ Threading: SAFE. May be called on any thread.
272
+ """
273
+ session_info = self._session_mgr.get_active_session_info(session_id)
274
+ if session_info is None:
275
+ return None
276
+ return session_info.client
277
+
278
+ def clear_user_info_for_session(self, session_id: str) -> None:
279
+ """Clear the user_info for the given session_id.
280
+
281
+ Notes
282
+ -----
283
+ Threading: SAFE. May be called on any thread.
284
+ """
285
+ session_info = self._session_mgr.get_session_info(session_id)
286
+ if session_info is not None:
287
+ session_info.session.clear_user_info()
288
+
289
+ async def start(self) -> None:
290
+ """Start the runtime. This must be called only once, before
291
+ any other functions are called.
292
+
293
+ When this coroutine returns, Streamlit is ready to accept new sessions.
294
+
295
+ Notes
296
+ -----
297
+ Threading: UNSAFE. Must be called on the eventloop thread.
298
+ """
299
+
300
+ # Create our AsyncObjects. We need to have a running eventloop to
301
+ # instantiate our various synchronization primitives.
302
+ async_objs = AsyncObjects(
303
+ eventloop=asyncio.get_running_loop(),
304
+ must_stop=asyncio.Event(),
305
+ has_connection=asyncio.Event(),
306
+ need_send_data=asyncio.Event(),
307
+ started=asyncio.Future(),
308
+ stopped=asyncio.Future(),
309
+ )
310
+ self._async_objs = async_objs
311
+
312
+ self._loop_coroutine_task = asyncio.create_task(
313
+ self._loop_coroutine(), name="Runtime.loop_coroutine"
314
+ )
315
+
316
+ await async_objs.started
317
+
318
+ def stop(self) -> None:
319
+ """Request that Streamlit close all sessions and stop running.
320
+ Note that Streamlit won't stop running immediately.
321
+
322
+ Notes
323
+ -----
324
+ Threading: SAFE. May be called from any thread.
325
+ """
326
+
327
+ async_objs = self._get_async_objs()
328
+
329
+ def stop_on_eventloop():
330
+ if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
331
+ return
332
+
333
+ _LOGGER.debug("Runtime stopping...")
334
+ self._set_state(RuntimeState.STOPPING)
335
+ async_objs.must_stop.set()
336
+
337
+ async_objs.eventloop.call_soon_threadsafe(stop_on_eventloop)
338
+
339
+ def is_active_session(self, session_id: str) -> bool:
340
+ """True if the session_id belongs to an active session.
341
+
342
+ Notes
343
+ -----
344
+ Threading: SAFE. May be called on any thread.
345
+ """
346
+ return self._session_mgr.is_active_session(session_id)
347
+
348
+ def connect_session(
349
+ self,
350
+ client: SessionClient,
351
+ user_info: dict[str, str | bool | None],
352
+ existing_session_id: str | None = None,
353
+ session_id_override: str | None = None,
354
+ ) -> str:
355
+ """Create a new session (or connect to an existing one) and return its unique ID.
356
+
357
+ Parameters
358
+ ----------
359
+ client
360
+ A concrete SessionClient implementation for communicating with
361
+ the session's client.
362
+ user_info
363
+ A dict that contains information about the session's user. For now,
364
+ it only (optionally) contains the user's email address.
365
+
366
+ {
367
+ "email": "example@example.com"
368
+ }
369
+ existing_session_id
370
+ The ID of an existing session to reconnect to. If one is not provided, a new
371
+ session is created. Note that whether the Runtime's SessionManager supports
372
+ reconnecting to an existing session depends on the SessionManager that this
373
+ runtime is configured with.
374
+ session_id_override
375
+ The ID to assign to a new session being created with this method. Setting
376
+ this can be useful when the service that a Streamlit Runtime is running in
377
+ wants to tie the lifecycle of a Streamlit session to some other session-like
378
+ object that it manages. Only one of existing_session_id and
379
+ session_id_override should be set.
380
+
381
+ Returns
382
+ -------
383
+ str
384
+ The session's unique string ID.
385
+
386
+ Notes
387
+ -----
388
+ Threading: UNSAFE. Must be called on the eventloop thread.
389
+ """
390
+ assert not (existing_session_id and session_id_override), (
391
+ "Only one of existing_session_id and session_id_override should be set!"
392
+ )
393
+
394
+ if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
395
+ raise RuntimeStoppedError(f"Can't connect_session (state={self._state})")
396
+
397
+ session_id = self._session_mgr.connect_session(
398
+ client=client,
399
+ script_data=ScriptData(self._main_script_path, self._is_hello),
400
+ user_info=user_info,
401
+ existing_session_id=existing_session_id,
402
+ session_id_override=session_id_override,
403
+ )
404
+ self._set_state(RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED)
405
+ self._get_async_objs().has_connection.set()
406
+
407
+ return session_id
408
+
409
+ def create_session(
410
+ self,
411
+ client: SessionClient,
412
+ user_info: dict[str, str | bool | None],
413
+ existing_session_id: str | None = None,
414
+ session_id_override: str | None = None,
415
+ ) -> str:
416
+ """Create a new session (or connect to an existing one) and return its unique ID.
417
+
418
+ Notes
419
+ -----
420
+ This method is simply an alias for connect_session added for backwards
421
+ compatibility.
422
+ """
423
+ _LOGGER.warning("create_session is deprecated! Use connect_session instead.")
424
+ return self.connect_session(
425
+ client=client,
426
+ user_info=user_info,
427
+ existing_session_id=existing_session_id,
428
+ session_id_override=session_id_override,
429
+ )
430
+
431
+ def close_session(self, session_id: str) -> None:
432
+ """Close and completely shut down a session.
433
+
434
+ This differs from disconnect_session in that it always completely shuts down a
435
+ session, permanently losing any associated state (session state, uploaded files,
436
+ etc.).
437
+
438
+ This function may be called multiple times for the same session,
439
+ which is not an error. (Subsequent calls just no-op.)
440
+
441
+ Parameters
442
+ ----------
443
+ session_id
444
+ The session's unique ID.
445
+
446
+ Notes
447
+ -----
448
+ Threading: UNSAFE. Must be called on the eventloop thread.
449
+ """
450
+ session_info = self._session_mgr.get_session_info(session_id)
451
+ if session_info:
452
+ self._message_cache.remove_refs_for_session(session_info.session)
453
+ self._session_mgr.close_session(session_id)
454
+ self._on_session_disconnected()
455
+
456
+ def disconnect_session(self, session_id: str) -> None:
457
+ """Disconnect a session. It will stop producing ForwardMsgs.
458
+
459
+ Differs from close_session because disconnected sessions can be reconnected to
460
+ for a brief window (depending on the SessionManager/SessionStorage
461
+ implementations used by the runtime).
462
+
463
+ This function may be called multiple times for the same session,
464
+ which is not an error. (Subsequent calls just no-op.)
465
+
466
+ Parameters
467
+ ----------
468
+ session_id
469
+ The session's unique ID.
470
+
471
+ Notes
472
+ -----
473
+ Threading: UNSAFE. Must be called on the eventloop thread.
474
+ """
475
+ session_info = self._session_mgr.get_active_session_info(session_id)
476
+ if session_info:
477
+ # NOTE: Ideally, we'd like to keep ForwardMsgCache refs for a session around
478
+ # when a session is disconnected (and defer their cleanup until the session
479
+ # is garbage collected), but this would be difficult to do as the
480
+ # ForwardMsgCache is not thread safe, and we have no guarantee that the
481
+ # garbage collector will only run on the eventloop thread. Because of this,
482
+ # we clean up refs now and accept the risk that we're deleting cache entries
483
+ # that will be useful once the browser tab reconnects.
484
+ self._message_cache.remove_refs_for_session(session_info.session)
485
+ self._session_mgr.disconnect_session(session_id)
486
+ self._on_session_disconnected()
487
+
488
+ def handle_backmsg(self, session_id: str, msg: BackMsg) -> None:
489
+ """Send a BackMsg to an active session.
490
+
491
+ Parameters
492
+ ----------
493
+ session_id
494
+ The session's unique ID.
495
+ msg
496
+ The BackMsg to deliver to the session.
497
+
498
+ Notes
499
+ -----
500
+ Threading: UNSAFE. Must be called on the eventloop thread.
501
+ """
502
+ if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
503
+ raise RuntimeStoppedError(f"Can't handle_backmsg (state={self._state})")
504
+
505
+ session_info = self._session_mgr.get_active_session_info(session_id)
506
+ if session_info is None:
507
+ _LOGGER.debug(
508
+ "Discarding BackMsg for disconnected session (id=%s)", session_id
509
+ )
510
+ return
511
+
512
+ session_info.session.handle_backmsg(msg)
513
+
514
+ def handle_backmsg_deserialization_exception(
515
+ self, session_id: str, exc: BaseException
516
+ ) -> None:
517
+ """Handle an Exception raised during deserialization of a BackMsg.
518
+
519
+ Parameters
520
+ ----------
521
+ session_id
522
+ The session's unique ID.
523
+ exc
524
+ The Exception.
525
+
526
+ Notes
527
+ -----
528
+ Threading: UNSAFE. Must be called on the eventloop thread.
529
+ """
530
+ if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
531
+ raise RuntimeStoppedError(
532
+ f"Can't handle_backmsg_deserialization_exception (state={self._state})"
533
+ )
534
+
535
+ session_info = self._session_mgr.get_active_session_info(session_id)
536
+ if session_info is None:
537
+ _LOGGER.debug(
538
+ "Discarding BackMsg Exception for disconnected session (id=%s)",
539
+ session_id,
540
+ )
541
+ return
542
+
543
+ session_info.session.handle_backmsg_exception(exc)
544
+
545
+ @property
546
+ async def is_ready_for_browser_connection(self) -> tuple[bool, str]:
547
+ if self._state not in (
548
+ RuntimeState.INITIAL,
549
+ RuntimeState.STOPPING,
550
+ RuntimeState.STOPPED,
551
+ ):
552
+ return True, "ok"
553
+
554
+ return False, "unavailable"
555
+
556
+ async def does_script_run_without_error(self) -> tuple[bool, str]:
557
+ """Load and execute the app's script to verify it runs without an error.
558
+
559
+ Returns
560
+ -------
561
+ (True, "ok") if the script completes without error, or (False, err_msg)
562
+ if the script raises an exception.
563
+
564
+ Notes
565
+ -----
566
+ Threading: UNSAFE. Must be called on the eventloop thread.
567
+ """
568
+ # NOTE: We create an AppSession directly here instead of using the
569
+ # SessionManager intentionally. This isn't a "real" session and is only being
570
+ # used to test that the script runs without error.
571
+ session = AppSession(
572
+ script_data=ScriptData(self._main_script_path, self._is_hello),
573
+ uploaded_file_manager=self._uploaded_file_mgr,
574
+ script_cache=self._script_cache,
575
+ message_enqueued_callback=self._enqueued_some_message,
576
+ user_info={"email": "test@example.com"},
577
+ )
578
+
579
+ try:
580
+ session.request_rerun(None)
581
+
582
+ now = time.perf_counter()
583
+ while ( # noqa: ASYNC110
584
+ SCRIPT_RUN_WITHOUT_ERRORS_KEY not in session.session_state
585
+ and (time.perf_counter() - now) < SCRIPT_RUN_CHECK_TIMEOUT
586
+ ):
587
+ await asyncio.sleep(0.1)
588
+
589
+ if SCRIPT_RUN_WITHOUT_ERRORS_KEY not in session.session_state:
590
+ return False, "timeout"
591
+
592
+ ok = session.session_state[SCRIPT_RUN_WITHOUT_ERRORS_KEY]
593
+ msg = "ok" if ok else "error"
594
+
595
+ return ok, msg
596
+ finally:
597
+ session.shutdown()
598
+
599
+ def _set_state(self, new_state: RuntimeState) -> None:
600
+ _LOGGER.debug("Runtime state: %s -> %s", self._state, new_state)
601
+ self._state = new_state
602
+
603
+ async def _loop_coroutine(self) -> None:
604
+ """The main Runtime loop.
605
+
606
+ This function won't exit until `stop` is called.
607
+
608
+ Notes
609
+ -----
610
+ Threading: UNSAFE. Must be called on the eventloop thread.
611
+ """
612
+
613
+ async_objs = self._get_async_objs()
614
+
615
+ try:
616
+ if self._state == RuntimeState.INITIAL:
617
+ self._set_state(RuntimeState.NO_SESSIONS_CONNECTED)
618
+ elif self._state == RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED:
619
+ pass
620
+ else:
621
+ raise RuntimeError(f"Bad Runtime state at start: {self._state}")
622
+
623
+ # Signal that we're started and ready to accept sessions
624
+ async_objs.started.set_result(None)
625
+
626
+ while not async_objs.must_stop.is_set():
627
+ if self._state == RuntimeState.NO_SESSIONS_CONNECTED: # type: ignore[comparison-overlap]
628
+ # mypy 1.4 incorrectly thinks this if-clause is unreachable,
629
+ # because it thinks self._state must be INITIAL | ONE_OR_MORE_SESSIONS_CONNECTED.
630
+
631
+ # Wait for new websocket connections (new sessions):
632
+ _, pending_tasks = await asyncio.wait( # type: ignore[unreachable]
633
+ (
634
+ asyncio.create_task(async_objs.must_stop.wait()),
635
+ asyncio.create_task(async_objs.has_connection.wait()),
636
+ ),
637
+ return_when=asyncio.FIRST_COMPLETED,
638
+ )
639
+ # Clean up pending tasks to avoid memory leaks
640
+ for task in pending_tasks:
641
+ task.cancel()
642
+ elif self._state == RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED:
643
+ async_objs.need_send_data.clear()
644
+
645
+ for active_session_info in self._session_mgr.list_active_sessions():
646
+ msg_list = active_session_info.session.flush_browser_queue()
647
+ for msg in msg_list:
648
+ try:
649
+ self._send_message(active_session_info, msg)
650
+ except SessionClientDisconnectedError:
651
+ self._session_mgr.disconnect_session(
652
+ active_session_info.session.id
653
+ )
654
+
655
+ # Yield for a tick after sending a message.
656
+ await asyncio.sleep(0)
657
+
658
+ # Yield for a few milliseconds between session message
659
+ # flushing.
660
+ await asyncio.sleep(0.01)
661
+ else:
662
+ # Break out of the thread loop if we encounter any other state.
663
+ break
664
+
665
+ # Wait for new proto messages that need to be sent out:
666
+ _, pending_tasks = await asyncio.wait(
667
+ (
668
+ asyncio.create_task(async_objs.must_stop.wait()),
669
+ asyncio.create_task(async_objs.need_send_data.wait()),
670
+ ),
671
+ return_when=asyncio.FIRST_COMPLETED,
672
+ )
673
+ # We need to cancel the pending tasks (the `must_stop` one in most situations).
674
+ # Otherwise, this would stack up one waiting task per loop
675
+ # (e.g. per forward message). These tasks cannot be garbage collected
676
+ # causing an increase in memory (-> memory leak).
677
+ for task in pending_tasks:
678
+ task.cancel()
679
+
680
+ # Shut down all AppSessions.
681
+ for session_info in self._session_mgr.list_sessions():
682
+ # NOTE: We want to fully shut down sessions when the runtime stops for
683
+ # now, but this may change in the future if/when our notion of a session
684
+ # is no longer so tightly coupled to a browser tab.
685
+ self._session_mgr.close_session(session_info.session.id)
686
+
687
+ self._set_state(RuntimeState.STOPPED)
688
+ async_objs.stopped.set_result(None)
689
+
690
+ except Exception as e:
691
+ async_objs.stopped.set_exception(e)
692
+ traceback.print_exc()
693
+ _LOGGER.info(
694
+ """
695
+ Please report this bug at https://github.com/streamlit/streamlit/issues.
696
+ """
697
+ )
698
+
699
+ def _send_message(self, session_info: ActiveSessionInfo, msg: ForwardMsg) -> None:
700
+ """Send a message to a client.
701
+
702
+ If the client is likely to have already cached the message, we may
703
+ instead send a "reference" message that contains only the hash of the
704
+ message.
705
+
706
+ Parameters
707
+ ----------
708
+ session_info : ActiveSessionInfo
709
+ The ActiveSessionInfo associated with websocket
710
+ msg : ForwardMsg
711
+ The message to send to the client
712
+
713
+ Notes
714
+ -----
715
+ Threading: UNSAFE. Must be called on the eventloop thread.
716
+ """
717
+ msg.metadata.cacheable = is_cacheable_msg(msg)
718
+ msg_to_send = msg
719
+ if msg.metadata.cacheable:
720
+ populate_hash_if_needed(msg)
721
+
722
+ if self._message_cache.has_message_reference(
723
+ msg, session_info.session, session_info.script_run_count
724
+ ):
725
+ # This session has probably cached this message. Send
726
+ # a reference instead.
727
+ _LOGGER.debug("Sending cached message ref (hash=%s)", msg.hash)
728
+ msg_to_send = create_reference_msg(msg)
729
+
730
+ # Cache the message so it can be referenced in the future.
731
+ # If the message is already cached, this will reset its
732
+ # age.
733
+ _LOGGER.debug("Caching message (hash=%s)", msg.hash)
734
+ self._message_cache.add_message(
735
+ msg, session_info.session, session_info.script_run_count
736
+ )
737
+
738
+ # If this was a `script_finished` message, we increment the
739
+ # script_run_count for this session, and update the cache
740
+ if msg.WhichOneof("type") == "script_finished" and (
741
+ msg.script_finished == ForwardMsg.FINISHED_SUCCESSFULLY
742
+ or (
743
+ config.get_option(
744
+ "global.includeFragmentRunsInForwardMessageCacheCount"
745
+ )
746
+ and msg.script_finished == ForwardMsg.FINISHED_FRAGMENT_RUN_SUCCESSFULLY
747
+ )
748
+ ):
749
+ _LOGGER.debug(
750
+ "Script run finished successfully; "
751
+ "removing expired entries from MessageCache "
752
+ "(max_age=%s)",
753
+ config.get_option("global.maxCachedMessageAge"),
754
+ )
755
+ session_info.script_run_count += 1
756
+ self._message_cache.remove_expired_entries_for_session(
757
+ session_info.session, session_info.script_run_count
758
+ )
759
+
760
+ # Ship it off!
761
+ session_info.client.write_forward_msg(msg_to_send)
762
+
763
+ def _enqueued_some_message(self) -> None:
764
+ """Callback called by AppSession after the AppSession has enqueued a
765
+ message. Sets the "needs_send_data" event, which causes our core
766
+ loop to wake up and flush client message queues.
767
+
768
+ Notes
769
+ -----
770
+ Threading: SAFE. May be called on any thread.
771
+ """
772
+ async_objs = self._get_async_objs()
773
+ async_objs.eventloop.call_soon_threadsafe(async_objs.need_send_data.set)
774
+
775
+ def _get_async_objs(self) -> AsyncObjects:
776
+ """Return our AsyncObjects instance. If the Runtime hasn't been
777
+ started, this will raise an error.
778
+ """
779
+ if self._async_objs is None:
780
+ raise RuntimeError("Runtime hasn't started yet!")
781
+ return self._async_objs
782
+
783
+ def _on_session_disconnected(self) -> None:
784
+ """Set the runtime state to NO_SESSIONS_CONNECTED if the last active
785
+ session was disconnected.
786
+ """
787
+ if (
788
+ self._state == RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED
789
+ and self._session_mgr.num_active_sessions() == 0
790
+ ):
791
+ self._get_async_objs().has_connection.clear()
792
+ self._set_state(RuntimeState.NO_SESSIONS_CONNECTED)