streamlit-data-editor-plus 0.1.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 (456) hide show
  1. streamlit/__init__.py +292 -0
  2. streamlit/__main__.py +20 -0
  3. streamlit/auth_util.py +583 -0
  4. streamlit/cli_util.py +107 -0
  5. streamlit/column_config.py +60 -0
  6. streamlit/commands/__init__.py +13 -0
  7. streamlit/commands/echo.py +128 -0
  8. streamlit/commands/execution_control.py +318 -0
  9. streamlit/commands/logo.py +250 -0
  10. streamlit/commands/navigation.py +430 -0
  11. streamlit/commands/page_config.py +335 -0
  12. streamlit/components/__init__.py +13 -0
  13. streamlit/components/lib/__init__.py +13 -0
  14. streamlit/components/lib/local_component_registry.py +84 -0
  15. streamlit/components/types/__init__.py +13 -0
  16. streamlit/components/types/base_component_registry.py +99 -0
  17. streamlit/components/types/base_custom_component.py +158 -0
  18. streamlit/components/v1/__init__.py +29 -0
  19. streamlit/components/v1/component_arrow.py +141 -0
  20. streamlit/components/v1/component_registry.py +147 -0
  21. streamlit/components/v1/components.py +38 -0
  22. streamlit/components/v1/custom_component.py +239 -0
  23. streamlit/components/v2/__init__.py +531 -0
  24. streamlit/components/v2/bidi_component/__init__.py +20 -0
  25. streamlit/components/v2/bidi_component/constants.py +29 -0
  26. streamlit/components/v2/bidi_component/main.py +537 -0
  27. streamlit/components/v2/bidi_component/serialization.py +272 -0
  28. streamlit/components/v2/bidi_component/state.py +92 -0
  29. streamlit/components/v2/component_definition_resolver.py +143 -0
  30. streamlit/components/v2/component_file_watcher.py +403 -0
  31. streamlit/components/v2/component_manager.py +439 -0
  32. streamlit/components/v2/component_manifest_handler.py +122 -0
  33. streamlit/components/v2/component_path_utils.py +233 -0
  34. streamlit/components/v2/component_registry.py +426 -0
  35. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  36. streamlit/components/v2/manifest_scanner.py +620 -0
  37. streamlit/components/v2/presentation.py +198 -0
  38. streamlit/components/v2/types.py +317 -0
  39. streamlit/config.py +2977 -0
  40. streamlit/config_option.py +319 -0
  41. streamlit/config_util.py +887 -0
  42. streamlit/connections/__init__.py +32 -0
  43. streamlit/connections/base_connection.py +215 -0
  44. streamlit/connections/snowflake_connection.py +765 -0
  45. streamlit/connections/snowpark_connection.py +213 -0
  46. streamlit/connections/sql_connection.py +427 -0
  47. streamlit/connections/util.py +97 -0
  48. streamlit/cursor.py +314 -0
  49. streamlit/dataframe_util.py +1434 -0
  50. streamlit/delta_generator.py +696 -0
  51. streamlit/delta_generator_singletons.py +243 -0
  52. streamlit/deprecation_util.py +253 -0
  53. streamlit/development.py +21 -0
  54. streamlit/elements/__init__.py +13 -0
  55. streamlit/elements/alert.py +341 -0
  56. streamlit/elements/arrow.py +1065 -0
  57. streamlit/elements/balloons.py +47 -0
  58. streamlit/elements/bokeh_chart.py +75 -0
  59. streamlit/elements/code.py +154 -0
  60. streamlit/elements/deck_gl_json_chart.py +627 -0
  61. streamlit/elements/dialog_decorator.py +320 -0
  62. streamlit/elements/empty.py +130 -0
  63. streamlit/elements/exception.py +370 -0
  64. streamlit/elements/form.py +481 -0
  65. streamlit/elements/graphviz_chart.py +226 -0
  66. streamlit/elements/heading.py +407 -0
  67. streamlit/elements/help.py +565 -0
  68. streamlit/elements/html.py +189 -0
  69. streamlit/elements/iframe.py +245 -0
  70. streamlit/elements/image.py +221 -0
  71. streamlit/elements/json.py +171 -0
  72. streamlit/elements/layouts.py +1534 -0
  73. streamlit/elements/lib/__init__.py +13 -0
  74. streamlit/elements/lib/built_in_chart_utils.py +1316 -0
  75. streamlit/elements/lib/color_util.py +272 -0
  76. streamlit/elements/lib/column_config_utils.py +555 -0
  77. streamlit/elements/lib/column_types.py +2699 -0
  78. streamlit/elements/lib/dialog.py +212 -0
  79. streamlit/elements/lib/dicttools.py +152 -0
  80. streamlit/elements/lib/file_uploader_utils.py +91 -0
  81. streamlit/elements/lib/form_utils.py +77 -0
  82. streamlit/elements/lib/image_utils.py +447 -0
  83. streamlit/elements/lib/js_number.py +105 -0
  84. streamlit/elements/lib/layout_utils.py +325 -0
  85. streamlit/elements/lib/mutable_expander_container.py +73 -0
  86. streamlit/elements/lib/mutable_popover_container.py +73 -0
  87. streamlit/elements/lib/mutable_status_container.py +194 -0
  88. streamlit/elements/lib/mutable_tab_container.py +73 -0
  89. streamlit/elements/lib/options_selector_utils.py +480 -0
  90. streamlit/elements/lib/pandas_styler_utils.py +302 -0
  91. streamlit/elements/lib/policies.py +198 -0
  92. streamlit/elements/lib/shortcut_utils.py +152 -0
  93. streamlit/elements/lib/streamlit_plotly_theme.py +206 -0
  94. streamlit/elements/lib/subtitle_utils.py +175 -0
  95. streamlit/elements/lib/utils.py +274 -0
  96. streamlit/elements/map.py +526 -0
  97. streamlit/elements/markdown.py +529 -0
  98. streamlit/elements/media.py +843 -0
  99. streamlit/elements/metric.py +529 -0
  100. streamlit/elements/pdf.py +190 -0
  101. streamlit/elements/plotly_chart.py +779 -0
  102. streamlit/elements/progress.py +172 -0
  103. streamlit/elements/pyplot.py +240 -0
  104. streamlit/elements/snow.py +47 -0
  105. streamlit/elements/space.py +121 -0
  106. streamlit/elements/spinner.py +152 -0
  107. streamlit/elements/table.py +240 -0
  108. streamlit/elements/text.py +113 -0
  109. streamlit/elements/toast.py +175 -0
  110. streamlit/elements/vega_charts.py +2510 -0
  111. streamlit/elements/widgets/__init__.py +13 -0
  112. streamlit/elements/widgets/audio_input.py +334 -0
  113. streamlit/elements/widgets/button.py +1559 -0
  114. streamlit/elements/widgets/button_group.py +1061 -0
  115. streamlit/elements/widgets/camera_input.py +281 -0
  116. streamlit/elements/widgets/chat.py +1028 -0
  117. streamlit/elements/widgets/checkbox.py +420 -0
  118. streamlit/elements/widgets/color_picker.py +329 -0
  119. streamlit/elements/widgets/data_editor.py +1168 -0
  120. streamlit/elements/widgets/data_editor_plus.py +902 -0
  121. streamlit/elements/widgets/feedback.py +322 -0
  122. streamlit/elements/widgets/file_uploader.py +592 -0
  123. streamlit/elements/widgets/multiselect.py +654 -0
  124. streamlit/elements/widgets/number_input.py +719 -0
  125. streamlit/elements/widgets/radio.py +551 -0
  126. streamlit/elements/widgets/select_slider.py +568 -0
  127. streamlit/elements/widgets/selectbox.py +680 -0
  128. streamlit/elements/widgets/slider.py +1093 -0
  129. streamlit/elements/widgets/text_widgets.py +779 -0
  130. streamlit/elements/widgets/time_widgets.py +1712 -0
  131. streamlit/elements/write.py +585 -0
  132. streamlit/emojis.py +34 -0
  133. streamlit/env_util.py +56 -0
  134. streamlit/error_util.py +112 -0
  135. streamlit/errors.py +680 -0
  136. streamlit/external/__init__.py +13 -0
  137. streamlit/external/langchain/__init__.py +23 -0
  138. streamlit/external/langchain/streamlit_callback_handler.py +410 -0
  139. streamlit/file_util.py +266 -0
  140. streamlit/git_util.py +200 -0
  141. streamlit/hello/__init__.py +13 -0
  142. streamlit/hello/__pycache__/__init__.cpython-312.pyc +0 -0
  143. streamlit/hello/__pycache__/streamlit_app.cpython-312.pyc +0 -0
  144. streamlit/hello/animation_demo.py +82 -0
  145. streamlit/hello/dataframe_demo.py +71 -0
  146. streamlit/hello/hello.py +46 -0
  147. streamlit/hello/mapping_demo.py +113 -0
  148. streamlit/hello/plotting_demo.py +62 -0
  149. streamlit/hello/streamlit_app.py +57 -0
  150. streamlit/hello/utils.py +30 -0
  151. streamlit/logger.py +129 -0
  152. streamlit/material_icon_names.py +25 -0
  153. streamlit/navigation/__init__.py +13 -0
  154. streamlit/navigation/page.py +365 -0
  155. streamlit/net_util.py +125 -0
  156. streamlit/path_security.py +98 -0
  157. streamlit/platform.py +31 -0
  158. streamlit/proto/Alert_pb2.py +28 -0
  159. streamlit/proto/Alert_pb2.pyi +100 -0
  160. streamlit/proto/AppPage_pb2.py +25 -0
  161. streamlit/proto/AppPage_pb2.pyi +75 -0
  162. streamlit/proto/ArrowData_pb2.py +27 -0
  163. streamlit/proto/ArrowData_pb2.pyi +103 -0
  164. streamlit/proto/ArrowNamedDataSet_pb2.py +26 -0
  165. streamlit/proto/ArrowNamedDataSet_pb2.pyi +65 -0
  166. streamlit/proto/AudioInput_pb2.py +26 -0
  167. streamlit/proto/AudioInput_pb2.pyi +72 -0
  168. streamlit/proto/Audio_pb2.py +26 -0
  169. streamlit/proto/Audio_pb2.pyi +75 -0
  170. streamlit/proto/AuthRedirect_pb2.py +25 -0
  171. streamlit/proto/AuthRedirect_pb2.pyi +48 -0
  172. streamlit/proto/AutoRerun_pb2.py +25 -0
  173. streamlit/proto/AutoRerun_pb2.pyi +52 -0
  174. streamlit/proto/BackMsg_pb2.py +29 -0
  175. streamlit/proto/BackMsg_pb2.pyi +132 -0
  176. streamlit/proto/Balloons_pb2.py +25 -0
  177. streamlit/proto/Balloons_pb2.pyi +48 -0
  178. streamlit/proto/BidiComponent_pb2.py +32 -0
  179. streamlit/proto/BidiComponent_pb2.pyi +176 -0
  180. streamlit/proto/Block_pb2.py +62 -0
  181. streamlit/proto/Block_pb2.pyi +518 -0
  182. streamlit/proto/ButtonGroup_pb2.py +32 -0
  183. streamlit/proto/ButtonGroup_pb2.pyi +157 -0
  184. streamlit/proto/ButtonLikeIconPosition_pb2.py +25 -0
  185. streamlit/proto/ButtonLikeIconPosition_pb2.pyi +47 -0
  186. streamlit/proto/Button_pb2.py +26 -0
  187. streamlit/proto/Button_pb2.pyi +82 -0
  188. streamlit/proto/CameraInput_pb2.py +26 -0
  189. streamlit/proto/CameraInput_pb2.pyi +66 -0
  190. streamlit/proto/ChatInput_pb2.py +27 -0
  191. streamlit/proto/ChatInput_pb2.pyi +113 -0
  192. streamlit/proto/Checkbox_pb2.py +28 -0
  193. streamlit/proto/Checkbox_pb2.pyi +99 -0
  194. streamlit/proto/ClientState_pb2.py +28 -0
  195. streamlit/proto/ClientState_pb2.pyi +137 -0
  196. streamlit/proto/Code_pb2.py +25 -0
  197. streamlit/proto/Code_pb2.pyi +59 -0
  198. streamlit/proto/ColorPicker_pb2.py +26 -0
  199. streamlit/proto/ColorPicker_pb2.pyi +82 -0
  200. streamlit/proto/Common_pb2.py +49 -0
  201. streamlit/proto/Common_pb2.pyi +325 -0
  202. streamlit/proto/Components_pb2.py +33 -0
  203. streamlit/proto/Components_pb2.pyi +196 -0
  204. streamlit/proto/Dataframe_pb2.py +30 -0
  205. streamlit/proto/Dataframe_pb2.pyi +172 -0
  206. streamlit/proto/DateInput_pb2.py +26 -0
  207. streamlit/proto/DateInput_pb2.pyi +91 -0
  208. streamlit/proto/DateTimeInput_pb2.py +26 -0
  209. streamlit/proto/DateTimeInput_pb2.pyi +94 -0
  210. streamlit/proto/DeckGlJsonChart_pb2.py +27 -0
  211. streamlit/proto/DeckGlJsonChart_pb2.pyi +91 -0
  212. streamlit/proto/Delta_pb2.py +29 -0
  213. streamlit/proto/Delta_pb2.pyi +82 -0
  214. streamlit/proto/DownloadButton_pb2.py +26 -0
  215. streamlit/proto/DownloadButton_pb2.pyi +92 -0
  216. streamlit/proto/Element_pb2.py +81 -0
  217. streamlit/proto/Element_pb2.pyi +348 -0
  218. streamlit/proto/Empty_pb2.py +25 -0
  219. streamlit/proto/Empty_pb2.pyi +42 -0
  220. streamlit/proto/Exception_pb2.py +26 -0
  221. streamlit/proto/Exception_pb2.pyi +88 -0
  222. streamlit/proto/Favicon_pb2.py +25 -0
  223. streamlit/proto/Favicon_pb2.pyi +47 -0
  224. streamlit/proto/Feedback_pb2.py +27 -0
  225. streamlit/proto/Feedback_pb2.pyi +93 -0
  226. streamlit/proto/FileUploader_pb2.py +26 -0
  227. streamlit/proto/FileUploader_pb2.pyi +90 -0
  228. streamlit/proto/ForwardMsg_pb2.py +48 -0
  229. streamlit/proto/ForwardMsg_pb2.pyi +296 -0
  230. streamlit/proto/GapSize_pb2.py +27 -0
  231. streamlit/proto/GapSize_pb2.pyi +82 -0
  232. streamlit/proto/GitInfo_pb2.py +27 -0
  233. streamlit/proto/GitInfo_pb2.pyi +84 -0
  234. streamlit/proto/GraphVizChart_pb2.py +25 -0
  235. streamlit/proto/GraphVizChart_pb2.pyi +56 -0
  236. streamlit/proto/Heading_pb2.py +25 -0
  237. streamlit/proto/Heading_pb2.pyi +63 -0
  238. streamlit/proto/HeightConfig_pb2.py +25 -0
  239. streamlit/proto/HeightConfig_pb2.pyi +61 -0
  240. streamlit/proto/Help_pb2.py +27 -0
  241. streamlit/proto/Help_pb2.pyi +104 -0
  242. streamlit/proto/Html_pb2.py +25 -0
  243. streamlit/proto/Html_pb2.pyi +52 -0
  244. streamlit/proto/IFrame_pb2.py +25 -0
  245. streamlit/proto/IFrame_pb2.pyi +68 -0
  246. streamlit/proto/Image_pb2.py +27 -0
  247. streamlit/proto/Image_pb2.pyi +73 -0
  248. streamlit/proto/Json_pb2.py +25 -0
  249. streamlit/proto/Json_pb2.pyi +63 -0
  250. streamlit/proto/LabelVisibility_pb2.py +27 -0
  251. streamlit/proto/LabelVisibility_pb2.pyi +69 -0
  252. streamlit/proto/LinkButton_pb2.py +26 -0
  253. streamlit/proto/LinkButton_pb2.pyi +76 -0
  254. streamlit/proto/Logo_pb2.py +27 -0
  255. streamlit/proto/Logo_pb2.pyi +82 -0
  256. streamlit/proto/Markdown_pb2.py +27 -0
  257. streamlit/proto/Markdown_pb2.pyi +83 -0
  258. streamlit/proto/Metric_pb2.py +32 -0
  259. streamlit/proto/Metric_pb2.pyi +145 -0
  260. streamlit/proto/MetricsEvent_pb2.py +28 -0
  261. streamlit/proto/MetricsEvent_pb2.pyi +224 -0
  262. streamlit/proto/MultiSelect_pb2.py +26 -0
  263. streamlit/proto/MultiSelect_pb2.pyi +108 -0
  264. streamlit/proto/Navigation_pb2.py +28 -0
  265. streamlit/proto/Navigation_pb2.pyi +89 -0
  266. streamlit/proto/NewSession_pb2.py +47 -0
  267. streamlit/proto/NewSession_pb2.pyi +753 -0
  268. streamlit/proto/NumberInput_pb2.py +28 -0
  269. streamlit/proto/NumberInput_pb2.pyi +138 -0
  270. streamlit/proto/PageConfig_pb2.py +33 -0
  271. streamlit/proto/PageConfig_pb2.pyi +179 -0
  272. streamlit/proto/PageInfo_pb2.py +25 -0
  273. streamlit/proto/PageInfo_pb2.pyi +50 -0
  274. streamlit/proto/PageLink_pb2.py +26 -0
  275. streamlit/proto/PageLink_pb2.pyi +80 -0
  276. streamlit/proto/PageNotFound_pb2.py +25 -0
  277. streamlit/proto/PageNotFound_pb2.pyi +49 -0
  278. streamlit/proto/PageProfile_pb2.py +29 -0
  279. streamlit/proto/PageProfile_pb2.pyi +146 -0
  280. streamlit/proto/ParentMessage_pb2.py +25 -0
  281. streamlit/proto/ParentMessage_pb2.pyi +53 -0
  282. streamlit/proto/PlotlyChart_pb2.py +27 -0
  283. streamlit/proto/PlotlyChart_pb2.pyi +96 -0
  284. streamlit/proto/Progress_pb2.py +25 -0
  285. streamlit/proto/Progress_pb2.pyi +50 -0
  286. streamlit/proto/Radio_pb2.py +26 -0
  287. streamlit/proto/Radio_pb2.pyi +104 -0
  288. streamlit/proto/RootContainer_pb2.py +25 -0
  289. streamlit/proto/RootContainer_pb2.pyi +56 -0
  290. streamlit/proto/Selectbox_pb2.py +26 -0
  291. streamlit/proto/Selectbox_pb2.pyi +107 -0
  292. streamlit/proto/SessionEvent_pb2.py +26 -0
  293. streamlit/proto/SessionEvent_pb2.pyi +72 -0
  294. streamlit/proto/SessionStatus_pb2.py +25 -0
  295. streamlit/proto/SessionStatus_pb2.pyi +64 -0
  296. streamlit/proto/Skeleton_pb2.py +27 -0
  297. streamlit/proto/Skeleton_pb2.pyi +75 -0
  298. streamlit/proto/Slider_pb2.py +30 -0
  299. streamlit/proto/Slider_pb2.pyi +161 -0
  300. streamlit/proto/Snow_pb2.py +25 -0
  301. streamlit/proto/Snow_pb2.pyi +48 -0
  302. streamlit/proto/Space_pb2.py +25 -0
  303. streamlit/proto/Space_pb2.pyi +48 -0
  304. streamlit/proto/Spinner_pb2.py +25 -0
  305. streamlit/proto/Spinner_pb2.pyi +56 -0
  306. streamlit/proto/Table_pb2.py +28 -0
  307. streamlit/proto/Table_pb2.pyi +83 -0
  308. streamlit/proto/TextAlignmentConfig_pb2.py +27 -0
  309. streamlit/proto/TextAlignmentConfig_pb2.pyi +69 -0
  310. streamlit/proto/TextArea_pb2.py +26 -0
  311. streamlit/proto/TextArea_pb2.pyi +97 -0
  312. streamlit/proto/TextInput_pb2.py +28 -0
  313. streamlit/proto/TextInput_pb2.pyi +124 -0
  314. streamlit/proto/Text_pb2.py +25 -0
  315. streamlit/proto/Text_pb2.pyi +53 -0
  316. streamlit/proto/TimeInput_pb2.py +26 -0
  317. streamlit/proto/TimeInput_pb2.pyi +86 -0
  318. streamlit/proto/Toast_pb2.py +25 -0
  319. streamlit/proto/Toast_pb2.pyi +64 -0
  320. streamlit/proto/Transient_pb2.py +26 -0
  321. streamlit/proto/Transient_pb2.pyi +53 -0
  322. streamlit/proto/VegaLiteChart_pb2.py +27 -0
  323. streamlit/proto/VegaLiteChart_pb2.pyi +92 -0
  324. streamlit/proto/Video_pb2.py +30 -0
  325. streamlit/proto/Video_pb2.pyi +129 -0
  326. streamlit/proto/WidgetStates_pb2.py +31 -0
  327. streamlit/proto/WidgetStates_pb2.pyi +157 -0
  328. streamlit/proto/WidthConfig_pb2.py +25 -0
  329. streamlit/proto/WidthConfig_pb2.pyi +61 -0
  330. streamlit/proto/__init__.py +15 -0
  331. streamlit/proto/openmetrics_data_model_pb2.py +58 -0
  332. streamlit/proto/openmetrics_data_model_pb2.pyi +558 -0
  333. streamlit/py.typed +0 -0
  334. streamlit/runtime/__init__.py +50 -0
  335. streamlit/runtime/app_session.py +1302 -0
  336. streamlit/runtime/caching/__init__.py +118 -0
  337. streamlit/runtime/caching/cache_data_api.py +775 -0
  338. streamlit/runtime/caching/cache_errors.py +143 -0
  339. streamlit/runtime/caching/cache_resource_api.py +756 -0
  340. streamlit/runtime/caching/cache_type.py +33 -0
  341. streamlit/runtime/caching/cache_utils.py +601 -0
  342. streamlit/runtime/caching/cached_message_replay.py +290 -0
  343. streamlit/runtime/caching/hashing.py +655 -0
  344. streamlit/runtime/caching/legacy_cache_api.py +170 -0
  345. streamlit/runtime/caching/storage/__init__.py +29 -0
  346. streamlit/runtime/caching/storage/cache_storage_protocol.py +236 -0
  347. streamlit/runtime/caching/storage/dummy_cache_storage.py +60 -0
  348. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +159 -0
  349. streamlit/runtime/caching/storage/local_disk_cache_storage.py +223 -0
  350. streamlit/runtime/caching/ttl_cleanup_cache.py +85 -0
  351. streamlit/runtime/connection_factory.py +498 -0
  352. streamlit/runtime/context.py +449 -0
  353. streamlit/runtime/context_util.py +49 -0
  354. streamlit/runtime/credentials.py +355 -0
  355. streamlit/runtime/download_data_util.py +53 -0
  356. streamlit/runtime/forward_msg_cache.py +101 -0
  357. streamlit/runtime/forward_msg_queue.py +263 -0
  358. streamlit/runtime/fragment.py +441 -0
  359. streamlit/runtime/media_file_manager.py +409 -0
  360. streamlit/runtime/media_file_storage.py +143 -0
  361. streamlit/runtime/memory_media_file_storage.py +201 -0
  362. streamlit/runtime/memory_session_storage.py +77 -0
  363. streamlit/runtime/memory_uploaded_file_manager.py +149 -0
  364. streamlit/runtime/metrics_util.py +612 -0
  365. streamlit/runtime/pages_manager.py +160 -0
  366. streamlit/runtime/runtime.py +775 -0
  367. streamlit/runtime/runtime_util.py +108 -0
  368. streamlit/runtime/script_data.py +46 -0
  369. streamlit/runtime/scriptrunner/__init__.py +38 -0
  370. streamlit/runtime/scriptrunner/exec_code.py +167 -0
  371. streamlit/runtime/scriptrunner/magic.py +277 -0
  372. streamlit/runtime/scriptrunner/magic_funcs.py +32 -0
  373. streamlit/runtime/scriptrunner/script_cache.py +89 -0
  374. streamlit/runtime/scriptrunner/script_runner.py +805 -0
  375. streamlit/runtime/scriptrunner_utils/__init__.py +19 -0
  376. streamlit/runtime/scriptrunner_utils/exceptions.py +44 -0
  377. streamlit/runtime/scriptrunner_utils/script_requests.py +311 -0
  378. streamlit/runtime/scriptrunner_utils/script_run_context.py +277 -0
  379. streamlit/runtime/secrets.py +533 -0
  380. streamlit/runtime/session_manager.py +430 -0
  381. streamlit/runtime/state/__init__.py +47 -0
  382. streamlit/runtime/state/common.py +256 -0
  383. streamlit/runtime/state/presentation.py +85 -0
  384. streamlit/runtime/state/query_params.py +767 -0
  385. streamlit/runtime/state/query_params_proxy.py +222 -0
  386. streamlit/runtime/state/safe_session_state.py +146 -0
  387. streamlit/runtime/state/session_state.py +1299 -0
  388. streamlit/runtime/state/session_state_proxy.py +153 -0
  389. streamlit/runtime/state/widgets.py +197 -0
  390. streamlit/runtime/stats.py +356 -0
  391. streamlit/runtime/theme_util.py +148 -0
  392. streamlit/runtime/uploaded_file_manager.py +152 -0
  393. streamlit/runtime/websocket_session_manager.py +301 -0
  394. streamlit/source_util.py +97 -0
  395. streamlit/starlette.py +34 -0
  396. streamlit/string_util.py +264 -0
  397. streamlit/temporary_directory.py +67 -0
  398. streamlit/testing/__init__.py +13 -0
  399. streamlit/testing/v1/__init__.py +17 -0
  400. streamlit/testing/v1/app_test.py +1089 -0
  401. streamlit/testing/v1/element_tree.py +2272 -0
  402. streamlit/testing/v1/local_script_runner.py +176 -0
  403. streamlit/testing/v1/util.py +61 -0
  404. streamlit/time_util.py +73 -0
  405. streamlit/type_util.py +480 -0
  406. streamlit/url_util.py +120 -0
  407. streamlit/user_info.py +698 -0
  408. streamlit/util.py +108 -0
  409. streamlit/vendor/__init__.py +0 -0
  410. streamlit/vendor/pympler/__init__.py +0 -0
  411. streamlit/vendor/pympler/asizeof.py +2870 -0
  412. streamlit/version.py +18 -0
  413. streamlit/watcher/__init__.py +28 -0
  414. streamlit/watcher/event_based_path_watcher.py +500 -0
  415. streamlit/watcher/folder_black_list.py +82 -0
  416. streamlit/watcher/local_sources_watcher.py +297 -0
  417. streamlit/watcher/path_watcher.py +244 -0
  418. streamlit/watcher/polling_path_watcher.py +138 -0
  419. streamlit/watcher/util.py +223 -0
  420. streamlit/web/__init__.py +13 -0
  421. streamlit/web/bootstrap.py +463 -0
  422. streamlit/web/cache_storage_manager_config.py +38 -0
  423. streamlit/web/cli.py +465 -0
  424. streamlit/web/server/__init__.py +30 -0
  425. streamlit/web/server/app_discovery.py +422 -0
  426. streamlit/web/server/app_static_file_handler.py +102 -0
  427. streamlit/web/server/authlib_tornado_integration.py +125 -0
  428. streamlit/web/server/bidi_component_request_handler.py +193 -0
  429. streamlit/web/server/browser_websocket_handler.py +341 -0
  430. streamlit/web/server/component_file_utils.py +105 -0
  431. streamlit/web/server/component_request_handler.py +107 -0
  432. streamlit/web/server/media_file_handler.py +148 -0
  433. streamlit/web/server/oauth_authlib_routes.py +314 -0
  434. streamlit/web/server/oidc_mixin.py +138 -0
  435. streamlit/web/server/routes.py +257 -0
  436. streamlit/web/server/server.py +555 -0
  437. streamlit/web/server/server_util.py +235 -0
  438. streamlit/web/server/starlette/__init__.py +23 -0
  439. streamlit/web/server/starlette/starlette_app.py +541 -0
  440. streamlit/web/server/starlette/starlette_app_utils.py +306 -0
  441. streamlit/web/server/starlette/starlette_auth_routes.py +584 -0
  442. streamlit/web/server/starlette/starlette_gzip_middleware.py +121 -0
  443. streamlit/web/server/starlette/starlette_path_security_middleware.py +97 -0
  444. streamlit/web/server/starlette/starlette_routes.py +884 -0
  445. streamlit/web/server/starlette/starlette_server.py +496 -0
  446. streamlit/web/server/starlette/starlette_server_config.py +55 -0
  447. streamlit/web/server/starlette/starlette_static_routes.py +181 -0
  448. streamlit/web/server/starlette/starlette_websocket.py +560 -0
  449. streamlit/web/server/stats_request_handler.py +116 -0
  450. streamlit/web/server/upload_file_request_handler.py +158 -0
  451. streamlit/web/server/websocket_headers.py +56 -0
  452. streamlit_data_editor_plus-0.1.0.dist-info/METADATA +76 -0
  453. streamlit_data_editor_plus-0.1.0.dist-info/RECORD +456 -0
  454. streamlit_data_editor_plus-0.1.0.dist-info/WHEEL +5 -0
  455. streamlit_data_editor_plus-0.1.0.dist-info/entry_points.txt +2 -0
  456. streamlit_data_editor_plus-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,533 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ import threading
19
+ from collections.abc import Callable, ItemsView, Iterator, KeysView, Mapping, ValuesView
20
+ from copy import deepcopy
21
+ from typing import (
22
+ Any,
23
+ Final,
24
+ NoReturn,
25
+ )
26
+
27
+ from blinker import Signal
28
+
29
+ import streamlit.watcher.path_watcher
30
+ from streamlit import config, runtime
31
+ from streamlit.errors import StreamlitMaxRetriesError, StreamlitSecretNotFoundError
32
+ from streamlit.logger import get_logger
33
+
34
+ _LOGGER: Final = get_logger(__name__)
35
+
36
+
37
+ class SecretErrorMessages:
38
+ """SecretErrorMessages stores all error messages we use for secrets to allow customization
39
+ for different environments.
40
+
41
+ For example Streamlit Cloud can customize the message to be different than the open source.
42
+
43
+ For internal use, may change in future releases without notice.
44
+ """
45
+
46
+ def __init__(self) -> None:
47
+ self.missing_attr_message: Callable[[str], str] = lambda attr_name: (
48
+ f'st.secrets has no attribute "{attr_name}". '
49
+ "Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings "
50
+ "on Streamlit Cloud? More info: "
51
+ "https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
52
+ )
53
+ self.missing_key_message: Callable[[str], str] = lambda key: (
54
+ f'st.secrets has no key "{key}". '
55
+ "Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings "
56
+ "on Streamlit Cloud? More info: "
57
+ "https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
58
+ )
59
+ self.no_secrets_found: Callable[[list[str]], str] = lambda file_paths: (
60
+ f"No secrets found. Valid paths for a secrets.toml file or secret directories are: {', '.join(file_paths)}"
61
+ )
62
+ self.error_parsing_file_at_path: Callable[[str, Exception], str] = (
63
+ lambda path, ex: f"Error parsing secrets file at {path}: {ex}"
64
+ )
65
+ self.subfolder_path_is_not_a_folder: Callable[[str], str] = (
66
+ lambda sub_folder_path: (
67
+ f"{sub_folder_path} is not a folder. "
68
+ "To use directory based secrets, mount every secret in a subfolder under the secret directory"
69
+ )
70
+ )
71
+ self.invalid_secret_path: Callable[[str], str] = lambda path: (
72
+ f"Invalid secrets path: {path}: path is not a .toml file or a directory"
73
+ )
74
+
75
+ def set_missing_attr_message(self, message: Callable[[str], str]) -> None:
76
+ """Set the missing attribute error message."""
77
+ self.missing_attr_message = message
78
+
79
+ def set_missing_key_message(self, message: Callable[[str], str]) -> None:
80
+ """Set the missing key error message."""
81
+ self.missing_key_message = message
82
+
83
+ def set_no_secrets_found_message(self, message: Callable[[list[str]], str]) -> None:
84
+ """Set the no secrets found error message."""
85
+ self.no_secrets_found = message
86
+
87
+ def set_error_parsing_file_at_path_message(
88
+ self, message: Callable[[str, Exception], str]
89
+ ) -> None:
90
+ """Set the error parsing file at path error message."""
91
+ self.error_parsing_file_at_path = message
92
+
93
+ def set_subfolder_path_is_not_a_folder_message(
94
+ self, message: Callable[[str], str]
95
+ ) -> None:
96
+ """Set the subfolder path is not a folder error message."""
97
+ self.subfolder_path_is_not_a_folder = message
98
+
99
+ def set_invalid_secret_path_message(self, message: Callable[[str], str]) -> None:
100
+ """Set the invalid secret path error message."""
101
+ self.invalid_secret_path = message
102
+
103
+ def get_missing_attr_message(self, attr_name: str) -> str:
104
+ """Get the missing attribute error message."""
105
+ return self.missing_attr_message(attr_name)
106
+
107
+ def get_missing_key_message(self, key: str) -> str:
108
+ """Get the missing key error message."""
109
+ return self.missing_key_message(key)
110
+
111
+ def get_no_secrets_found_message(self, file_paths: list[str]) -> str:
112
+ """Get the no secrets found error message."""
113
+ return self.no_secrets_found(file_paths)
114
+
115
+ def get_error_parsing_file_at_path_message(self, path: str, ex: Exception) -> str:
116
+ """Get the error parsing file at path error message."""
117
+ return self.error_parsing_file_at_path(path, ex)
118
+
119
+ def get_subfolder_path_is_not_a_folder_message(self, sub_folder_path: str) -> str:
120
+ """Get the subfolder path is not a folder error message."""
121
+ return self.subfolder_path_is_not_a_folder(sub_folder_path)
122
+
123
+ def get_invalid_secret_path_message(self, path: str) -> str:
124
+ """Get the invalid secret path error message."""
125
+ return self.invalid_secret_path(path)
126
+
127
+
128
+ secret_error_messages_singleton: Final = SecretErrorMessages()
129
+
130
+
131
+ def _convert_to_dict(obj: Mapping[str, Any] | AttrDict) -> dict[str, Any]:
132
+ """Convert Mapping or AttrDict objects to dictionaries."""
133
+ if isinstance(obj, AttrDict):
134
+ return obj.to_dict()
135
+ return {k: v.to_dict() if isinstance(v, AttrDict) else v for k, v in obj.items()}
136
+
137
+
138
+ def _missing_attr_error_message(attr_name: str) -> str:
139
+ return secret_error_messages_singleton.get_missing_attr_message(attr_name)
140
+
141
+
142
+ def _missing_key_error_message(key: str) -> str:
143
+ return secret_error_messages_singleton.get_missing_key_message(key)
144
+
145
+
146
+ class AttrDict(Mapping[str, Any]):
147
+ """We use AttrDict to wrap up dictionary values from secrets
148
+ to provide dot access to nested secrets.
149
+ """
150
+
151
+ def __init__(self, value: Mapping[str, Any]) -> None:
152
+ self.__dict__["__nested_secrets__"] = dict(value)
153
+
154
+ @staticmethod
155
+ def _maybe_wrap_in_attr_dict(value: Any) -> Any:
156
+ if not isinstance(value, Mapping):
157
+ return value
158
+ return AttrDict(value)
159
+
160
+ def __len__(self) -> int:
161
+ return len(self.__nested_secrets__)
162
+
163
+ def __iter__(self) -> Iterator[str]:
164
+ return iter(self.__nested_secrets__)
165
+
166
+ def __getitem__(self, key: str) -> Any:
167
+ try:
168
+ value = self.__nested_secrets__[key]
169
+ return self._maybe_wrap_in_attr_dict(value)
170
+ except KeyError:
171
+ raise KeyError(_missing_key_error_message(key))
172
+
173
+ def __getattr__(self, attr_name: str) -> Any:
174
+ try:
175
+ value = self.__nested_secrets__[attr_name]
176
+ return self._maybe_wrap_in_attr_dict(value)
177
+ except KeyError:
178
+ raise AttributeError(_missing_attr_error_message(attr_name))
179
+
180
+ def __repr__(self) -> str:
181
+ return repr(self.__nested_secrets__)
182
+
183
+ def __setitem__(self, key: str, value: Any) -> NoReturn:
184
+ raise TypeError("Secrets does not support item assignment.")
185
+
186
+ def __setattr__(self, key: str, value: Any) -> NoReturn:
187
+ raise TypeError("Secrets does not support attribute assignment.")
188
+
189
+ def to_dict(self) -> dict[str, Any]:
190
+ return deepcopy(self.__nested_secrets__)
191
+
192
+
193
+ class Secrets(Mapping[str, Any]):
194
+ """A dict-like class that stores secrets.
195
+ Parses secrets.toml on-demand. Cannot be externally mutated.
196
+
197
+ Safe to use from multiple threads.
198
+ """
199
+
200
+ def __init__(self) -> None:
201
+ # Our secrets dict.
202
+ self._secrets: Mapping[str, Any] | None = None
203
+ self._lock = threading.RLock()
204
+ self._file_watchers_installed = False
205
+
206
+ self.file_change_listener = Signal(
207
+ doc="Emitted when a `secrets.toml` file has been changed."
208
+ )
209
+
210
+ def load_if_toml_exists(self) -> bool:
211
+ """Load secrets.toml files from disk if they exists. If none exist,
212
+ no exception will be raised. (If a file exists but is malformed,
213
+ an exception *will* be raised.).
214
+
215
+ Returns True if a secrets.toml file was successfully parsed, False otherwise.
216
+
217
+ Thread-safe.
218
+ """
219
+ try:
220
+ self._parse()
221
+
222
+ return True
223
+ except StreamlitSecretNotFoundError:
224
+ # No secrets.toml files exist. That's fine.
225
+ return False
226
+
227
+ def set_suppress_print_error_on_exception(
228
+ self, suppress_print_error_on_exception: bool
229
+ ) -> None:
230
+ """Left in place for compatibility with integrations until integration
231
+ code can be updated.
232
+ """
233
+
234
+ def _reset(self) -> None:
235
+ """Clear the secrets dictionary and remove any secrets that were
236
+ added to os.environ.
237
+
238
+ Thread-safe.
239
+ """
240
+ with self._lock:
241
+ if self._secrets is None:
242
+ return
243
+
244
+ for k, v in self._secrets.items():
245
+ self._maybe_delete_environment_variable(k, v)
246
+ self._secrets = None
247
+
248
+ def _parse_toml_file(self, path: str) -> tuple[Mapping[str, Any], bool]:
249
+ """Parse a TOML file and return the secrets as a dictionary."""
250
+ secrets = {}
251
+ found_secrets_file = False
252
+
253
+ try:
254
+ with open(path, encoding="utf-8") as f:
255
+ secrets_file_str = f.read()
256
+
257
+ found_secrets_file = True
258
+ except FileNotFoundError:
259
+ # the default config for secrets contains two paths. It's likely one of will not have secrets file.
260
+ return {}, False
261
+
262
+ import toml
263
+
264
+ try:
265
+ secrets.update(toml.loads(secrets_file_str))
266
+ except (TypeError, toml.TomlDecodeError) as ex:
267
+ msg = (
268
+ secret_error_messages_singleton.get_error_parsing_file_at_path_message(
269
+ path, ex
270
+ )
271
+ )
272
+ raise StreamlitSecretNotFoundError(msg) from ex
273
+
274
+ return secrets, found_secrets_file
275
+
276
+ def _parse_directory(self, path: str) -> tuple[Mapping[str, Any], bool]:
277
+ """Parse a directory for secrets. Directory style can be used to support Kubernetes secrets that are
278
+ mounted to folders.
279
+
280
+ Example structure:
281
+ - top_level_secret_folder
282
+ - user_pass_secret (folder)
283
+ - username (file), content: myuser
284
+ - password (file), content: mypassword
285
+ - my_plain_secret (folder)
286
+ - regular_secret (file), content: mysecret
287
+
288
+ See: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#create-a-pod-that-has-access-to-the-secret-data-through-a-volume
289
+ And: https://docs.snowflake.com/en/developer-guide/snowpark-container-services/additional-considerations-services-jobs#passing-secrets-in-local-container-files
290
+ """
291
+ secrets: dict[str, Any] = {}
292
+ found_secrets_file = False
293
+
294
+ for dirname in os.listdir(path):
295
+ sub_folder_path = os.path.join(path, dirname)
296
+ if not os.path.isdir(sub_folder_path):
297
+ error_msg = secret_error_messages_singleton.get_subfolder_path_is_not_a_folder_message(
298
+ sub_folder_path
299
+ )
300
+ raise StreamlitSecretNotFoundError(error_msg)
301
+ sub_secrets = {}
302
+
303
+ for filename in os.listdir(sub_folder_path):
304
+ file_path = os.path.join(sub_folder_path, filename)
305
+
306
+ # ignore folders
307
+ if os.path.isdir(file_path):
308
+ continue
309
+
310
+ with open(file_path, encoding="utf-8") as f:
311
+ sub_secrets[filename] = f.read().strip()
312
+ found_secrets_file = True
313
+
314
+ if len(sub_secrets) == 1:
315
+ # if there's just one file, collapse it so it's directly under `dirname`
316
+ secrets[dirname] = sub_secrets[next(iter(sub_secrets.keys()))]
317
+ else:
318
+ secrets[dirname] = sub_secrets
319
+
320
+ return secrets, found_secrets_file
321
+
322
+ def _parse_file_path(self, path: str) -> tuple[Mapping[str, Any], bool]:
323
+ if path.endswith(".toml"):
324
+ return self._parse_toml_file(path)
325
+
326
+ if os.path.isdir(path):
327
+ return self._parse_directory(path)
328
+
329
+ error_msg = secret_error_messages_singleton.get_invalid_secret_path_message(
330
+ path
331
+ )
332
+ raise StreamlitSecretNotFoundError(error_msg)
333
+
334
+ def _parse(self) -> Mapping[str, Any]:
335
+ """Parse our secrets.toml files if they're not already parsed.
336
+ This function is safe to call from multiple threads.
337
+
338
+ Parameters
339
+ ----------
340
+ print_exceptions : bool
341
+ If True, then exceptions will be printed with `st.error` before
342
+ being re-raised.
343
+
344
+ Raises
345
+ ------
346
+ StreamlitSecretNotFoundError
347
+ Raised if secrets.toml doesn't exist.
348
+
349
+ """
350
+ # Avoid taking a lock for the common case where secrets are already
351
+ # loaded.
352
+ secrets = self._secrets
353
+ if secrets is not None:
354
+ return secrets
355
+
356
+ with self._lock:
357
+ if self._secrets is not None:
358
+ return self._secrets
359
+
360
+ secrets = {}
361
+
362
+ file_paths = config.get_option("secrets.files")
363
+ found_secrets_file = False
364
+ for path in file_paths:
365
+ path_secrets, found_secrets_file_in_path = self._parse_file_path(path)
366
+ found_secrets_file = found_secrets_file or found_secrets_file_in_path
367
+ secrets.update(path_secrets)
368
+
369
+ if not found_secrets_file:
370
+ error_msg = (
371
+ secret_error_messages_singleton.get_no_secrets_found_message(
372
+ file_paths
373
+ )
374
+ )
375
+ raise StreamlitSecretNotFoundError(error_msg)
376
+
377
+ for k, v in secrets.items():
378
+ self._maybe_set_environment_variable(k, v)
379
+
380
+ self._secrets = secrets
381
+ self._maybe_install_file_watchers()
382
+
383
+ return self._secrets
384
+
385
+ def to_dict(self) -> dict[str, Any]:
386
+ """Converts the secrets store into a nested dictionary, where nested AttrDict objects are
387
+ also converted into dictionaries.
388
+ """
389
+ secrets = self._parse()
390
+ return _convert_to_dict(secrets)
391
+
392
+ @staticmethod
393
+ def _maybe_set_environment_variable(k: Any, v: Any) -> None:
394
+ """Add the given key/value pair to os.environ if the value
395
+ is a string, int, or float.
396
+ """
397
+ value_type = type(v)
398
+ if value_type in {str, int, float}:
399
+ os.environ[k] = str(v)
400
+
401
+ @staticmethod
402
+ def _maybe_delete_environment_variable(k: Any, v: Any) -> None:
403
+ """Remove the given key/value pair from os.environ if the value
404
+ is a string, int, or float.
405
+ """
406
+ value_type = type(v)
407
+ if value_type in {str, int, float} and os.environ.get(k) == v:
408
+ del os.environ[k]
409
+
410
+ def _maybe_install_file_watchers(self) -> None:
411
+ with self._lock:
412
+ if self._file_watchers_installed:
413
+ return
414
+
415
+ file_paths = config.get_option("secrets.files")
416
+ for path in file_paths:
417
+ try:
418
+ if path.endswith(".toml"):
419
+ streamlit.watcher.path_watcher.watch_file(
420
+ path,
421
+ self._on_secrets_changed,
422
+ watcher_type="poll",
423
+ )
424
+ else:
425
+ streamlit.watcher.path_watcher.watch_dir(
426
+ path,
427
+ self._on_secrets_changed,
428
+ watcher_type="poll",
429
+ )
430
+ except (StreamlitMaxRetriesError, FileNotFoundError): # noqa: PERF203
431
+ # A user may only have one secrets.toml file defined, so we'd expect
432
+ # exceptions to be raised here when attempting to install a
433
+ # watcher on the nonexistent ones.
434
+ pass
435
+
436
+ # We set file_watchers_installed to True even if the installation attempt
437
+ # failed to avoid repeatedly trying to install it.
438
+ self._file_watchers_installed = True
439
+
440
+ def _on_secrets_changed(self, changed_file_path: str) -> None:
441
+ with self._lock:
442
+ _LOGGER.debug("Secret path %s changed, reloading", changed_file_path)
443
+ self._reset()
444
+ self._parse()
445
+
446
+ # Emit a signal to notify receivers that the `secrets.toml` file
447
+ # has been changed.
448
+ self.file_change_listener.send()
449
+
450
+ def __getattr__(self, key: str) -> Any:
451
+ """Return the value with the given key. If no such key
452
+ exists, raise an AttributeError.
453
+
454
+ Thread-safe.
455
+ """
456
+ try:
457
+ value = self._parse()[key]
458
+ if not isinstance(value, Mapping):
459
+ return value
460
+ return AttrDict(value)
461
+ # We add FileNotFoundError since __getattr__ is expected to only raise
462
+ # AttributeError and mocking utilities expect that contract.
463
+ except (KeyError, FileNotFoundError):
464
+ raise AttributeError(_missing_attr_error_message(key))
465
+
466
+ def __getitem__(self, key: str) -> Any:
467
+ """Return the value with the given key. If no such key
468
+ exists, raise a KeyError.
469
+
470
+ Thread-safe.
471
+ """
472
+ try:
473
+ value = self._parse()[key]
474
+ if not isinstance(value, Mapping):
475
+ return value
476
+ return AttrDict(value)
477
+ except KeyError:
478
+ raise KeyError(_missing_key_error_message(key))
479
+
480
+ def __setattr__(self, key: str, value: Any) -> None:
481
+ # Allow internal attributes to be set
482
+ if key in {
483
+ "_secrets",
484
+ "_lock",
485
+ "_file_watchers_installed",
486
+ "_suppress_print_error_on_exception",
487
+ "file_change_listener",
488
+ "load_if_toml_exists",
489
+ }:
490
+ super().__setattr__(key, value)
491
+ else:
492
+ raise TypeError("Secrets does not support attribute assignment.")
493
+
494
+ def __repr__(self) -> str:
495
+ # If the runtime is NOT initialized, it is a method call outside
496
+ # the streamlit app, so we avoid reading the secrets file as it may not exist.
497
+ # If the runtime is initialized, display the contents of the file and
498
+ # the file must already exist.
499
+ """A string representation of the contents of the dict. Thread-safe."""
500
+ if not runtime.exists():
501
+ return f"{self.__class__.__name__}"
502
+ return repr(self._parse())
503
+
504
+ def __len__(self) -> int:
505
+ """The number of entries in the dict. Thread-safe."""
506
+ return len(self._parse())
507
+
508
+ def has_key(self, k: str) -> bool:
509
+ """True if the given key is in the dict. Thread-safe."""
510
+ return k in self._parse()
511
+
512
+ def keys(self) -> KeysView[str]:
513
+ """A view of the keys in the dict. Thread-safe."""
514
+ return self._parse().keys()
515
+
516
+ def values(self) -> ValuesView[Any]:
517
+ """A view of the values in the dict. Thread-safe."""
518
+ return self._parse().values()
519
+
520
+ def items(self) -> ItemsView[str, Any]:
521
+ """A view of the key-value items in the dict. Thread-safe."""
522
+ return self._parse().items()
523
+
524
+ def __contains__(self, key: Any) -> bool:
525
+ """True if the given key is in the dict. Thread-safe."""
526
+ return key in self._parse()
527
+
528
+ def __iter__(self) -> Iterator[str]:
529
+ """An iterator over the keys in the dict. Thread-safe."""
530
+ return iter(self._parse())
531
+
532
+
533
+ secrets_singleton: Final = Secrets()