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,213 @@
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
+ # NOTE: We won't always be able to import from snowflake.snowpark.session so need the
16
+ # `type: ignore` comment below, but that comment will explode if `warn-unused-ignores` is
17
+ # turned on when the package is available. Unfortunately, mypy doesn't provide a good
18
+ # way to configure this at a per-line level :(
19
+ # mypy: no-warn-unused-ignores
20
+
21
+ from __future__ import annotations
22
+
23
+ import threading
24
+ from collections import ChainMap
25
+ from contextlib import contextmanager
26
+ from typing import TYPE_CHECKING, cast
27
+
28
+ from streamlit.connections import BaseConnection
29
+ from streamlit.connections.util import (
30
+ SNOWSQL_CONNECTION_FILE,
31
+ load_from_snowsql_config_file,
32
+ running_in_sis,
33
+ )
34
+ from streamlit.errors import StreamlitAPIException
35
+ from streamlit.runtime.caching import cache_data
36
+
37
+ if TYPE_CHECKING:
38
+ from collections.abc import Iterator
39
+ from datetime import timedelta
40
+
41
+ from pandas import DataFrame
42
+ from snowflake.snowpark.session import Session # type:ignore[import]
43
+
44
+
45
+ _REQUIRED_CONNECTION_PARAMS = {"account"}
46
+
47
+
48
+ class SnowparkConnection(BaseConnection["Session"]):
49
+ """A connection to Snowpark using snowflake.snowpark.session.Session. Initialize using
50
+ ``st.connection("<name>", type="snowpark")``.
51
+
52
+ In addition to providing access to the Snowpark Session, SnowparkConnection supports
53
+ direct SQL querying using ``query("...")`` and thread safe access using
54
+ ``with conn.safe_session():``. See methods below for more information.
55
+ SnowparkConnections should always be created using ``st.connection()``, **not**
56
+ initialized directly.
57
+
58
+ .. note::
59
+ We don't expect this iteration of SnowparkConnection to be able to scale
60
+ well in apps with many concurrent users due to the lock contention that will occur
61
+ over the single underlying Session object under high load.
62
+ """
63
+
64
+ def __init__(self, connection_name: str, **kwargs) -> None:
65
+ self._lock = threading.RLock()
66
+ super().__init__(connection_name, **kwargs)
67
+
68
+ def _connect(self, **kwargs) -> Session:
69
+ from snowflake.snowpark.context import get_active_session # type:ignore[import]
70
+ from snowflake.snowpark.session import Session
71
+
72
+ # If we're running in SiS, just call get_active_session(). Otherwise, attempt to
73
+ # create a new session from whatever credentials we have available.
74
+ if running_in_sis():
75
+ return get_active_session()
76
+
77
+ conn_params = ChainMap(
78
+ kwargs,
79
+ self._secrets.to_dict(),
80
+ load_from_snowsql_config_file(self._connection_name),
81
+ )
82
+
83
+ if not len(conn_params):
84
+ raise StreamlitAPIException(
85
+ "Missing Snowpark connection configuration. "
86
+ f"Did you forget to set this in `secrets.toml`, `{SNOWSQL_CONNECTION_FILE}`, "
87
+ "or as kwargs to `st.connection`?"
88
+ )
89
+
90
+ for p in _REQUIRED_CONNECTION_PARAMS:
91
+ if p not in conn_params:
92
+ raise StreamlitAPIException(f"Missing Snowpark connection param: {p}")
93
+
94
+ return cast(Session, Session.builder.configs(conn_params).create())
95
+
96
+ def query(
97
+ self,
98
+ sql: str,
99
+ ttl: float | int | timedelta | None = None,
100
+ ) -> DataFrame:
101
+ """Run a read-only SQL query.
102
+
103
+ This method implements both query result caching (with caching behavior
104
+ identical to that of using ``@st.cache_data``) as well as simple error handling/retries.
105
+
106
+ .. note::
107
+ Queries that are run without a specified ttl are cached indefinitely.
108
+
109
+ Parameters
110
+ ----------
111
+ sql : str
112
+ The read-only SQL query to execute.
113
+ ttl : float, int, timedelta or None
114
+ The maximum number of seconds to keep results in the cache, or
115
+ None if cached results should not expire. The default is None.
116
+
117
+ Returns
118
+ -------
119
+ pandas.DataFrame
120
+ The result of running the query, formatted as a pandas DataFrame.
121
+
122
+ Example
123
+ -------
124
+ >>> import streamlit as st
125
+ >>>
126
+ >>> conn = st.connection("snowpark")
127
+ >>> df = conn.query("SELECT * FROM pet_owners")
128
+ >>> st.dataframe(df)
129
+ """
130
+ from snowflake.snowpark.exceptions import ( # type:ignore[import]
131
+ SnowparkServerException,
132
+ )
133
+ from tenacity import (
134
+ retry,
135
+ retry_if_exception_type,
136
+ stop_after_attempt,
137
+ wait_fixed,
138
+ )
139
+
140
+ @retry(
141
+ after=lambda _: self.reset(),
142
+ stop=stop_after_attempt(3),
143
+ reraise=True,
144
+ retry=retry_if_exception_type(SnowparkServerException),
145
+ wait=wait_fixed(1),
146
+ )
147
+ def _query(sql: str) -> DataFrame:
148
+ with self._lock:
149
+ return self._instance.sql(sql).to_pandas()
150
+
151
+ # We modify our helper function's `__qualname__` here to work around default
152
+ # `@st.cache_data` behavior. Otherwise, `.query()` being called with different
153
+ # `ttl` values will reset the cache with each call, and the query caches won't
154
+ # be scoped by connection.
155
+ ttl_str = str( # Avoid adding extra `.` characters to `__qualname__`
156
+ ttl
157
+ ).replace(".", "_")
158
+ _query.__qualname__ = f"{_query.__qualname__}_{self._connection_name}_{ttl_str}"
159
+ _query = cache_data(
160
+ show_spinner="Running `snowpark.query(...)`.",
161
+ ttl=ttl,
162
+ )(_query)
163
+
164
+ return _query(sql)
165
+
166
+ @property
167
+ def session(self) -> Session:
168
+ """Access the underlying Snowpark session.
169
+
170
+ .. note::
171
+ Snowpark sessions are **not** thread safe. Users of this method are
172
+ responsible for ensuring that access to the session returned by this method is
173
+ done in a thread-safe manner. For most users, we recommend using the thread-safe
174
+ safe_session() method and a ``with`` block.
175
+
176
+ Information on how to use Snowpark sessions can be found in the `Snowpark documentation
177
+ <https://docs.snowflake.com/en/developer-guide/snowpark/python/working-with-dataframes>`_.
178
+
179
+ Example
180
+ -------
181
+ >>> import streamlit as st
182
+ >>>
183
+ >>> session = st.connection("snowpark").session
184
+ >>> df = session.table("mytable").limit(10).to_pandas()
185
+ >>> st.dataframe(df)
186
+ """
187
+ return self._instance
188
+
189
+ @contextmanager
190
+ def safe_session(self) -> Iterator[Session]:
191
+ """Grab the underlying Snowpark session in a thread-safe manner.
192
+
193
+ As operations on a Snowpark session are not thread safe, we need to take care
194
+ when using a session in the context of a Streamlit app where each script run
195
+ occurs in its own thread. Using the contextmanager pattern to do this ensures
196
+ that access on this connection's underlying Session is done in a thread-safe
197
+ manner.
198
+
199
+ Information on how to use Snowpark sessions can be found in the `Snowpark documentation
200
+ <https://docs.snowflake.com/en/developer-guide/snowpark/python/working-with-dataframes>`_.
201
+
202
+ Example
203
+ -------
204
+ >>> import streamlit as st
205
+ >>>
206
+ >>> conn = st.connection("snowpark")
207
+ >>> with conn.safe_session() as session:
208
+ ... df = session.table("mytable").limit(10).to_pandas()
209
+ >>>
210
+ >>> st.dataframe(df)
211
+ """
212
+ with self._lock:
213
+ yield self.session
@@ -0,0 +1,425 @@
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
+ # NOTE: We ignore all mypy import-not-found errors as top-level since
16
+ # this module is optional and the SQLAlchemy dependency is not installed
17
+ # by default.
18
+ # mypy: disable-error-code="import-not-found, redundant-cast"
19
+
20
+ from __future__ import annotations
21
+
22
+ from collections import ChainMap
23
+ from copy import deepcopy
24
+ from typing import TYPE_CHECKING, cast
25
+
26
+ from streamlit.connections import BaseConnection
27
+ from streamlit.connections.util import extract_from_dict
28
+ from streamlit.errors import StreamlitAPIException
29
+ from streamlit.runtime.caching import cache_data
30
+
31
+ if TYPE_CHECKING:
32
+ from datetime import timedelta
33
+
34
+ from pandas import DataFrame
35
+ from sqlalchemy.engine import Connection as SQLAlchemyConnection
36
+ from sqlalchemy.engine.base import Engine
37
+ from sqlalchemy.orm import Session
38
+
39
+
40
+ _ALL_CONNECTION_PARAMS = {
41
+ "url",
42
+ "driver",
43
+ "dialect",
44
+ "username",
45
+ "password",
46
+ "host",
47
+ "port",
48
+ "database",
49
+ "query",
50
+ }
51
+ _REQUIRED_CONNECTION_PARAMS = {"dialect", "username", "host"}
52
+
53
+
54
+ class SQLConnection(BaseConnection["Engine"]):
55
+ """A connection to a SQL database using a SQLAlchemy Engine.
56
+
57
+ Initialize this connection object using ``st.connection("sql")`` or
58
+ ``st.connection("<name>", type="sql")``. Connection parameters for a
59
+ SQLConnection can be specified using ``secrets.toml`` and/or ``**kwargs``.
60
+ Possible connection parameters include:
61
+
62
+ - ``url`` or keyword arguments for |sqlalchemy.engine.URL.create()|_, except
63
+ ``drivername``. Use ``dialect`` and ``driver`` instead of ``drivername``.
64
+ - Keyword arguments for |sqlalchemy.create_engine()|_, including custom
65
+ ``connect()`` arguments used by your specific ``dialect`` or ``driver``.
66
+ - ``autocommit``. If this is ``False`` (default), the connection operates
67
+ in manual commit (transactional) mode. If this is ``True``, the
68
+ connection operates in autocommit (non-transactional) mode.
69
+
70
+ If ``url`` exists as a connection parameter, Streamlit will pass it to
71
+ ``sqlalchemy.engine.make_url()``. Otherwise, Streamlit requires (at a
72
+ minimum) ``dialect``, ``username``, and ``host``. Streamlit will use
73
+ ``dialect`` and ``driver`` (if defined) to derive ``drivername``, then pass
74
+ the relevant connection parameters to ``sqlalchemy.engine.URL.create()``.
75
+
76
+ In addition to the default keyword arguments for ``sqlalchemy.create_engine()``,
77
+ your dialect may accept additional keyword arguments. For example, if you
78
+ use ``dialect="snowflake"`` with `Snowflake SQLAlchemy
79
+ <https://github.com/snowflakedb/snowflake-sqlalchemy#key-pair-authentication-support>`_,
80
+ you can pass a value for ``private_key`` to use key-pair authentication. If
81
+ you use ``dialect="bigquery"`` with `Google BigQuery
82
+ <https://github.com/googleapis/python-bigquery-sqlalchemy#authentication>`_,
83
+ you can pass a value for ``location``.
84
+
85
+ SQLConnection provides the ``.query()`` convenience method, which can be
86
+ used to run simple, read-only queries with both caching and simple error
87
+ handling/retries. More complex database interactions can be performed by
88
+ using the ``.session`` property to receive a regular SQLAlchemy Session.
89
+
90
+ .. Important::
91
+ `SQLAlchemy <https://pypi.org/project/SQLAlchemy/>`_ must be installed
92
+ in your environment to use this connection. You must also install your
93
+ driver, such as ``pyodbc`` or ``psycopg2``.
94
+
95
+ .. |sqlalchemy.engine.URL.create()| replace:: ``sqlalchemy.engine.URL.create()``
96
+ .. _sqlalchemy.engine.URL.create(): https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.engine.URL.create
97
+ .. |sqlalchemy.engine.make_url()| replace:: ``sqlalchemy.engine.make_url()``
98
+ .. _sqlalchemy.engine.make_url(): https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.engine.make_url
99
+ .. |sqlalchemy.create_engine()| replace:: ``sqlalchemy.create_engine()``
100
+ .. _sqlalchemy.create_engine(): https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.create_engine
101
+
102
+ Examples
103
+ --------
104
+
105
+ **Example 1: Configuration with URL**
106
+
107
+ You can configure your SQL connection using Streamlit's
108
+ `Secrets management <https://docs.streamlit.io/develop/concepts/connections/secrets-management>`_.
109
+ The following example specifies a SQL connection URL.
110
+
111
+ ``.streamlit/secrets.toml``:
112
+
113
+ >>> [connections.sql]
114
+ >>> url = "xxx+xxx://xxx:xxx@xxx:xxx/xxx"
115
+
116
+ Your app code:
117
+
118
+ >>> import streamlit as st
119
+ >>>
120
+ >>> conn = st.connection("sql")
121
+ >>> df = conn.query("SELECT * FROM pet_owners")
122
+ >>> st.dataframe(df)
123
+
124
+ **Example 2: Configuration with dialect, host, and username**
125
+
126
+ If you do not specify ``url``, you must at least specify ``dialect``,
127
+ ``host``, and ``username`` instead. The following example also includes
128
+ ``password``.
129
+
130
+ ``.streamlit/secrets.toml``:
131
+
132
+ >>> [connections.sql]
133
+ >>> dialect = "xxx"
134
+ >>> host = "xxx"
135
+ >>> username = "xxx"
136
+ >>> password = "xxx"
137
+
138
+ Your app code:
139
+
140
+ >>> import streamlit as st
141
+ >>>
142
+ >>> conn = st.connection("sql")
143
+ >>> df = conn.query("SELECT * FROM pet_owners")
144
+ >>> st.dataframe(df)
145
+
146
+ **Example 3: Configuration with keyword arguments**
147
+
148
+ You can configure your SQL connection with keyword arguments (with or
149
+ without ``secrets.toml``). For example, if you use Microsoft Entra ID with
150
+ a Microsoft Azure SQL server, you can quickly set up a local connection for
151
+ development using `interactive authentication
152
+ <https://learn.microsoft.com/en-us/sql/connect/odbc/using-azure-active-directory?view=sql-server-ver16#new-andor-modified-dsn-and-connection-string-keywords>`_.
153
+
154
+ This example requires the `Microsoft ODBC Driver for SQL Server
155
+ <https://learn.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server?view=sql-server-ver16>`_
156
+ for *Windows* in addition to the ``sqlalchemy`` and ``pyodbc`` packages for
157
+ Python.
158
+
159
+ >>> import streamlit as st
160
+ >>>
161
+ >>> conn = st.connection(
162
+ ... "sql",
163
+ ... dialect="mssql",
164
+ ... driver="pyodbc",
165
+ ... host="xxx.database.windows.net",
166
+ ... database="xxx",
167
+ ... username="xxx",
168
+ ... query={
169
+ ... "driver": "ODBC Driver 18 for SQL Server",
170
+ ... "authentication": "ActiveDirectoryInteractive",
171
+ ... "encrypt": "yes",
172
+ ... },
173
+ ... )
174
+ >>>
175
+ >>> df = conn.query("SELECT * FROM pet_owners")
176
+ >>> st.dataframe(df)
177
+
178
+ """
179
+
180
+ def _connect(self, autocommit: bool = False, **kwargs) -> Engine:
181
+ import sqlalchemy
182
+
183
+ kwargs = deepcopy(kwargs)
184
+ conn_param_kwargs = extract_from_dict(_ALL_CONNECTION_PARAMS, kwargs)
185
+ conn_params = ChainMap(conn_param_kwargs, self._secrets.to_dict())
186
+
187
+ if not len(conn_params):
188
+ raise StreamlitAPIException(
189
+ "Missing SQL DB connection configuration. "
190
+ "Did you forget to set this in `secrets.toml` or as kwargs to `st.connection`?"
191
+ )
192
+
193
+ if "url" in conn_params:
194
+ url = sqlalchemy.engine.make_url(conn_params["url"])
195
+ else:
196
+ for p in _REQUIRED_CONNECTION_PARAMS:
197
+ if p not in conn_params:
198
+ raise StreamlitAPIException(f"Missing SQL DB connection param: {p}")
199
+
200
+ drivername = conn_params["dialect"] + (
201
+ f"+{conn_params['driver']}" if "driver" in conn_params else ""
202
+ )
203
+
204
+ url = sqlalchemy.engine.URL.create(
205
+ drivername=drivername,
206
+ username=conn_params["username"],
207
+ password=conn_params.get("password"),
208
+ host=conn_params["host"],
209
+ port=int(conn_params["port"]) if "port" in conn_params else None,
210
+ database=conn_params.get("database"),
211
+ query=conn_params["query"] if "query" in conn_params else None,
212
+ )
213
+
214
+ create_engine_kwargs = ChainMap(
215
+ kwargs, self._secrets.get("create_engine_kwargs", {})
216
+ )
217
+ eng = sqlalchemy.create_engine(url, **create_engine_kwargs)
218
+
219
+ if autocommit:
220
+ return cast("Engine", eng.execution_options(isolation_level="AUTOCOMMIT"))
221
+ else:
222
+ return cast("Engine", eng)
223
+
224
+ def query(
225
+ self,
226
+ sql: str,
227
+ *, # keyword-only arguments:
228
+ show_spinner: bool | str = "Running `sql.query(...)`.",
229
+ ttl: float | int | timedelta | None = None,
230
+ index_col: str | list[str] | None = None,
231
+ chunksize: int | None = None,
232
+ params=None,
233
+ **kwargs,
234
+ ) -> DataFrame:
235
+ """Run a read-only query.
236
+
237
+ This method implements query result caching and simple error
238
+ handling/retries. The caching behavior is identical to that of using
239
+ ``@st.cache_data``.
240
+
241
+ .. note::
242
+ Queries that are run without a specified ttl are cached indefinitely.
243
+
244
+ All keyword arguments passed to this function are passed down to
245
+ |pandas.read_sql|_, except ``ttl``.
246
+
247
+ .. |pandas.read_sql| replace:: ``pandas.read_sql``
248
+ .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
249
+
250
+ Parameters
251
+ ----------
252
+ sql : str
253
+ The read-only SQL query to execute.
254
+ show_spinner : boolean or string
255
+ Enable the spinner. The default is to show a spinner when there is a
256
+ "cache miss" and the cached resource is being created. If a string, the value
257
+ of the show_spinner param will be used for the spinner text.
258
+ ttl : float, int, timedelta or None
259
+ The maximum number of seconds to keep results in the cache, or
260
+ None if cached results should not expire. The default is None.
261
+ index_col : str, list of str, or None
262
+ Column(s) to set as index(MultiIndex). Default is None.
263
+ chunksize : int or None
264
+ If specified, return an iterator where chunksize is the number of
265
+ rows to include in each chunk. Default is None.
266
+ params : list, tuple, dict or None
267
+ List of parameters to pass to the execute method. The syntax used to pass
268
+ parameters is database driver dependent. Check your database driver
269
+ documentation for which of the five syntax styles, described in `PEP 249
270
+ paramstyle <https://peps.python.org/pep-0249/#paramstyle>`_, is supported.
271
+ Default is None.
272
+ **kwargs: dict
273
+ Additional keyword arguments are passed to |pandas.read_sql|_.
274
+
275
+ .. |pandas.read_sql| replace:: ``pandas.read_sql``
276
+ .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
277
+
278
+ Returns
279
+ -------
280
+ pandas.DataFrame
281
+ The result of running the query, formatted as a pandas DataFrame.
282
+
283
+ Example
284
+ -------
285
+ >>> import streamlit as st
286
+ >>>
287
+ >>> conn = st.connection("sql")
288
+ >>> df = conn.query(
289
+ ... "SELECT * FROM pet_owners WHERE owner = :owner",
290
+ ... ttl=3600,
291
+ ... params={"owner": "barbara"},
292
+ ... )
293
+ >>> st.dataframe(df)
294
+ """
295
+
296
+ from sqlalchemy import text
297
+ from sqlalchemy.exc import DatabaseError, InternalError, OperationalError
298
+ from tenacity import (
299
+ retry,
300
+ retry_if_exception_type,
301
+ stop_after_attempt,
302
+ wait_fixed,
303
+ )
304
+
305
+ @retry(
306
+ after=lambda _: self.reset(),
307
+ stop=stop_after_attempt(3),
308
+ reraise=True,
309
+ retry=retry_if_exception_type(
310
+ (DatabaseError, InternalError, OperationalError)
311
+ ),
312
+ wait=wait_fixed(1),
313
+ )
314
+ def _query(
315
+ sql: str,
316
+ index_col=None,
317
+ chunksize=None,
318
+ params=None,
319
+ **kwargs,
320
+ ) -> DataFrame:
321
+ import pandas as pd
322
+
323
+ instance = self._instance.connect()
324
+ return pd.read_sql(
325
+ text(sql),
326
+ instance,
327
+ index_col=index_col,
328
+ chunksize=chunksize,
329
+ params=params,
330
+ **kwargs,
331
+ )
332
+
333
+ # We modify our helper function's `__qualname__` here to work around default
334
+ # `@st.cache_data` behavior. Otherwise, `.query()` being called with different
335
+ # `ttl` values will reset the cache with each call, and the query caches won't
336
+ # be scoped by connection.
337
+ ttl_str = str( # Avoid adding extra `.` characters to `__qualname__`
338
+ ttl
339
+ ).replace(".", "_")
340
+ _query.__qualname__ = f"{_query.__qualname__}_{self._connection_name}_{ttl_str}"
341
+ _query = cache_data(
342
+ show_spinner=show_spinner,
343
+ ttl=ttl,
344
+ )(_query)
345
+
346
+ return _query(
347
+ sql,
348
+ index_col=index_col,
349
+ chunksize=chunksize,
350
+ params=params,
351
+ **kwargs,
352
+ )
353
+
354
+ def connect(self) -> SQLAlchemyConnection:
355
+ """Call ``.connect()`` on the underlying SQLAlchemy Engine, returning a new\
356
+ connection object.
357
+
358
+ Calling this method is equivalent to calling ``self._instance.connect()``.
359
+
360
+ NOTE: This method should not be confused with the internal ``_connect`` method used
361
+ to implement a Streamlit Connection.
362
+
363
+ Returns
364
+ -------
365
+ sqlalchemy.engine.Connection
366
+ A new SQLAlchemy connection object.
367
+ """
368
+ return self._instance.connect()
369
+
370
+ @property
371
+ def engine(self) -> Engine:
372
+ """The underlying SQLAlchemy Engine.
373
+
374
+ This is equivalent to accessing ``self._instance``.
375
+
376
+ Returns
377
+ -------
378
+ sqlalchemy.engine.base.Engine
379
+ The underlying SQLAlchemy Engine.
380
+ """
381
+ return self._instance
382
+
383
+ @property
384
+ def driver(self) -> str:
385
+ """The name of the driver used by the underlying SQLAlchemy Engine.
386
+
387
+ This is equivalent to accessing ``self._instance.driver``.
388
+
389
+ Returns
390
+ -------
391
+ str
392
+ The name of the driver. For example, ``"pyodbc"`` or ``"psycopg2"``.
393
+ """
394
+ return cast(str, self._instance.driver)
395
+
396
+ @property
397
+ def session(self) -> Session:
398
+ """Return a SQLAlchemy Session.
399
+
400
+ Users of this connection should use the contextmanager pattern for writes,
401
+ transactions, and anything more complex than simple read queries.
402
+
403
+ See the usage example below, which assumes we have a table ``numbers`` with a
404
+ single integer column ``val``. The `SQLAlchemy
405
+ <https://docs.sqlalchemy.org/en/20/orm/session_basics.html>`_ docs also contain
406
+ much more information on the usage of sessions.
407
+
408
+ Returns
409
+ -------
410
+ sqlalchemy.orm.Session
411
+ A SQLAlchemy Session.
412
+
413
+ Example
414
+ -------
415
+ >>> import streamlit as st
416
+ >>> conn = st.connection("sql")
417
+ >>> n = st.slider("Pick a number")
418
+ >>> if st.button("Add the number!"):
419
+ ... with conn.session as session:
420
+ ... session.execute("INSERT INTO numbers (val) VALUES (:n);", {"n": n})
421
+ ... session.commit()
422
+ """
423
+ from sqlalchemy.orm import Session
424
+
425
+ return Session(self._instance)