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,983 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ from dataclasses import dataclass
19
+ from decimal import Decimal
20
+ from typing import (
21
+ TYPE_CHECKING,
22
+ Any,
23
+ Final,
24
+ Literal,
25
+ TypedDict,
26
+ TypeVar,
27
+ Union,
28
+ cast,
29
+ overload,
30
+ )
31
+
32
+ from typing_extensions import TypeAlias
33
+
34
+ from streamlit import dataframe_util
35
+ from streamlit import logger as _logger
36
+ from streamlit.elements.lib.column_config_utils import (
37
+ INDEX_IDENTIFIER,
38
+ ColumnConfigMapping,
39
+ ColumnConfigMappingInput,
40
+ ColumnDataKind,
41
+ DataframeSchema,
42
+ apply_data_specific_configs,
43
+ determine_dataframe_schema,
44
+ is_type_compatible,
45
+ marshall_column_config,
46
+ process_config_mapping,
47
+ update_column_config,
48
+ )
49
+ from streamlit.elements.lib.form_utils import current_form_id
50
+ from streamlit.elements.lib.pandas_styler_utils import marshall_styler
51
+ from streamlit.elements.lib.policies import check_widget_policies
52
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
53
+ from streamlit.errors import StreamlitAPIException
54
+ from streamlit.proto.Arrow_pb2 import Arrow as ArrowProto
55
+ from streamlit.runtime.metrics_util import gather_metrics
56
+ from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
57
+ from streamlit.runtime.state import (
58
+ WidgetArgs,
59
+ WidgetCallback,
60
+ WidgetKwargs,
61
+ register_widget,
62
+ )
63
+ from streamlit.type_util import is_type
64
+ from streamlit.util import calc_md5
65
+
66
+ if TYPE_CHECKING:
67
+ from collections.abc import Iterable, Mapping
68
+
69
+ import numpy as np
70
+ import pandas as pd
71
+ import pyarrow as pa
72
+ from pandas.io.formats.style import Styler
73
+
74
+ from streamlit.delta_generator import DeltaGenerator
75
+
76
+ _LOGGER: Final = _logger.get_logger(__name__)
77
+
78
+ # All formats that support direct editing, meaning that these
79
+ # formats will be returned with the same type when used with data_editor.
80
+ EditableData = TypeVar(
81
+ "EditableData",
82
+ bound=Union[
83
+ dataframe_util.DataFrameGenericAlias[Any], # covers DataFrame and Series
84
+ tuple[Any],
85
+ list[Any],
86
+ set[Any],
87
+ dict[str, Any],
88
+ # TODO(lukasmasuch): Add support for np.ndarray
89
+ # but it is not possible with np.ndarray.
90
+ # NDArray[Any] works, but is only available in numpy>1.20.
91
+ # TODO(lukasmasuch): Add support for pa.Table typing
92
+ # pa.Table does not work since it is a C-based class resulting in Any
93
+ ],
94
+ )
95
+
96
+
97
+ # All data types supported by the data editor.
98
+ DataTypes: TypeAlias = Union[
99
+ "pd.DataFrame",
100
+ "pd.Series",
101
+ "pd.Index",
102
+ "Styler",
103
+ "pa.Table",
104
+ "np.ndarray[Any, np.dtype[np.float64]]",
105
+ tuple[Any],
106
+ list[Any],
107
+ set[Any],
108
+ dict[str, Any],
109
+ ]
110
+
111
+
112
+ class EditingState(TypedDict, total=False):
113
+ """
114
+ A dictionary representing the current state of the data editor.
115
+
116
+ Attributes
117
+ ----------
118
+ edited_rows : Dict[int, Dict[str, str | int | float | bool | None]]
119
+ An hierarchical mapping of edited cells based on:
120
+ row position -> column name -> value.
121
+
122
+ added_rows : List[Dict[str, str | int | float | bool | None]]
123
+ A list of added rows, where each row is a mapping from column name to
124
+ the cell value.
125
+
126
+ deleted_rows : List[int]
127
+ A list of deleted rows, where each row is the numerical position of
128
+ the deleted row.
129
+ """
130
+
131
+ edited_rows: dict[int, dict[str, str | int | float | bool | None]]
132
+ added_rows: list[dict[str, str | int | float | bool | None]]
133
+ deleted_rows: list[int]
134
+
135
+
136
+ @dataclass
137
+ class DataEditorSerde:
138
+ """DataEditorSerde is used to serialize and deserialize the data editor state."""
139
+
140
+ def deserialize(self, ui_value: str | None, widget_id: str = "") -> EditingState:
141
+ data_editor_state: EditingState = (
142
+ {
143
+ "edited_rows": {},
144
+ "added_rows": [],
145
+ "deleted_rows": [],
146
+ }
147
+ if ui_value is None
148
+ else json.loads(ui_value)
149
+ )
150
+
151
+ # Make sure that all editing state keys are present:
152
+ if "edited_rows" not in data_editor_state:
153
+ data_editor_state["edited_rows"] = {}
154
+
155
+ if "deleted_rows" not in data_editor_state:
156
+ data_editor_state["deleted_rows"] = []
157
+
158
+ if "added_rows" not in data_editor_state:
159
+ data_editor_state["added_rows"] = []
160
+
161
+ # Convert the keys (numerical row positions) to integers.
162
+ # The keys are strings because they are serialized to JSON.
163
+ data_editor_state["edited_rows"] = {
164
+ int(k): v for k, v in data_editor_state["edited_rows"].items()
165
+ }
166
+ return data_editor_state
167
+
168
+ def serialize(self, editing_state: EditingState) -> str:
169
+ return json.dumps(editing_state, default=str)
170
+
171
+
172
+ def _parse_value(
173
+ value: str | int | float | bool | None,
174
+ column_data_kind: ColumnDataKind,
175
+ ) -> Any:
176
+ """Convert a value to the correct type.
177
+
178
+ Parameters
179
+ ----------
180
+ value : str | int | float | bool | None
181
+ The value to convert.
182
+
183
+ column_data_kind : ColumnDataKind
184
+ The determined data kind of the column. The column data kind refers to the
185
+ shared data type of the values in the column (e.g. int, float, str).
186
+
187
+ Returns
188
+ -------
189
+ The converted value.
190
+ """
191
+ if value is None:
192
+ return None
193
+
194
+ import pandas as pd
195
+
196
+ try:
197
+ if column_data_kind == ColumnDataKind.STRING:
198
+ return str(value)
199
+
200
+ if column_data_kind == ColumnDataKind.INTEGER:
201
+ return int(value)
202
+
203
+ if column_data_kind == ColumnDataKind.FLOAT:
204
+ return float(value)
205
+
206
+ if column_data_kind == ColumnDataKind.BOOLEAN:
207
+ return bool(value)
208
+
209
+ if column_data_kind == ColumnDataKind.DECIMAL:
210
+ # Decimal theoretically can also be initialized via number values.
211
+ # However, using number values here seems to cause issues with Arrow
212
+ # serialization, once you try to render the returned dataframe.
213
+ return Decimal(str(value))
214
+
215
+ if column_data_kind == ColumnDataKind.TIMEDELTA:
216
+ return pd.Timedelta(value)
217
+
218
+ if column_data_kind in [
219
+ ColumnDataKind.DATETIME,
220
+ ColumnDataKind.DATE,
221
+ ColumnDataKind.TIME,
222
+ ]:
223
+ datetime_value = pd.Timestamp(value)
224
+
225
+ if datetime_value is pd.NaT:
226
+ return None
227
+
228
+ if column_data_kind == ColumnDataKind.DATETIME:
229
+ return datetime_value
230
+
231
+ if column_data_kind == ColumnDataKind.DATE:
232
+ return datetime_value.date()
233
+
234
+ if column_data_kind == ColumnDataKind.TIME:
235
+ return datetime_value.time()
236
+
237
+ except (ValueError, pd.errors.ParserError) as ex:
238
+ _LOGGER.warning(
239
+ "Failed to parse value %s as %s.",
240
+ value,
241
+ column_data_kind,
242
+ exc_info=ex,
243
+ )
244
+ return None
245
+ return value
246
+
247
+
248
+ def _apply_cell_edits(
249
+ df: pd.DataFrame,
250
+ edited_rows: Mapping[int, Mapping[str, str | int | float | bool | None]],
251
+ dataframe_schema: DataframeSchema,
252
+ ) -> None:
253
+ """Apply cell edits to the provided dataframe (inplace).
254
+
255
+ Parameters
256
+ ----------
257
+ df : pd.DataFrame
258
+ The dataframe to apply the cell edits to.
259
+
260
+ edited_rows : Mapping[int, Mapping[str, str | int | float | bool | None]]
261
+ A hierarchical mapping based on row position -> column name -> value
262
+
263
+ dataframe_schema: DataframeSchema
264
+ The schema of the dataframe.
265
+ """
266
+ for row_id, row_changes in edited_rows.items():
267
+ row_pos = int(row_id)
268
+ for col_name, value in row_changes.items():
269
+ if col_name == INDEX_IDENTIFIER:
270
+ # The edited cell is part of the index
271
+ # TODO(lukasmasuch): To support multi-index in the future:
272
+ # use a tuple of values here instead of a single value
273
+ df.index.to_numpy()[row_pos] = _parse_value(
274
+ value, dataframe_schema[INDEX_IDENTIFIER]
275
+ )
276
+ else:
277
+ col_pos = df.columns.get_loc(col_name)
278
+ df.iloc[row_pos, col_pos] = _parse_value(
279
+ value, dataframe_schema[col_name]
280
+ )
281
+
282
+
283
+ def _apply_row_additions(
284
+ df: pd.DataFrame,
285
+ added_rows: list[dict[str, Any]],
286
+ dataframe_schema: DataframeSchema,
287
+ ) -> None:
288
+ """Apply row additions to the provided dataframe (inplace).
289
+
290
+ Parameters
291
+ ----------
292
+ df : pd.DataFrame
293
+ The dataframe to apply the row additions to.
294
+
295
+ added_rows : List[Dict[str, Any]]
296
+ A list of row additions. Each row addition is a dictionary with the
297
+ column position as key and the new cell value as value.
298
+
299
+ dataframe_schema: DataframeSchema
300
+ The schema of the dataframe.
301
+ """
302
+
303
+ if not added_rows:
304
+ return
305
+
306
+ import pandas as pd
307
+
308
+ # This is only used if the dataframe has a range index:
309
+ # There seems to be a bug in older pandas versions with RangeIndex in
310
+ # combination with loc. As a workaround, we manually track the values here:
311
+ range_index_stop = None
312
+ range_index_step = None
313
+ if isinstance(df.index, pd.RangeIndex):
314
+ range_index_stop = df.index.stop
315
+ range_index_step = df.index.step
316
+
317
+ for added_row in added_rows:
318
+ index_value = None
319
+ new_row: list[Any] = [None for _ in range(df.shape[1])]
320
+ for col_name in added_row.keys():
321
+ value = added_row[col_name]
322
+ if col_name == INDEX_IDENTIFIER:
323
+ # TODO(lukasmasuch): To support multi-index in the future:
324
+ # use a tuple of values here instead of a single value
325
+ index_value = _parse_value(value, dataframe_schema[INDEX_IDENTIFIER])
326
+ else:
327
+ col_pos = df.columns.get_loc(col_name)
328
+ new_row[col_pos] = _parse_value(value, dataframe_schema[col_name])
329
+ # Append the new row to the dataframe
330
+ if range_index_stop is not None:
331
+ df.loc[range_index_stop, :] = new_row
332
+ # Increment to the next range index value
333
+ range_index_stop += range_index_step
334
+ elif index_value is not None:
335
+ # TODO(lukasmasuch): we are only adding rows that have a non-None index
336
+ # value to prevent issues in the frontend component. Also, it just overwrites
337
+ # the row in case the index value already exists in the dataframe.
338
+ # In the future, it would be better to require users to provide unique
339
+ # non-None values for the index with some kind of visual indications.
340
+ df.loc[index_value, :] = new_row
341
+
342
+
343
+ def _apply_row_deletions(df: pd.DataFrame, deleted_rows: list[int]) -> None:
344
+ """Apply row deletions to the provided dataframe (inplace).
345
+
346
+ Parameters
347
+ ----------
348
+ df : pd.DataFrame
349
+ The dataframe to apply the row deletions to.
350
+
351
+ deleted_rows : List[int]
352
+ A list of row numbers to delete.
353
+ """
354
+ # Drop rows based in numeric row positions
355
+ df.drop(df.index[deleted_rows], inplace=True) # noqa: PD002
356
+
357
+
358
+ def _apply_dataframe_edits(
359
+ df: pd.DataFrame,
360
+ data_editor_state: EditingState,
361
+ dataframe_schema: DataframeSchema,
362
+ ) -> None:
363
+ """Apply edits to the provided dataframe (inplace).
364
+
365
+ This includes cell edits, row additions and row deletions.
366
+
367
+ Parameters
368
+ ----------
369
+ df : pd.DataFrame
370
+ The dataframe to apply the edits to.
371
+
372
+ data_editor_state : EditingState
373
+ The editing state of the data editor component.
374
+
375
+ dataframe_schema: DataframeSchema
376
+ The schema of the dataframe.
377
+ """
378
+ if data_editor_state.get("edited_rows"):
379
+ _apply_cell_edits(df, data_editor_state["edited_rows"], dataframe_schema)
380
+
381
+ if data_editor_state.get("deleted_rows"):
382
+ _apply_row_deletions(df, data_editor_state["deleted_rows"])
383
+
384
+ if data_editor_state.get("added_rows"):
385
+ # The addition of new rows needs to happen after the deletion to not have
386
+ # unexpected side-effects, like https://github.com/streamlit/streamlit/issues/8854
387
+ _apply_row_additions(df, data_editor_state["added_rows"], dataframe_schema)
388
+
389
+
390
+ def _is_supported_index(df_index: pd.Index) -> bool:
391
+ """Check if the index is supported by the data editor component.
392
+
393
+ Parameters
394
+ ----------
395
+
396
+ df_index : pd.Index
397
+ The index to check.
398
+
399
+ Returns
400
+ -------
401
+
402
+ bool
403
+ True if the index is supported, False otherwise.
404
+ """
405
+ import pandas as pd
406
+
407
+ return (
408
+ type(df_index)
409
+ in [
410
+ pd.RangeIndex,
411
+ pd.Index,
412
+ pd.DatetimeIndex,
413
+ pd.CategoricalIndex,
414
+ # Interval type isn't editable currently:
415
+ # pd.IntervalIndex,
416
+ # Period type isn't editable currently:
417
+ # pd.PeriodIndex,
418
+ ]
419
+ # We need to check these index types without importing, since they are
420
+ # deprecated and planned to be removed soon.
421
+ or is_type(df_index, "pandas.core.indexes.numeric.Int64Index")
422
+ or is_type(df_index, "pandas.core.indexes.numeric.Float64Index")
423
+ or is_type(df_index, "pandas.core.indexes.numeric.UInt64Index")
424
+ )
425
+
426
+
427
+ def _fix_column_headers(data_df: pd.DataFrame) -> None:
428
+ """Fix the column headers of the provided dataframe inplace to work
429
+ correctly for data editing."""
430
+ import pandas as pd
431
+
432
+ if isinstance(data_df.columns, pd.MultiIndex):
433
+ # Flatten hierarchical column headers to a single level:
434
+ data_df.columns = [
435
+ "_".join(map(str, header)) for header in data_df.columns.to_flat_index()
436
+ ]
437
+ elif pd.api.types.infer_dtype(data_df.columns) != "string":
438
+ # If the column names are not all strings, we need to convert them to strings
439
+ # to avoid issues with editing:
440
+ data_df.rename(
441
+ columns={column: str(column) for column in data_df.columns},
442
+ inplace=True, # noqa: PD002
443
+ )
444
+
445
+
446
+ def _check_column_names(data_df: pd.DataFrame):
447
+ """Check if the column names in the provided dataframe are valid.
448
+
449
+ It's not allowed to have duplicate column names or column names that are
450
+ named ``_index``. If the column names are not valid, a ``StreamlitAPIException``
451
+ is raised.
452
+ """
453
+
454
+ if data_df.columns.empty:
455
+ return
456
+
457
+ # Check if the column names are unique and raise an exception if not.
458
+ # Add the names of the duplicated columns to the exception message.
459
+ duplicated_columns = data_df.columns[data_df.columns.duplicated()]
460
+ if len(duplicated_columns) > 0:
461
+ raise StreamlitAPIException(
462
+ f"All column names are required to be unique for usage with data editor. "
463
+ f"The following column names are duplicated: {list(duplicated_columns)}. "
464
+ f"Please rename the duplicated columns in the provided data."
465
+ )
466
+
467
+ # Check if the column names are not named "_index" and raise an exception if so.
468
+ if INDEX_IDENTIFIER in data_df.columns:
469
+ raise StreamlitAPIException(
470
+ f"The column name '{INDEX_IDENTIFIER}' is reserved for the index column "
471
+ f"and can't be used for data columns. Please rename the column in the "
472
+ f"provided data."
473
+ )
474
+
475
+
476
+ def _check_type_compatibilities(
477
+ data_df: pd.DataFrame,
478
+ columns_config: ColumnConfigMapping,
479
+ dataframe_schema: DataframeSchema,
480
+ ):
481
+ """Check column type to data type compatibility.
482
+
483
+ Iterates the index and all columns of the dataframe to check if
484
+ the configured column types are compatible with the underlying data types.
485
+
486
+ Parameters
487
+ ----------
488
+ data_df : pd.DataFrame
489
+ The dataframe to check the type compatibilities for.
490
+
491
+ columns_config : ColumnConfigMapping
492
+ A mapping of column to column configurations.
493
+
494
+ dataframe_schema : DataframeSchema
495
+ The schema of the dataframe.
496
+
497
+ Raises
498
+ ------
499
+ StreamlitAPIException
500
+ If a configured column type is editable and not compatible with the
501
+ underlying data type.
502
+ """
503
+ # TODO(lukasmasuch): Update this here to support multi-index in the future:
504
+ indices = [(INDEX_IDENTIFIER, data_df.index)]
505
+
506
+ for column in indices + list(data_df.items()):
507
+ column_name, _ = column
508
+ column_data_kind = dataframe_schema[column_name]
509
+
510
+ # TODO(lukasmasuch): support column config via numerical index here?
511
+ if column_name in columns_config:
512
+ column_config = columns_config[column_name]
513
+ if column_config.get("disabled") is True:
514
+ # Disabled columns are not checked for compatibility.
515
+ # This might change in the future.
516
+ continue
517
+
518
+ type_config = column_config.get("type_config")
519
+
520
+ if type_config is None:
521
+ continue
522
+
523
+ configured_column_type = type_config.get("type")
524
+
525
+ if configured_column_type is None:
526
+ continue
527
+
528
+ if is_type_compatible(configured_column_type, column_data_kind) is False:
529
+ raise StreamlitAPIException(
530
+ f"The configured column type `{configured_column_type}` for column "
531
+ f"`{column_name}` is not compatible for editing the underlying "
532
+ f"data type `{column_data_kind}`.\n\nYou have following options to "
533
+ f"fix this: 1) choose a compatible type 2) disable the column "
534
+ f"3) convert the column into a compatible data type."
535
+ )
536
+
537
+
538
+ class DataEditorMixin:
539
+ @overload
540
+ def data_editor(
541
+ self,
542
+ data: EditableData,
543
+ *,
544
+ width: int | None = None,
545
+ height: int | None = None,
546
+ use_container_width: bool | None = None,
547
+ hide_index: bool | None = None,
548
+ column_order: Iterable[str] | None = None,
549
+ column_config: ColumnConfigMappingInput | None = None,
550
+ num_rows: Literal["fixed", "dynamic"] = "fixed",
551
+ disabled: bool | Iterable[str] = False,
552
+ key: Key | None = None,
553
+ on_change: WidgetCallback | None = None,
554
+ args: WidgetArgs | None = None,
555
+ kwargs: WidgetKwargs | None = None,
556
+ row_height: int | None = None,
557
+ ) -> EditableData:
558
+ pass
559
+
560
+ @overload
561
+ def data_editor(
562
+ self,
563
+ data: Any,
564
+ *,
565
+ width: int | None = None,
566
+ height: int | None = None,
567
+ use_container_width: bool | None = None,
568
+ hide_index: bool | None = None,
569
+ column_order: Iterable[str] | None = None,
570
+ column_config: ColumnConfigMappingInput | None = None,
571
+ num_rows: Literal["fixed", "dynamic"] = "fixed",
572
+ disabled: bool | Iterable[str] = False,
573
+ key: Key | None = None,
574
+ on_change: WidgetCallback | None = None,
575
+ args: WidgetArgs | None = None,
576
+ kwargs: WidgetKwargs | None = None,
577
+ row_height: int | None = None,
578
+ ) -> pd.DataFrame:
579
+ pass
580
+
581
+ @gather_metrics("data_editor")
582
+ def data_editor(
583
+ self,
584
+ data: DataTypes,
585
+ *,
586
+ width: int | None = None,
587
+ height: int | None = None,
588
+ use_container_width: bool | None = None,
589
+ hide_index: bool | None = None,
590
+ column_order: Iterable[str] | None = None,
591
+ column_config: ColumnConfigMappingInput | None = None,
592
+ num_rows: Literal["fixed", "dynamic"] = "fixed",
593
+ disabled: bool | Iterable[str] = False,
594
+ key: Key | None = None,
595
+ on_change: WidgetCallback | None = None,
596
+ args: WidgetArgs | None = None,
597
+ kwargs: WidgetKwargs | None = None,
598
+ row_height: int | None = None,
599
+ ) -> DataTypes:
600
+ """Display a data editor widget.
601
+
602
+ The data editor widget allows you to edit dataframes and many other data structures in a table-like UI.
603
+
604
+ Parameters
605
+ ----------
606
+ data : Anything supported by st.dataframe
607
+ The data to edit in the data editor.
608
+
609
+ .. note::
610
+ - Styles from ``pandas.Styler`` will only be applied to non-editable columns.
611
+ - Text and number formatting from ``column_config`` always takes
612
+ precedence over text and number formatting from ``pandas.Styler``.
613
+ - Mixing data types within a column can make the column uneditable.
614
+ - Additionally, the following data types are not yet supported for editing:
615
+ ``complex``, ``list``, ``tuple``, ``bytes``, ``bytearray``,
616
+ ``memoryview``, ``dict``, ``set``, ``frozenset``,
617
+ ``fractions.Fraction``, ``pandas.Interval``, and
618
+ ``pandas.Period``.
619
+ - To prevent overflow in JavaScript, columns containing
620
+ ``datetime.timedelta`` and ``pandas.Timedelta`` values will
621
+ default to uneditable, but this can be changed through column
622
+ configuration.
623
+
624
+ width : int or None
625
+ Desired width of the data editor expressed in pixels. If ``width``
626
+ is ``None`` (default), Streamlit sets the data editor width to fit
627
+ its contents up to the width of the parent container. If ``width``
628
+ is greater than the width of the parent container, Streamlit sets
629
+ the data editor width to match the width of the parent container.
630
+
631
+ height : int or None
632
+ Desired height of the data editor expressed in pixels. If ``height``
633
+ is ``None`` (default), Streamlit sets the height to show at most
634
+ ten rows. Vertical scrolling within the data editor element is
635
+ enabled when the height does not accomodate all rows.
636
+
637
+ use_container_width : bool
638
+ Whether to override ``width`` with the width of the parent
639
+ container. If this is ``True`` (default), Streamlit sets the width
640
+ of the data editor to match the width of the parent container. If
641
+ this is ``False``, Streamlit sets the data editor's width according
642
+ to ``width``.
643
+
644
+ hide_index : bool or None
645
+ Whether to hide the index column(s). If ``hide_index`` is ``None``
646
+ (default), the visibility of index columns is automatically
647
+ determined based on the data.
648
+
649
+ column_order : Iterable of str or None
650
+ Specifies the display order of columns. This also affects which columns are
651
+ visible. For example, ``column_order=("col2", "col1")`` will display 'col2'
652
+ first, followed by 'col1', and will hide all other non-index columns. If
653
+ None (default), the order is inherited from the original data structure.
654
+
655
+ column_config : dict or None
656
+ Configures how columns are displayed, e.g. their title, visibility, type, or
657
+ format, as well as editing properties such as min/max value or step.
658
+ This needs to be a dictionary where each key is a column name and the value
659
+ is one of:
660
+
661
+ - ``None`` to hide the column.
662
+
663
+ - A string to set the display label of the column.
664
+
665
+ - One of the column types defined under ``st.column_config``, e.g.
666
+ ``st.column_config.NumberColumn("Dollar values”, format=”$ %d")`` to show
667
+ a column as dollar amounts. See more info on the available column types
668
+ and config options `here <https://docs.streamlit.io/develop/api-reference/data/st.column_config>`_.
669
+
670
+ To configure the index column(s), use ``_index`` as the column name.
671
+
672
+ num_rows : "fixed" or "dynamic"
673
+ Specifies if the user can add and delete rows in the data editor.
674
+ If "fixed", the user cannot add or delete rows. If "dynamic", the user can
675
+ add and delete rows in the data editor, but column sorting is disabled.
676
+ Defaults to "fixed".
677
+
678
+ disabled : bool or Iterable of str
679
+ Controls the editing of columns. If True, editing is disabled for all columns.
680
+ If an Iterable of column names is provided (e.g., ``disabled=("col1", "col2"))``,
681
+ only the specified columns will be disabled for editing. If False (default),
682
+ all columns that support editing are editable.
683
+
684
+ key : str
685
+ An optional string to use as the unique key for this widget. If this
686
+ is omitted, a key will be generated for the widget based on its
687
+ content. No two widgets may have the same key.
688
+
689
+ on_change : callable
690
+ An optional callback invoked when this data_editor's value changes.
691
+
692
+ args : tuple
693
+ An optional tuple of args to pass to the callback.
694
+
695
+ kwargs : dict
696
+ An optional dict of kwargs to pass to the callback.
697
+
698
+ row_height : int or None
699
+ The height of each row in the data editor in pixels. If ``row_height``
700
+ is ``None`` (default), Streamlit will use a default row height,
701
+ which fits one line of text.
702
+
703
+ Returns
704
+ -------
705
+ pandas.DataFrame, pandas.Series, pyarrow.Table, numpy.ndarray, list, set, tuple, or dict.
706
+ The edited data. The edited data is returned in its original data type if
707
+ it corresponds to any of the supported return types. All other data types
708
+ are returned as a ``pandas.DataFrame``.
709
+
710
+ Examples
711
+ --------
712
+ >>> import streamlit as st
713
+ >>> import pandas as pd
714
+ >>>
715
+ >>> df = pd.DataFrame(
716
+ >>> [
717
+ >>> {"command": "st.selectbox", "rating": 4, "is_widget": True},
718
+ >>> {"command": "st.balloons", "rating": 5, "is_widget": False},
719
+ >>> {"command": "st.time_input", "rating": 3, "is_widget": True},
720
+ >>> ]
721
+ >>> )
722
+ >>> edited_df = st.data_editor(df)
723
+ >>>
724
+ >>> favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
725
+ >>> st.markdown(f"Your favorite command is **{favorite_command}** 🎈")
726
+
727
+ .. output::
728
+ https://doc-data-editor.streamlit.app/
729
+ height: 350px
730
+
731
+ You can also allow the user to add and delete rows by setting ``num_rows`` to "dynamic":
732
+
733
+ >>> import streamlit as st
734
+ >>> import pandas as pd
735
+ >>>
736
+ >>> df = pd.DataFrame(
737
+ >>> [
738
+ >>> {"command": "st.selectbox", "rating": 4, "is_widget": True},
739
+ >>> {"command": "st.balloons", "rating": 5, "is_widget": False},
740
+ >>> {"command": "st.time_input", "rating": 3, "is_widget": True},
741
+ >>> ]
742
+ >>> )
743
+ >>> edited_df = st.data_editor(df, num_rows="dynamic")
744
+ >>>
745
+ >>> favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
746
+ >>> st.markdown(f"Your favorite command is **{favorite_command}** 🎈")
747
+
748
+ .. output::
749
+ https://doc-data-editor1.streamlit.app/
750
+ height: 450px
751
+
752
+ Or you can customize the data editor via ``column_config``, ``hide_index``,
753
+ ``column_order``, or ``disabled``:
754
+
755
+ >>> import pandas as pd
756
+ >>> import streamlit as st
757
+ >>>
758
+ >>> df = pd.DataFrame(
759
+ >>> [
760
+ >>> {"command": "st.selectbox", "rating": 4, "is_widget": True},
761
+ >>> {"command": "st.balloons", "rating": 5, "is_widget": False},
762
+ >>> {"command": "st.time_input", "rating": 3, "is_widget": True},
763
+ >>> ]
764
+ >>> )
765
+ >>> edited_df = st.data_editor(
766
+ >>> df,
767
+ >>> column_config={
768
+ >>> "command": "Streamlit Command",
769
+ >>> "rating": st.column_config.NumberColumn(
770
+ >>> "Your rating",
771
+ >>> help="How much do you like this command (1-5)?",
772
+ >>> min_value=1,
773
+ >>> max_value=5,
774
+ >>> step=1,
775
+ >>> format="%d ⭐",
776
+ >>> ),
777
+ >>> "is_widget": "Widget ?",
778
+ >>> },
779
+ >>> disabled=["command", "is_widget"],
780
+ >>> hide_index=True,
781
+ >>> )
782
+ >>>
783
+ >>> favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
784
+ >>> st.markdown(f"Your favorite command is **{favorite_command}** 🎈")
785
+
786
+
787
+ .. output::
788
+ https://doc-data-editor-config.streamlit.app/
789
+ height: 350px
790
+
791
+ """
792
+ # Lazy-loaded import
793
+ import pandas as pd
794
+ import pyarrow as pa
795
+
796
+ key = to_key(key)
797
+
798
+ check_widget_policies(
799
+ self.dg,
800
+ key,
801
+ on_change,
802
+ default_value=None,
803
+ writes_allowed=False,
804
+ )
805
+
806
+ if column_order is not None:
807
+ column_order = list(column_order)
808
+
809
+ column_config_mapping: ColumnConfigMapping = {}
810
+
811
+ data_format = dataframe_util.determine_data_format(data)
812
+ if data_format == dataframe_util.DataFormat.UNKNOWN:
813
+ raise StreamlitAPIException(
814
+ f"The data type ({type(data).__name__}) or format is not supported by "
815
+ "the data editor. Please convert your data into a Pandas Dataframe or "
816
+ "another supported data format."
817
+ )
818
+
819
+ # The dataframe should always be a copy of the original data
820
+ # since we will apply edits directly to it.
821
+ data_df = dataframe_util.convert_anything_to_pandas_df(data, ensure_copy=True)
822
+
823
+ # Check if the index is supported.
824
+ if not _is_supported_index(data_df.index):
825
+ raise StreamlitAPIException(
826
+ f"The type of the dataframe index - {type(data_df.index).__name__} - is not "
827
+ "yet supported by the data editor."
828
+ )
829
+
830
+ # Check if the column names are valid and unique.
831
+ _check_column_names(data_df)
832
+
833
+ # Convert the user provided column config into the frontend compatible format:
834
+ column_config_mapping = process_config_mapping(column_config)
835
+
836
+ # Deactivate editing for columns that are not compatible with arrow
837
+ for column_name, column_data in data_df.items():
838
+ if dataframe_util.is_colum_type_arrow_incompatible(column_data):
839
+ update_column_config(
840
+ column_config_mapping, column_name, {"disabled": True}
841
+ )
842
+ # Convert incompatible type to string
843
+ data_df[column_name] = column_data.astype("string")
844
+
845
+ apply_data_specific_configs(column_config_mapping, data_format)
846
+
847
+ # Fix the column headers to work correctly for data editing:
848
+ _fix_column_headers(data_df)
849
+
850
+ has_range_index = isinstance(data_df.index, pd.RangeIndex)
851
+
852
+ if not has_range_index:
853
+ # If the index is not a range index, we will configure it as required
854
+ # since the user is required to provide a (unique) value for editing.
855
+ update_column_config(
856
+ column_config_mapping, INDEX_IDENTIFIER, {"required": True}
857
+ )
858
+
859
+ if hide_index is None and has_range_index and num_rows == "dynamic":
860
+ # Temporary workaround:
861
+ # We hide range indices if num_rows is dynamic.
862
+ # since the current way of handling this index during editing is a
863
+ # bit confusing. The user can still decide to show the index by
864
+ # setting hide_index explicitly to False.
865
+ hide_index = True
866
+
867
+ if hide_index is not None:
868
+ update_column_config(
869
+ column_config_mapping, INDEX_IDENTIFIER, {"hidden": hide_index}
870
+ )
871
+
872
+ # If disabled not a boolean, we assume it is a list of columns to disable.
873
+ # This gets translated into the columns configuration:
874
+ if not isinstance(disabled, bool):
875
+ for column in disabled:
876
+ update_column_config(column_config_mapping, column, {"disabled": True})
877
+
878
+ # Convert the dataframe to an arrow table which is used as the main
879
+ # serialization format for sending the data to the frontend.
880
+ # We also utilize the arrow schema to determine the data kinds of every column.
881
+ arrow_table = pa.Table.from_pandas(data_df)
882
+
883
+ # Determine the dataframe schema which is required for parsing edited values
884
+ # and for checking type compatibilities.
885
+ dataframe_schema = determine_dataframe_schema(data_df, arrow_table.schema)
886
+
887
+ # Check if all configured column types are compatible with the underlying data.
888
+ # Throws an exception if any of the configured types are incompatible.
889
+ _check_type_compatibilities(data_df, column_config_mapping, dataframe_schema)
890
+
891
+ arrow_bytes = dataframe_util.convert_arrow_table_to_arrow_bytes(arrow_table)
892
+
893
+ # We want to do this as early as possible to avoid introducing nondeterminism,
894
+ # but it isn't clear how much processing is needed to have the data in a
895
+ # format that will hash consistently, so we do it late here to have it
896
+ # as close as possible to how it used to be.
897
+ ctx = get_script_run_ctx()
898
+ element_id = compute_and_register_element_id(
899
+ "data_editor",
900
+ user_key=key,
901
+ form_id=current_form_id(self.dg),
902
+ data=arrow_bytes,
903
+ width=width,
904
+ height=height,
905
+ use_container_width=use_container_width,
906
+ column_order=column_order,
907
+ column_config_mapping=str(column_config_mapping),
908
+ num_rows=num_rows,
909
+ row_height=row_height,
910
+ )
911
+
912
+ proto = ArrowProto()
913
+ proto.id = element_id
914
+
915
+ if use_container_width is None:
916
+ # If use_container_width was not explicitly set by the user, we set
917
+ # it to True if width was not set explicitly, and False otherwise.
918
+ use_container_width = True if width is None else False
919
+
920
+ proto.use_container_width = use_container_width
921
+
922
+ if width:
923
+ proto.width = width
924
+ if height:
925
+ proto.height = height
926
+
927
+ if row_height:
928
+ proto.row_height = row_height
929
+
930
+ if column_order:
931
+ proto.column_order[:] = column_order
932
+
933
+ # Only set disabled to true if it is actually true
934
+ # It can also be a list of columns, which should result in false here.
935
+ proto.disabled = disabled is True
936
+
937
+ proto.editing_mode = (
938
+ ArrowProto.EditingMode.DYNAMIC
939
+ if num_rows == "dynamic"
940
+ else ArrowProto.EditingMode.FIXED
941
+ )
942
+
943
+ proto.form_id = current_form_id(self.dg)
944
+
945
+ if dataframe_util.is_pandas_styler(data):
946
+ # Pandas styler will only work for non-editable/disabled columns.
947
+ # Get first 10 chars of md5 hash of the key or delta path as styler uuid
948
+ # and set it as styler uuid.
949
+ # We are only using the first 10 chars to keep the uuid short since
950
+ # it will be used for all the cells in the dataframe. Therefore, this
951
+ # might have a significant impact on the message size. 10 chars
952
+ # should be good enough to avoid potential collisions in this case.
953
+ # Even on collisions, there should not be a big issue with the
954
+ # rendering in the data editor.
955
+ styler_uuid = calc_md5(key or self.dg._get_delta_path_str())[:10]
956
+ data.set_uuid(styler_uuid)
957
+ marshall_styler(proto, data, styler_uuid)
958
+
959
+ proto.data = arrow_bytes
960
+
961
+ marshall_column_config(proto, column_config_mapping)
962
+
963
+ serde = DataEditorSerde()
964
+
965
+ widget_state = register_widget(
966
+ proto.id,
967
+ on_change_handler=on_change,
968
+ args=args,
969
+ kwargs=kwargs,
970
+ deserializer=serde.deserialize,
971
+ serializer=serde.serialize,
972
+ ctx=ctx,
973
+ value_type="string_value",
974
+ )
975
+
976
+ _apply_dataframe_edits(data_df, widget_state.value, dataframe_schema)
977
+ self.dg._enqueue("arrow_data_frame", proto)
978
+ return dataframe_util.convert_pandas_df_to_data_format(data_df, data_format)
979
+
980
+ @property
981
+ def dg(self) -> DeltaGenerator:
982
+ """Get our DeltaGenerator."""
983
+ return cast("DeltaGenerator", self)