streamlit 1.50.0__py3-none-any.whl → 1.52.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. streamlit/__init__.py +5 -1
  2. streamlit/commands/execution_control.py +89 -14
  3. streamlit/commands/navigation.py +4 -6
  4. streamlit/commands/page_config.py +4 -6
  5. streamlit/components/v1/component_arrow.py +7 -7
  6. streamlit/components/v2/__init__.py +514 -0
  7. streamlit/components/v2/bidi_component/__init__.py +20 -0
  8. streamlit/components/v2/bidi_component/constants.py +29 -0
  9. streamlit/components/v2/bidi_component/main.py +534 -0
  10. streamlit/components/v2/bidi_component/serialization.py +272 -0
  11. streamlit/components/v2/bidi_component/state.py +92 -0
  12. streamlit/components/v2/component_definition_resolver.py +143 -0
  13. streamlit/components/v2/component_file_watcher.py +403 -0
  14. streamlit/components/v2/component_manager.py +439 -0
  15. streamlit/components/v2/component_manifest_handler.py +122 -0
  16. streamlit/components/v2/component_path_utils.py +245 -0
  17. streamlit/components/v2/component_registry.py +426 -0
  18. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  19. streamlit/components/v2/manifest_scanner.py +615 -0
  20. streamlit/components/v2/presentation.py +198 -0
  21. streamlit/components/v2/types.py +324 -0
  22. streamlit/config.py +456 -53
  23. streamlit/config_option.py +4 -1
  24. streamlit/config_util.py +650 -1
  25. streamlit/connections/snowflake_connection.py +1 -1
  26. streamlit/connections/snowpark_connection.py +1 -1
  27. streamlit/dataframe_util.py +33 -26
  28. streamlit/delta_generator.py +13 -4
  29. streamlit/delta_generator_singletons.py +11 -15
  30. streamlit/deprecation_util.py +17 -6
  31. streamlit/elements/alert.py +16 -0
  32. streamlit/elements/arrow.py +68 -10
  33. streamlit/elements/bokeh_chart.py +10 -78
  34. streamlit/elements/code.py +2 -2
  35. streamlit/elements/deck_gl_json_chart.py +98 -40
  36. streamlit/elements/dialog_decorator.py +2 -1
  37. streamlit/elements/exception.py +4 -2
  38. streamlit/elements/form.py +27 -0
  39. streamlit/elements/graphviz_chart.py +1 -3
  40. streamlit/elements/heading.py +63 -10
  41. streamlit/elements/html.py +13 -2
  42. streamlit/elements/image.py +3 -5
  43. streamlit/elements/layouts.py +59 -33
  44. streamlit/elements/lib/built_in_chart_utils.py +50 -19
  45. streamlit/elements/lib/color_util.py +9 -19
  46. streamlit/elements/lib/column_config_utils.py +9 -12
  47. streamlit/elements/lib/column_types.py +40 -12
  48. streamlit/elements/lib/dialog.py +2 -2
  49. streamlit/elements/lib/image_utils.py +3 -5
  50. streamlit/elements/lib/layout_utils.py +100 -13
  51. streamlit/elements/lib/mutable_status_container.py +2 -2
  52. streamlit/elements/lib/options_selector_utils.py +2 -2
  53. streamlit/elements/lib/pandas_styler_utils.py +17 -9
  54. streamlit/elements/lib/shortcut_utils.py +152 -0
  55. streamlit/elements/lib/utils.py +4 -4
  56. streamlit/elements/map.py +80 -37
  57. streamlit/elements/markdown.py +50 -3
  58. streamlit/elements/media.py +5 -7
  59. streamlit/elements/metric.py +34 -6
  60. streamlit/elements/pdf.py +2 -4
  61. streamlit/elements/plotly_chart.py +197 -20
  62. streamlit/elements/progress.py +2 -4
  63. streamlit/elements/space.py +113 -0
  64. streamlit/elements/spinner.py +1 -1
  65. streamlit/elements/text.py +20 -3
  66. streamlit/elements/toast.py +2 -0
  67. streamlit/elements/vega_charts.py +356 -149
  68. streamlit/elements/widgets/audio_input.py +12 -11
  69. streamlit/elements/widgets/button.py +280 -43
  70. streamlit/elements/widgets/button_group.py +60 -9
  71. streamlit/elements/widgets/camera_input.py +3 -5
  72. streamlit/elements/widgets/chat.py +307 -43
  73. streamlit/elements/widgets/color_picker.py +8 -1
  74. streamlit/elements/widgets/data_editor.py +88 -44
  75. streamlit/elements/widgets/file_uploader.py +9 -11
  76. streamlit/elements/widgets/multiselect.py +4 -3
  77. streamlit/elements/widgets/number_input.py +4 -4
  78. streamlit/elements/widgets/radio.py +10 -3
  79. streamlit/elements/widgets/select_slider.py +8 -5
  80. streamlit/elements/widgets/selectbox.py +6 -3
  81. streamlit/elements/widgets/slider.py +38 -42
  82. streamlit/elements/widgets/text_widgets.py +2 -0
  83. streamlit/elements/widgets/time_widgets.py +587 -21
  84. streamlit/elements/write.py +27 -6
  85. streamlit/emojis.py +1 -1
  86. streamlit/errors.py +137 -0
  87. streamlit/git_util.py +1 -1
  88. streamlit/hello/hello.py +8 -0
  89. streamlit/hello/utils.py +2 -1
  90. streamlit/material_icon_names.py +1 -1
  91. streamlit/navigation/page.py +11 -1
  92. streamlit/net_util.py +2 -2
  93. streamlit/proto/Alert_pb2.pyi +3 -3
  94. streamlit/proto/AppPage_pb2.pyi +7 -1
  95. streamlit/proto/ArrowData_pb2.py +27 -0
  96. streamlit/proto/ArrowData_pb2.pyi +52 -0
  97. streamlit/proto/ArrowNamedDataSet_pb2.pyi +7 -1
  98. streamlit/proto/ArrowVegaLiteChart_pb2.pyi +7 -1
  99. streamlit/proto/Arrow_pb2.py +10 -10
  100. streamlit/proto/Arrow_pb2.pyi +19 -12
  101. streamlit/proto/AudioInput_pb2.pyi +7 -1
  102. streamlit/proto/Audio_pb2.pyi +7 -1
  103. streamlit/proto/AuthRedirect_pb2.pyi +7 -1
  104. streamlit/proto/AutoRerun_pb2.pyi +7 -1
  105. streamlit/proto/BackMsg_pb2.py +4 -2
  106. streamlit/proto/BackMsg_pb2.pyi +34 -4
  107. streamlit/proto/Balloons_pb2.pyi +7 -1
  108. streamlit/proto/BidiComponent_pb2.py +34 -0
  109. streamlit/proto/BidiComponent_pb2.pyi +159 -0
  110. streamlit/proto/Block_pb2.py +7 -7
  111. streamlit/proto/Block_pb2.pyi +39 -36
  112. streamlit/proto/BokehChart_pb2.pyi +7 -1
  113. streamlit/proto/ButtonGroup_pb2.pyi +9 -9
  114. streamlit/proto/Button_pb2.py +2 -2
  115. streamlit/proto/Button_pb2.pyi +11 -2
  116. streamlit/proto/CameraInput_pb2.pyi +7 -1
  117. streamlit/proto/ChatInput_pb2.py +6 -6
  118. streamlit/proto/ChatInput_pb2.pyi +18 -6
  119. streamlit/proto/Checkbox_pb2.pyi +3 -3
  120. streamlit/proto/ClientState_pb2.pyi +10 -4
  121. streamlit/proto/Code_pb2.pyi +7 -1
  122. streamlit/proto/ColorPicker_pb2.pyi +7 -1
  123. streamlit/proto/Common_pb2.py +3 -3
  124. streamlit/proto/Common_pb2.pyi +35 -23
  125. streamlit/proto/Components_pb2.pyi +19 -13
  126. streamlit/proto/DataFrame_pb2.pyi +55 -49
  127. streamlit/proto/DateInput_pb2.pyi +7 -1
  128. streamlit/proto/DateTimeInput_pb2.py +28 -0
  129. streamlit/proto/DateTimeInput_pb2.pyi +92 -0
  130. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  131. streamlit/proto/DeckGlJsonChart_pb2.pyi +12 -6
  132. streamlit/proto/Delta_pb2.pyi +7 -1
  133. streamlit/proto/DocString_pb2.pyi +10 -4
  134. streamlit/proto/DownloadButton_pb2.py +2 -2
  135. streamlit/proto/DownloadButton_pb2.pyi +16 -2
  136. streamlit/proto/Element_pb2.py +7 -3
  137. streamlit/proto/Element_pb2.pyi +33 -5
  138. streamlit/proto/Empty_pb2.pyi +7 -1
  139. streamlit/proto/Exception_pb2.pyi +7 -1
  140. streamlit/proto/Favicon_pb2.pyi +7 -1
  141. streamlit/proto/FileUploader_pb2.pyi +7 -1
  142. streamlit/proto/ForwardMsg_pb2.py +12 -10
  143. streamlit/proto/ForwardMsg_pb2.pyi +42 -15
  144. streamlit/proto/GapSize_pb2.pyi +4 -4
  145. streamlit/proto/GitInfo_pb2.pyi +3 -3
  146. streamlit/proto/GraphVizChart_pb2.pyi +7 -1
  147. streamlit/proto/Heading_pb2.pyi +7 -1
  148. streamlit/proto/HeightConfig_pb2.py +2 -2
  149. streamlit/proto/HeightConfig_pb2.pyi +13 -4
  150. streamlit/proto/Html_pb2.py +2 -2
  151. streamlit/proto/Html_pb2.pyi +11 -2
  152. streamlit/proto/IFrame_pb2.pyi +7 -1
  153. streamlit/proto/Image_pb2.pyi +10 -4
  154. streamlit/proto/Json_pb2.pyi +7 -1
  155. streamlit/proto/LabelVisibilityMessage_pb2.pyi +3 -3
  156. streamlit/proto/LinkButton_pb2.py +2 -2
  157. streamlit/proto/LinkButton_pb2.pyi +15 -2
  158. streamlit/proto/Logo_pb2.pyi +7 -1
  159. streamlit/proto/Markdown_pb2.pyi +3 -3
  160. streamlit/proto/Metric_pb2.pyi +7 -7
  161. streamlit/proto/MetricsEvent_pb2.pyi +10 -4
  162. streamlit/proto/MultiSelect_pb2.pyi +7 -1
  163. streamlit/proto/NamedDataSet_pb2.pyi +7 -1
  164. streamlit/proto/Navigation_pb2.pyi +3 -3
  165. streamlit/proto/NewSession_pb2.py +18 -18
  166. streamlit/proto/NewSession_pb2.pyi +59 -40
  167. streamlit/proto/NumberInput_pb2.pyi +3 -3
  168. streamlit/proto/PageConfig_pb2.pyi +7 -7
  169. streamlit/proto/PageInfo_pb2.pyi +7 -1
  170. streamlit/proto/PageLink_pb2.py +2 -2
  171. streamlit/proto/PageLink_pb2.pyi +11 -2
  172. streamlit/proto/PageNotFound_pb2.pyi +7 -1
  173. streamlit/proto/PageProfile_pb2.pyi +13 -7
  174. streamlit/proto/PagesChanged_pb2.pyi +7 -1
  175. streamlit/proto/ParentMessage_pb2.pyi +7 -1
  176. streamlit/proto/PlotlyChart_pb2.py +8 -6
  177. streamlit/proto/PlotlyChart_pb2.pyi +9 -7
  178. streamlit/proto/Progress_pb2.pyi +7 -1
  179. streamlit/proto/Radio_pb2.pyi +7 -1
  180. streamlit/proto/RootContainer_pb2.pyi +1 -1
  181. streamlit/proto/Selectbox_pb2.pyi +7 -1
  182. streamlit/proto/SessionEvent_pb2.pyi +7 -1
  183. streamlit/proto/SessionStatus_pb2.pyi +7 -1
  184. streamlit/proto/Skeleton_pb2.pyi +3 -3
  185. streamlit/proto/Slider_pb2.pyi +5 -5
  186. streamlit/proto/Snow_pb2.pyi +7 -1
  187. streamlit/proto/Space_pb2.py +27 -0
  188. streamlit/proto/Space_pb2.pyi +48 -0
  189. streamlit/proto/Spinner_pb2.pyi +7 -1
  190. streamlit/proto/TextAlignmentConfig_pb2.py +29 -0
  191. streamlit/proto/TextAlignmentConfig_pb2.pyi +68 -0
  192. streamlit/proto/TextArea_pb2.pyi +7 -1
  193. streamlit/proto/TextInput_pb2.pyi +3 -3
  194. streamlit/proto/Text_pb2.pyi +7 -1
  195. streamlit/proto/TimeInput_pb2.pyi +7 -1
  196. streamlit/proto/Toast_pb2.pyi +7 -1
  197. streamlit/proto/VegaLiteChart_pb2.pyi +7 -1
  198. streamlit/proto/Video_pb2.pyi +6 -6
  199. streamlit/proto/WidgetStates_pb2.py +2 -2
  200. streamlit/proto/WidgetStates_pb2.pyi +23 -7
  201. streamlit/proto/WidthConfig_pb2.py +2 -2
  202. streamlit/proto/WidthConfig_pb2.pyi +13 -4
  203. streamlit/proto/openmetrics_data_model_pb2.pyi +52 -52
  204. streamlit/runtime/app_session.py +65 -2
  205. streamlit/runtime/caching/cache_data_api.py +5 -5
  206. streamlit/runtime/caching/cache_errors.py +4 -1
  207. streamlit/runtime/caching/cache_resource_api.py +5 -4
  208. streamlit/runtime/caching/cache_utils.py +3 -2
  209. streamlit/runtime/caching/cached_message_replay.py +3 -3
  210. streamlit/runtime/caching/hashing.py +4 -5
  211. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  212. streamlit/runtime/connection_factory.py +1 -3
  213. streamlit/runtime/download_data_util.py +53 -0
  214. streamlit/runtime/forward_msg_queue.py +5 -1
  215. streamlit/runtime/fragment.py +2 -1
  216. streamlit/runtime/media_file_manager.py +178 -2
  217. streamlit/runtime/memory_media_file_storage.py +1 -1
  218. streamlit/runtime/metrics_util.py +91 -3
  219. streamlit/runtime/runtime.py +14 -0
  220. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  221. streamlit/runtime/scriptrunner/script_runner.py +5 -3
  222. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  223. streamlit/runtime/secrets.py +2 -4
  224. streamlit/runtime/session_manager.py +3 -1
  225. streamlit/runtime/state/common.py +30 -5
  226. streamlit/runtime/state/presentation.py +85 -0
  227. streamlit/runtime/state/query_params.py +80 -29
  228. streamlit/runtime/state/safe_session_state.py +2 -2
  229. streamlit/runtime/state/session_state.py +221 -17
  230. streamlit/runtime/state/widgets.py +19 -3
  231. streamlit/runtime/websocket_session_manager.py +3 -1
  232. streamlit/source_util.py +2 -2
  233. streamlit/static/index.html +2 -2
  234. streamlit/static/manifest.json +557 -239
  235. streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
  236. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  237. streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.ZJDbmVTx.js} +1 -1
  238. streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Dx0vI3vH.js} +1 -1
  239. streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.B7Ero7qQ.js} +3 -3
  240. streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.CG2XN1_g.js} +1 -1
  241. streamlit/static/static/js/IFrameUtil.DefezniK.js +1 -0
  242. streamlit/static/static/js/InputInstructions.Cj5-1zf6.js +1 -0
  243. streamlit/static/static/js/Particles.BfWfv0Aw.js +1 -0
  244. streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.CGQ8OgfO.js} +2 -2
  245. streamlit/static/static/js/StreamlitSyntaxHighlighter.DTKLpwhl.js +20 -0
  246. streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.B2qFUmd9.js} +1 -1
  247. streamlit/static/static/js/_arrayIncludes.B19Iyn2B.js +1 -0
  248. streamlit/static/static/js/_baseIndexOf.BTknn6Gb.js +1 -0
  249. streamlit/static/static/js/{base-input.BQft14La.js → base-input.o9tL8MDP.js} +4 -4
  250. streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.0BeV1IBL.js} +1 -1
  251. streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.RBO59fEm.js} +1 -1
  252. streamlit/static/static/js/data-grid-overlay-editor.CiTkUy0t.js +1 -0
  253. streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.DwNZg3Mw.js} +1 -1
  254. streamlit/static/static/js/embed.XT9xNd3F.js +195 -0
  255. streamlit/static/static/js/{es6.VpBPGCnM.js → es6.x9KsYQg-.js} +2 -2
  256. streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.ZVXpMPi0.js} +1 -1
  257. streamlit/static/static/js/index.5VPOamri.js +1 -0
  258. streamlit/static/static/js/index.8HslT92O.js +14 -0
  259. streamlit/static/static/js/index.AnXMIBz3.js +7 -0
  260. streamlit/static/static/js/index.B0yp3bM1.js +6 -0
  261. streamlit/static/static/js/index.B1fRb5wF.js +1 -0
  262. streamlit/static/static/js/index.B527JZdO.js +3 -0
  263. streamlit/static/static/js/index.BHgV-yW4.js +1 -0
  264. streamlit/static/static/js/index.BQr-XwGV.js +1 -0
  265. streamlit/static/static/js/index.BTtmaLDB.js +1 -0
  266. streamlit/static/static/js/index.BWB_91TA.js +1 -0
  267. streamlit/static/static/js/index.BfEKaEmw.js +1 -0
  268. streamlit/static/static/js/index.BfXjTO8b.js +1 -0
  269. streamlit/static/static/js/index.Bjy4NRu9.js +3 -0
  270. streamlit/static/static/js/index.Bu5JWpT_.js +1 -0
  271. streamlit/static/static/js/index.BuCx76ZV.js +1 -0
  272. streamlit/static/static/js/index.BxjzhVUb.js +2 -0
  273. streamlit/static/static/js/index.By55VdPY.js +1 -0
  274. streamlit/static/static/js/index.CF5MxTbK.js +1 -0
  275. streamlit/static/static/js/index.CLmq_z9K.js +1 -0
  276. streamlit/static/static/js/index.CNH4rdSz.js +1 -0
  277. streamlit/static/static/js/{index.B0H9IXUJ.js → index.CTgm_-jO.js} +10 -41
  278. streamlit/static/static/js/index.C_rK-Swb.js +188 -0
  279. streamlit/static/static/js/index.CjozwSzS.js +1 -0
  280. streamlit/static/static/js/{index.CH1tqnSs.js → index.CkGVt6-G.js} +1 -1
  281. streamlit/static/static/js/index.CuvXOyER.js +2 -0
  282. streamlit/static/static/js/{index.FFOzOWzC.js → index.CyUHWoCC.js} +2 -2
  283. streamlit/static/static/js/index.CyroQtI4.js +2 -0
  284. streamlit/static/static/js/index.D6HmkoDm.js +263 -0
  285. streamlit/static/static/js/index.DAqCNvsO.js +1 -0
  286. streamlit/static/static/js/index.DB_w_CZQ.js +1 -0
  287. streamlit/static/static/js/index.DBalctjj.js +2 -0
  288. streamlit/static/static/js/index.DK0RFJUG.js +11 -0
  289. streamlit/static/static/js/index.DMxc2XFp.js +151 -0
  290. streamlit/static/static/js/index.DO5utP74.js +2 -0
  291. streamlit/static/static/js/index.DS7lf09n.js +1 -0
  292. streamlit/static/static/js/index.DWexTVLY.js +1 -0
  293. streamlit/static/static/js/index.DXxnU5ej.js +1 -0
  294. streamlit/static/static/js/index.DcU3uDvB.js +2 -0
  295. streamlit/static/static/js/index.DlltaH7J.js +1 -0
  296. streamlit/static/static/js/index.DpNTZz82.js +27 -0
  297. streamlit/static/static/js/index.Dr9HIhQw.js +1 -0
  298. streamlit/static/static/js/index.DsgAU5lc.js +1 -0
  299. streamlit/static/static/js/{index.64ejlaaT.js → index.KfXqjDYy.js} +1 -1
  300. streamlit/static/static/js/index.PaidgjCs.js +1 -0
  301. streamlit/static/static/js/index.RJZuWCGA.js +1 -0
  302. streamlit/static/static/js/{index.Ctn27_AE.js → index.hbeqcRTn.js} +53 -122
  303. streamlit/static/static/js/index.q5hIQwAY.js +1 -0
  304. streamlit/static/static/js/index.rORSX6IW.js +1 -0
  305. streamlit/static/static/js/index.uSX757_v.js +1 -0
  306. streamlit/static/static/js/index.x_QRaLMd.js +1 -0
  307. streamlit/static/static/js/{input.s6pjQ49A.js → input.D5oh9-aB.js} +2 -2
  308. streamlit/static/static/js/main.q9oGOg0H.js +13 -0
  309. streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.5kCSFUJS.js} +1 -1
  310. streamlit/static/static/js/moment.C3j7ZXd7.js +4 -0
  311. streamlit/static/static/js/number-overlay-editor.Cn_LsK8N.js +9 -0
  312. streamlit/static/static/js/pandasStylerUtils.BqhXt51_.js +1 -0
  313. streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.DD9NK1Z8.js} +1 -1
  314. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  315. streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.DACSyz29.js} +1 -1
  316. streamlit/static/static/js/styled-components.C3R090At.js +1 -0
  317. streamlit/static/static/js/threshold.Q1mXg5rX.js +1 -0
  318. streamlit/static/static/js/throttle.B0GR3Iyz.js +1 -0
  319. streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.BdhzPxrv.js} +1 -1
  320. streamlit/static/static/js/timer.C2hYhUse.js +1 -0
  321. streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.Db2pdqM2.js} +1 -1
  322. streamlit/static/static/js/uniqueId.CtqIr-Yh.js +1 -0
  323. streamlit/static/static/js/urls.BwSlolu9.js +1 -0
  324. streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.Bfp6TnSw.js} +1 -1
  325. streamlit/static/static/js/useIntlLocale.hRV75Xgj.js +12 -0
  326. streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.QepX7n8Y.js} +1 -1
  327. streamlit/static/static/js/useUpdateUiValue.DHx8TzX6.js +1 -0
  328. streamlit/static/static/js/useWaveformController.WxVzpzEX.js +1 -0
  329. streamlit/static/static/js/value.B4vHRSi7.js +1 -0
  330. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  331. streamlit/static/static/js/withCalculatedWidth.DcKeRSWJ.js +1 -0
  332. streamlit/static/static/js/withFullScreenWrapper.CrHddARq.js +1 -0
  333. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  334. streamlit/string_util.py +9 -4
  335. streamlit/testing/v1/app_test.py +17 -2
  336. streamlit/testing/v1/element_tree.py +85 -9
  337. streamlit/testing/v1/util.py +2 -2
  338. streamlit/type_util.py +3 -4
  339. streamlit/url_util.py +1 -3
  340. streamlit/user_info.py +1 -2
  341. streamlit/util.py +3 -1
  342. streamlit/watcher/event_based_path_watcher.py +23 -12
  343. streamlit/watcher/local_sources_watcher.py +11 -1
  344. streamlit/watcher/path_watcher.py +9 -6
  345. streamlit/watcher/polling_path_watcher.py +4 -1
  346. streamlit/watcher/util.py +2 -2
  347. streamlit/web/bootstrap.py +24 -0
  348. streamlit/web/cli.py +51 -22
  349. streamlit/web/server/bidi_component_request_handler.py +193 -0
  350. streamlit/web/server/component_file_utils.py +97 -0
  351. streamlit/web/server/component_request_handler.py +8 -21
  352. streamlit/web/server/oauth_authlib_routes.py +5 -2
  353. streamlit/web/server/oidc_mixin.py +3 -1
  354. streamlit/web/server/routes.py +2 -2
  355. streamlit/web/server/server.py +9 -0
  356. streamlit/web/server/server_util.py +3 -1
  357. streamlit/web/server/upload_file_request_handler.py +19 -1
  358. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/METADATA +10 -7
  359. streamlit-1.52.0.dist-info/RECORD +620 -0
  360. streamlit/static/static/css/index.CHEnSPGk.css +0 -1
  361. streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
  362. streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
  363. streamlit/static/static/js/Particles.CElH0XX2.js +0 -1
  364. streamlit/static/static/js/data-grid-overlay-editor.DcuHuCyW.js +0 -1
  365. streamlit/static/static/js/index.6xX1278W.js +0 -975
  366. streamlit/static/static/js/index.B-hiXRzw.js +0 -1
  367. streamlit/static/static/js/index.B4cAbHP6.js +0 -1
  368. streamlit/static/static/js/index.B4dUQfni.js +0 -1
  369. streamlit/static/static/js/index.BPQo7BKk.js +0 -1
  370. streamlit/static/static/js/index.Baqa90pe.js +0 -2
  371. streamlit/static/static/js/index.Bj9JgOEC.js +0 -1
  372. streamlit/static/static/js/index.BjCwMzj4.js +0 -3
  373. streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
  374. streamlit/static/static/js/index.Bxz2yX3P.js +0 -1
  375. streamlit/static/static/js/index.BycLveZ4.js +0 -1
  376. streamlit/static/static/js/index.C9BdUqTi.js +0 -1
  377. streamlit/static/static/js/index.CFMf5_ez.js +0 -197
  378. streamlit/static/static/js/index.CGYqqs6j.js +0 -1
  379. streamlit/static/static/js/index.CMItVsFA.js +0 -1
  380. streamlit/static/static/js/index.CTBk8Vk2.js +0 -1
  381. streamlit/static/static/js/index.CiAQIz1H.js +0 -7
  382. streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
  383. streamlit/static/static/js/index.Ck8rQ9OL.js +0 -1
  384. streamlit/static/static/js/index.ClELlchS.js +0 -1617
  385. streamlit/static/static/js/index.Cnpi3o3E.js +0 -1
  386. streamlit/static/static/js/index.D2QEXQq_.js +0 -1
  387. streamlit/static/static/js/index.DH71Ezyj.js +0 -1
  388. streamlit/static/static/js/index.DHh-U0dK.js +0 -3
  389. streamlit/static/static/js/index.DK7hD7_w.js +0 -1
  390. streamlit/static/static/js/index.DKv_lNO7.js +0 -2
  391. streamlit/static/static/js/index.DNLrMXgm.js +0 -12
  392. streamlit/static/static/js/index.DW0Grddz.js +0 -1
  393. streamlit/static/static/js/index.Dbe-Q3C-.js +0 -2
  394. streamlit/static/static/js/index.DcPNYEUo.js +0 -1
  395. streamlit/static/static/js/index.DuxqVQpd.js +0 -1
  396. streamlit/static/static/js/index.GRUzrudl.js +0 -1
  397. streamlit/static/static/js/number-overlay-editor.DdgVR5m3.js +0 -9
  398. streamlit/static/static/js/uniqueId.RI1LJdtz.js +0 -1
  399. streamlit/static/static/js/useUpdateUiValue.DeXelfRH.js +0 -1
  400. streamlit/static/static/js/withFullScreenWrapper.C3561XxJ.js +0 -1
  401. streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
  402. streamlit-1.50.0.dist-info/RECORD +0 -557
  403. {streamlit-1.50.0.data → streamlit-1.52.0.data}/scripts/streamlit.cmd +0 -0
  404. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/WHEEL +0 -0
  405. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/entry_points.txt +0 -0
  406. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,439 @@
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
+ """Custom Components v2 manager and supporting orchestration.
16
+
17
+ This module composes the registry, manifest handling, and file watching
18
+ capabilities for Streamlit's Custom Components v2. It provides a unified
19
+ interface to register components from manifests or individual definitions, query
20
+ component metadata and asset paths, and react to on-disk changes by re-resolving
21
+ component definitions.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import threading
27
+ from dataclasses import dataclass
28
+ from typing import TYPE_CHECKING, Final
29
+
30
+ from streamlit.components.v2.component_definition_resolver import (
31
+ build_definition_with_validation,
32
+ )
33
+ from streamlit.components.v2.component_file_watcher import ComponentFileWatcher
34
+ from streamlit.components.v2.component_manifest_handler import ComponentManifestHandler
35
+ from streamlit.components.v2.component_registry import (
36
+ BidiComponentDefinition,
37
+ BidiComponentRegistry,
38
+ )
39
+ from streamlit.logger import get_logger
40
+
41
+ if TYPE_CHECKING:
42
+ from pathlib import Path
43
+
44
+ from streamlit.components.v2.manifest_scanner import ComponentManifest
45
+
46
+ _LOGGER: Final = get_logger(__name__)
47
+
48
+
49
+ @dataclass
50
+ class _ApiInputs:
51
+ """Inputs provided via the Python API to resolve a component definition.
52
+
53
+ Attributes
54
+ ----------
55
+ css : str | None
56
+ Inline CSS content or a path/glob to a CSS asset within ``asset_dir``.
57
+ js : str | None
58
+ Inline JS content or a path/glob to a JS asset within ``asset_dir``.
59
+ """
60
+
61
+ css: str | None
62
+ js: str | None
63
+
64
+
65
+ class BidiComponentManager:
66
+ """Manager class that composes component registry, manifest handler, and
67
+ file watcher.
68
+
69
+ This class provides a unified interface for working with bidirectional
70
+ components while maintaining clean separation of concerns through
71
+ composition. It handles the coordination and lifecycle management of all
72
+ component-related functionality.
73
+
74
+ Component Lifecycle
75
+ -------------------
76
+ The lifecycle of a component managed by this class involves four key stages:
77
+
78
+ 1. **Discovery**: On startup, ``discover_and_register_components`` scans
79
+ for installed packages with component manifests (``pyproject.toml``).
80
+ For each component found, a placeholder definition containing only its
81
+ name and ``asset_dir`` is registered. This makes the system aware of all
82
+ available installed components from the outset.
83
+
84
+ 2. **Definition & Validation**: When a user's script calls the public API
85
+ (e.g., ``st.components.v2.component(...)``), the manager invokes
86
+ ``build_definition_with_validation``. This function is the single,
87
+ centralized point for all validation. It resolves file paths, performs
88
+ security checks against the component's ``asset_dir``, and produces a
89
+ complete, validated ``BidiComponentDefinition``.
90
+
91
+ 3. **Registration**: The validated definition is then passed to the
92
+ registry's ``register`` method. This adds the complete definition,
93
+ overwriting the placeholder if one existed from the discovery phase.
94
+
95
+ 4. **Updating**: The ``ComponentFileWatcher`` monitors the ``asset_dir``
96
+ for changes. On a change, it triggers a re-computation of the definition
97
+ using the original API inputs, runs it through the same validation
98
+ logic, and updates the registry with the new definition via the stricter
99
+ ``update_component`` method.
100
+
101
+ Notes
102
+ -----
103
+ This manager intentionally favors composition over inheritance and delegates
104
+ specialized responsibilities to ``BidiComponentRegistry``,
105
+ ``ComponentManifestHandler``, and ``ComponentFileWatcher``.
106
+ """
107
+
108
+ def __init__(
109
+ self,
110
+ registry: BidiComponentRegistry | None = None,
111
+ manifest_handler: ComponentManifestHandler | None = None,
112
+ file_watcher: ComponentFileWatcher | None = None,
113
+ ) -> None:
114
+ """Initialize the component manager.
115
+
116
+ Parameters
117
+ ----------
118
+ registry : BidiComponentRegistry, optional
119
+ Component registry instance. If not provided, a new one will be created.
120
+ manifest_handler : ComponentManifestHandler, optional
121
+ Manifest handler instance. If not provided, a new one will be created.
122
+ file_watcher : ComponentFileWatcher, optional
123
+ File watcher instance. If not provided, a new one will be created.
124
+ """
125
+ # Create dependencies
126
+ self._registry = registry or BidiComponentRegistry()
127
+ self._manifest_handler = manifest_handler or ComponentManifestHandler()
128
+ # Store API inputs for re-resolution on change events
129
+ self._api_inputs: dict[str, _ApiInputs] = {}
130
+ self._api_inputs_lock = threading.Lock()
131
+ self._file_watcher = file_watcher or ComponentFileWatcher(
132
+ self._on_components_changed
133
+ )
134
+
135
+ def record_api_inputs(
136
+ self, component_key: str, css: str | None, js: str | None
137
+ ) -> None:
138
+ """Record original API inputs for later re-resolution on file changes.
139
+
140
+ Parameters
141
+ ----------
142
+ component_key : str
143
+ Fully-qualified component name.
144
+ css : str | None
145
+ Inline CSS or a path/glob to a CSS file within the component's
146
+ ``asset_dir``.
147
+ js : str | None
148
+ Inline JavaScript or a path/glob to a JS file within the component's
149
+ ``asset_dir``.
150
+ """
151
+ with self._api_inputs_lock:
152
+ self._api_inputs[component_key] = _ApiInputs(css=css, js=js)
153
+
154
+ def register_from_manifest(
155
+ self, manifest: ComponentManifest, package_root: Path
156
+ ) -> None:
157
+ """Register components from a manifest file.
158
+
159
+ This is a high-level method that processes the manifest and registers
160
+ all components found within it.
161
+
162
+ Parameters
163
+ ----------
164
+ manifest : ComponentManifest
165
+ The component manifest to process.
166
+ package_root : Path
167
+ Root path of the package containing the components.
168
+ """
169
+ # First process the manifest
170
+ component_definitions = self._manifest_handler.process_manifest(
171
+ manifest, package_root
172
+ )
173
+
174
+ # Register all component definitions
175
+ self._registry.register_components_from_definitions(component_definitions)
176
+
177
+ _LOGGER.debug(
178
+ "Registered %d components from manifest", len(component_definitions)
179
+ )
180
+
181
+ def register(self, definition: BidiComponentDefinition) -> None:
182
+ """Register a single component definition.
183
+
184
+ Parameters
185
+ ----------
186
+ definition : BidiComponentDefinition
187
+ The component definition to register.
188
+ """
189
+ self._registry.register(definition)
190
+
191
+ def get(self, name: str) -> BidiComponentDefinition | None:
192
+ """Get a component definition by name.
193
+
194
+ Parameters
195
+ ----------
196
+ name : str
197
+ The name of the component to retrieve.
198
+
199
+ Returns
200
+ -------
201
+ BidiComponentDefinition or None
202
+ The component definition if found; otherwise ``None``.
203
+ """
204
+ return self._registry.get(name)
205
+
206
+ def build_definition_with_validation(
207
+ self,
208
+ *,
209
+ component_key: str,
210
+ html: str | None,
211
+ css: str | None,
212
+ js: str | None,
213
+ ) -> BidiComponentDefinition:
214
+ """Build a validated component definition for the given inputs.
215
+
216
+ Parameters
217
+ ----------
218
+ component_key : str
219
+ Fully-qualified component name the definition is for.
220
+ html : str | None
221
+ Inline HTML content to include in the definition.
222
+ css : str | None
223
+ Inline CSS content or a path/glob under the component's asset_dir.
224
+ js : str | None
225
+ Inline JS content or a path/glob under the component's asset_dir.
226
+
227
+ Returns
228
+ -------
229
+ BidiComponentDefinition
230
+ The fully validated component definition.
231
+ """
232
+ return build_definition_with_validation(
233
+ manager=self,
234
+ component_key=component_key,
235
+ html=html,
236
+ css=css,
237
+ js=js,
238
+ )
239
+
240
+ def get_component_asset_root(self, name: str) -> Path | None:
241
+ """Get the asset root for a manifest-backed component.
242
+
243
+ Parameters
244
+ ----------
245
+ name : str
246
+ The name of the component to get the asset root for.
247
+
248
+ Returns
249
+ -------
250
+ Path or None
251
+ The component's ``asset_root`` directory if found; otherwise
252
+ ``None``.
253
+ """
254
+ return self._manifest_handler.get_asset_root(name)
255
+
256
+ def unregister(self, name: str) -> None:
257
+ """Unregister a component by name.
258
+
259
+ Parameters
260
+ ----------
261
+ name : str
262
+ The name of the component to unregister.
263
+ """
264
+ self._registry.unregister(name)
265
+
266
+ def clear(self) -> None:
267
+ """Clear all registered components."""
268
+ self._registry.clear()
269
+
270
+ def get_component_path(self, name: str) -> str | None:
271
+ """Get the filesystem path for a manifest-backed component.
272
+
273
+ Parameters
274
+ ----------
275
+ name : str
276
+ The name of the component.
277
+
278
+ Returns
279
+ -------
280
+ str or None
281
+ The component's ``asset_dir`` directory if found; otherwise
282
+ ``None``.
283
+ """
284
+ asset_root = self._manifest_handler.get_asset_root(name)
285
+ if asset_root is not None:
286
+ return str(asset_root)
287
+
288
+ return None
289
+
290
+ def start_file_watching(self) -> None:
291
+ """Start file watching for component changes."""
292
+ if self._file_watcher.is_watching_active:
293
+ _LOGGER.warning("File watching is already started")
294
+ return
295
+
296
+ # Get asset watch roots from manifest handler
297
+ asset_roots = self._manifest_handler.get_asset_watch_roots()
298
+
299
+ # Start file watching
300
+ self._file_watcher.start_file_watching(asset_roots)
301
+
302
+ if self._file_watcher.is_watching_active:
303
+ _LOGGER.debug("Started file watching for component changes") # type: ignore[unreachable]
304
+ else:
305
+ _LOGGER.debug("File watching not started")
306
+
307
+ def discover_and_register_components(
308
+ self, *, start_file_watching: bool = True
309
+ ) -> None:
310
+ """Discover installed v2 components and register them.
311
+
312
+ This scans installed distributions for manifests, registers all discovered
313
+ components, and starts file watching for development workflows.
314
+
315
+ Parameters
316
+ ----------
317
+ start_file_watching : bool
318
+ Whether to start file watching after components are registered.
319
+ """
320
+ try:
321
+ from streamlit.components.v2.manifest_scanner import (
322
+ scan_component_manifests,
323
+ )
324
+
325
+ manifests = scan_component_manifests()
326
+ for manifest, package_root in manifests:
327
+ self.register_from_manifest(manifest, package_root)
328
+ _LOGGER.debug(
329
+ "Registered components from pyproject.toml: %s v%s",
330
+ manifest.name,
331
+ manifest.version,
332
+ )
333
+
334
+ # Start file watching for development mode after all components are registered
335
+ if start_file_watching:
336
+ self.start_file_watching()
337
+
338
+ except Exception as e:
339
+ _LOGGER.warning("Failed to scan component manifests: %s", e)
340
+
341
+ def stop_file_watching(self) -> None:
342
+ """Stop file watching."""
343
+ if not self._file_watcher.is_watching_active:
344
+ _LOGGER.warning("File watching is not started")
345
+ return
346
+
347
+ self._file_watcher.stop_file_watching()
348
+
349
+ _LOGGER.debug("Stopped file watching")
350
+
351
+ def get_metadata(self, component_name: str) -> ComponentManifest | None:
352
+ """Get metadata for a component.
353
+
354
+ Parameters
355
+ ----------
356
+ component_name : str
357
+ The name of the component to get metadata for.
358
+
359
+ Returns
360
+ -------
361
+ ComponentManifest or None
362
+ The component metadata if found; otherwise ``None``.
363
+ """
364
+ return self._manifest_handler.get_metadata(component_name)
365
+
366
+ def _on_components_changed(self, component_names: list[str]) -> None:
367
+ """Handle change events for components' asset roots.
368
+
369
+ For each component, re-resolve from stored API inputs and update the
370
+ registry with the new definition if resolution succeeds.
371
+
372
+ Parameters
373
+ ----------
374
+ component_names : list[str]
375
+ Fully-qualified component names whose watched files changed.
376
+ """
377
+ for name in component_names:
378
+ try:
379
+ updated_def = self._recompute_definition_from_api(name)
380
+ if updated_def is not None:
381
+ self._registry.update_component(updated_def)
382
+ except Exception: # noqa: PERF203
383
+ _LOGGER.exception("Failed to update component after change: %s", name)
384
+
385
+ def _recompute_definition_from_api(
386
+ self, component_name: str
387
+ ) -> BidiComponentDefinition | None:
388
+ """Recompute a component's definition using previously recorded API inputs.
389
+
390
+ Parameters
391
+ ----------
392
+ component_name : str
393
+ Fully-qualified component name to recompute.
394
+
395
+ Returns
396
+ -------
397
+ BidiComponentDefinition | None
398
+ A fully validated component definition suitable for replacing the
399
+ stored entry in the registry, or ``None`` if recomputation failed
400
+ or no API inputs were previously recorded.
401
+ """
402
+ with self._api_inputs_lock:
403
+ inputs = self._api_inputs.get(component_name)
404
+ if inputs is None:
405
+ return None
406
+
407
+ # Get existing def to preserve html unless new content is provided later
408
+ existing_def = self._registry.get(component_name)
409
+ html_value = existing_def.html if existing_def else None
410
+
411
+ try:
412
+ # Resolve a fully validated definition from stored API inputs and
413
+ # the preserved html value from the existing definition.
414
+ new_def = self.build_definition_with_validation(
415
+ component_key=component_name,
416
+ html=html_value,
417
+ css=inputs.css,
418
+ js=inputs.js,
419
+ )
420
+ except Exception as e:
421
+ _LOGGER.debug(
422
+ "Skipping update for %s due to re-resolution error: %s",
423
+ component_name,
424
+ e,
425
+ )
426
+ return None
427
+
428
+ return new_def
429
+
430
+ @property
431
+ def is_file_watching_started(self) -> bool:
432
+ """Check if file watching is currently active.
433
+
434
+ Returns
435
+ -------
436
+ bool
437
+ True if file watching is started, False otherwise
438
+ """
439
+ return self._file_watcher.is_watching_active
@@ -0,0 +1,122 @@
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
+ from typing import TYPE_CHECKING, Any
18
+
19
+ if TYPE_CHECKING:
20
+ from collections.abc import MutableMapping
21
+ from pathlib import Path
22
+
23
+ from streamlit.components.v2.manifest_scanner import ComponentManifest
24
+
25
+
26
+ class ComponentManifestHandler:
27
+ """Handles component registration from parsed ComponentManifest objects."""
28
+
29
+ def __init__(self) -> None:
30
+ # Component metadata from pyproject.toml
31
+ self._metadata: MutableMapping[str, ComponentManifest] = {}
32
+ # Resolved asset roots keyed by fully-qualified component name
33
+ self._asset_roots: MutableMapping[str, Path] = {}
34
+
35
+ def process_manifest(
36
+ self, manifest: ComponentManifest, package_root: Path
37
+ ) -> dict[str, dict[str, Any]]:
38
+ """Process a manifest and return component definitions to register.
39
+
40
+ Parameters
41
+ ----------
42
+ manifest : ComponentManifest
43
+ The manifest to process
44
+ package_root : Path
45
+ The package root directory
46
+
47
+ Returns
48
+ -------
49
+ dict[str, dict[str, Any]]
50
+ Dictionary mapping component names to their definitions
51
+
52
+ Raises
53
+ ------
54
+ StreamlitComponentRegistryError
55
+ If a declared ``asset_dir`` does not exist, is not a directory, or
56
+ resolves (after following symlinks) outside of ``package_root``.
57
+ """
58
+ base_name = manifest.name
59
+ component_definitions = {}
60
+
61
+ # Process each component in the manifest
62
+ for comp_config in manifest.components:
63
+ comp_name = comp_config.name
64
+
65
+ component_name = f"{base_name}.{comp_name}"
66
+
67
+ # Parse and persist asset_dir if provided. This is the component's
68
+ # root directory for all future file references.
69
+ asset_root = comp_config.resolve_asset_root(package_root)
70
+ if asset_root is not None:
71
+ self._asset_roots[component_name] = asset_root
72
+
73
+ # Create component definition data
74
+ component_definitions[component_name] = {
75
+ "name": component_name,
76
+ }
77
+
78
+ # Store metadata
79
+ self._metadata[component_name] = manifest
80
+
81
+ return component_definitions
82
+
83
+ def get_metadata(self, component_name: str) -> ComponentManifest | None:
84
+ """Get metadata for a specific component.
85
+
86
+ Parameters
87
+ ----------
88
+ component_name : str
89
+ Fully-qualified component name (e.g., ``"package.component"``).
90
+
91
+ Returns
92
+ -------
93
+ ComponentManifest | None
94
+ The manifest that declared this component, or ``None`` if unknown.
95
+ """
96
+ return self._metadata.get(component_name)
97
+
98
+ def get_asset_root(self, component_name: str) -> Path | None:
99
+ """Get the absolute asset root directory for a component if declared.
100
+
101
+ Parameters
102
+ ----------
103
+ component_name : str
104
+ Fully-qualified component name (e.g. "package.component").
105
+
106
+ Returns
107
+ -------
108
+ Path | None
109
+ Absolute path to the component's asset root if present, otherwise None.
110
+ """
111
+ return self._asset_roots.get(component_name)
112
+
113
+ def get_asset_watch_roots(self) -> dict[str, Path]:
114
+ """Get a mapping of component names to their asset root directories.
115
+
116
+ Returns
117
+ -------
118
+ dict[str, Path]
119
+ A shallow copy mapping fully-qualified component names to absolute
120
+ asset root directories.
121
+ """
122
+ return dict(self._asset_roots)