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,680 @@
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
+ from __future__ import annotations
15
+
16
+ from textwrap import dedent
17
+ from typing import (
18
+ TYPE_CHECKING,
19
+ Any,
20
+ Generic,
21
+ Literal,
22
+ TypeVar,
23
+ cast,
24
+ overload,
25
+ )
26
+
27
+ from typing_extensions import Never
28
+
29
+ from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
30
+ from streamlit.elements.lib.form_utils import current_form_id
31
+ from streamlit.elements.lib.layout_utils import (
32
+ LayoutConfig,
33
+ WidthWithoutContent,
34
+ validate_width,
35
+ )
36
+ from streamlit.elements.lib.options_selector_utils import (
37
+ create_mappings,
38
+ maybe_coerce_enum,
39
+ validate_and_sync_value_with_options,
40
+ )
41
+ from streamlit.elements.lib.policies import (
42
+ check_widget_policies,
43
+ maybe_raise_label_warnings,
44
+ )
45
+ from streamlit.elements.lib.utils import (
46
+ Key,
47
+ LabelVisibility,
48
+ compute_and_register_element_id,
49
+ get_label_visibility_proto_value,
50
+ save_for_app_testing,
51
+ to_key,
52
+ )
53
+ from streamlit.errors import StreamlitAPIException
54
+ from streamlit.proto.Selectbox_pb2 import Selectbox as SelectboxProto
55
+ from streamlit.runtime.metrics_util import gather_metrics
56
+ from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
57
+ from streamlit.runtime.state import (
58
+ BindOption,
59
+ WidgetArgs,
60
+ WidgetCallback,
61
+ WidgetKwargs,
62
+ get_session_state,
63
+ register_widget,
64
+ )
65
+ from streamlit.type_util import (
66
+ check_python_comparable,
67
+ )
68
+
69
+ if TYPE_CHECKING:
70
+ from collections.abc import Callable, Sequence
71
+
72
+ from streamlit.delta_generator import DeltaGenerator
73
+
74
+ T = TypeVar("T")
75
+
76
+
77
+ class SelectboxSerde(Generic[T]):
78
+ options: Sequence[T]
79
+ formatted_options: list[str]
80
+ formatted_option_to_option_index: dict[str, int]
81
+ default_option_index: int | None
82
+ format_func: Callable[[Any], str]
83
+
84
+ def __init__(
85
+ self,
86
+ options: Sequence[T],
87
+ *,
88
+ formatted_options: list[str],
89
+ formatted_option_to_option_index: dict[str, int],
90
+ default_option_index: int | None = None,
91
+ format_func: Callable[[Any], str] = str,
92
+ ) -> None:
93
+ """Initialize the SelectboxSerde.
94
+
95
+ We do not store an option_to_formatted_option mapping because the generic
96
+ options might not be hashable, which would raise a RuntimeError. So we do
97
+ two lookups: option -> index -> formatted_option[index].
98
+
99
+
100
+ Parameters
101
+ ----------
102
+ options : Sequence[T]
103
+ The sequence of selectable options.
104
+ formatted_options : list[str]
105
+ The string representations of each option. The formatted_options correspond
106
+ to the options sequence by index.
107
+ formatted_option_to_option_index : dict[str, int]
108
+ A mapping from formatted option strings to their corresponding indices in
109
+ the options sequence.
110
+ default_option_index : int or None, optional
111
+ The index of the default option to use when no selection is made.
112
+ If None, no default option is selected.
113
+ format_func : Callable[[Any], str], optional
114
+ Function to format options for comparison. Used to compare values by their
115
+ string representation instead of using == directly. This is necessary because
116
+ widget values are deepcopied, and for custom classes without __eq__, the
117
+ deepcopied instances would fail identity comparison.
118
+ """
119
+
120
+ self.options = options
121
+ self.formatted_options = formatted_options
122
+ self.formatted_option_to_option_index = formatted_option_to_option_index
123
+ self.default_option_index = default_option_index
124
+ self.format_func = format_func
125
+
126
+ def serialize(self, v: T | str | None) -> str | None:
127
+ if v is None:
128
+ return None
129
+ # Note: We don't short-circuit for empty options here because
130
+ # accept_new_options=True allows user-entered values even with no options.
131
+ # The normal flow below handles this correctly.
132
+
133
+ # Use format_func to find the formatted option instead of using
134
+ # index_(self.options, v) which relies on == comparison. This is necessary
135
+ # because widget values are deepcopied, and for custom classes without
136
+ # __eq__, the deepcopied instances would fail identity comparison.
137
+ try:
138
+ formatted_value = self.format_func(v)
139
+ except Exception:
140
+ # format_func failed (e.g., v is a string but format_func expects
141
+ # an object with specific attributes). Use str(v) to ensure we return
142
+ # a proper string, not the original object. This handles both cases:
143
+ # - v is already a string -> str(v) returns it unchanged
144
+ # - v is a custom object -> str(v) gives its string representation
145
+ return str(v)
146
+
147
+ if formatted_value in self.formatted_option_to_option_index:
148
+ return formatted_value
149
+ # Value not found in options - return the formatted string (not the original
150
+ # object) to maintain type consistency since serialize() must return str|None
151
+ return formatted_value
152
+
153
+ def deserialize(self, ui_value: str | None) -> T | str | None:
154
+ # Note: We don't short-circuit for empty options here because
155
+ # accept_new_options=True allows user-entered values even with no options.
156
+ # The normal flow below handles this: ui_value not in options -> return ui_value.
157
+
158
+ # Check if the option is pointing to a generic option type T,
159
+ # otherwise return the option itself.
160
+ if ui_value is None:
161
+ return (
162
+ self.options[self.default_option_index]
163
+ if self.default_option_index is not None and len(self.options) > 0
164
+ else None
165
+ )
166
+
167
+ option_index = self.formatted_option_to_option_index.get(ui_value)
168
+ return self.options[option_index] if option_index is not None else ui_value
169
+
170
+
171
+ class SelectboxMixin:
172
+ @overload
173
+ def selectbox(
174
+ self,
175
+ label: str,
176
+ options: Sequence[Never], # Type for empty or Never-inferred options
177
+ index: int = 0,
178
+ format_func: Callable[[Any], str] = str,
179
+ key: Key | None = None,
180
+ help: str | None = None,
181
+ on_change: WidgetCallback | None = None,
182
+ args: WidgetArgs | None = None,
183
+ kwargs: WidgetKwargs | None = None,
184
+ *, # keyword-only arguments:
185
+ placeholder: str | None = None,
186
+ disabled: bool = False,
187
+ label_visibility: LabelVisibility = "visible",
188
+ accept_new_options: Literal[False] = False,
189
+ width: WidthWithoutContent = "stretch",
190
+ bind: BindOption = None,
191
+ ) -> None: ... # Returns None if options is empty and accept_new_options is False
192
+
193
+ @overload
194
+ def selectbox(
195
+ self,
196
+ label: str,
197
+ options: OptionSequence[T],
198
+ index: int = 0,
199
+ format_func: Callable[[Any], str] = str,
200
+ key: Key | None = None,
201
+ help: str | None = None,
202
+ on_change: WidgetCallback | None = None,
203
+ args: WidgetArgs | None = None,
204
+ kwargs: WidgetKwargs | None = None,
205
+ *, # keyword-only arguments:
206
+ placeholder: str | None = None,
207
+ disabled: bool = False,
208
+ label_visibility: LabelVisibility = "visible",
209
+ accept_new_options: Literal[False] = False,
210
+ width: WidthWithoutContent = "stretch",
211
+ bind: BindOption = None,
212
+ ) -> T: ...
213
+
214
+ @overload
215
+ def selectbox(
216
+ self,
217
+ label: str,
218
+ options: OptionSequence[T],
219
+ index: int = 0,
220
+ format_func: Callable[[Any], str] = str,
221
+ key: Key | None = None,
222
+ help: str | None = None,
223
+ on_change: WidgetCallback | None = None,
224
+ args: WidgetArgs | None = None,
225
+ kwargs: WidgetKwargs | None = None,
226
+ *, # keyword-only arguments:
227
+ placeholder: str | None = None,
228
+ disabled: bool = False,
229
+ label_visibility: LabelVisibility = "visible",
230
+ accept_new_options: Literal[True] = True,
231
+ width: WidthWithoutContent = "stretch",
232
+ bind: BindOption = None,
233
+ ) -> T | str: ...
234
+
235
+ @overload
236
+ def selectbox(
237
+ self,
238
+ label: str,
239
+ options: OptionSequence[T],
240
+ index: None,
241
+ format_func: Callable[[Any], str] = str,
242
+ key: Key | None = None,
243
+ help: str | None = None,
244
+ on_change: WidgetCallback | None = None,
245
+ args: WidgetArgs | None = None,
246
+ kwargs: WidgetKwargs | None = None,
247
+ *, # keyword-only arguments:
248
+ placeholder: str | None = None,
249
+ disabled: bool = False,
250
+ label_visibility: LabelVisibility = "visible",
251
+ accept_new_options: Literal[False] = False,
252
+ width: WidthWithoutContent = "stretch",
253
+ bind: BindOption = None,
254
+ ) -> T | None: ...
255
+
256
+ @overload
257
+ def selectbox(
258
+ self,
259
+ label: str,
260
+ options: OptionSequence[T],
261
+ index: None,
262
+ format_func: Callable[[Any], str] = str,
263
+ key: Key | None = None,
264
+ help: str | None = None,
265
+ on_change: WidgetCallback | None = None,
266
+ args: WidgetArgs | None = None,
267
+ kwargs: WidgetKwargs | None = None,
268
+ *, # keyword-only arguments:
269
+ placeholder: str | None = None,
270
+ disabled: bool = False,
271
+ label_visibility: LabelVisibility = "visible",
272
+ accept_new_options: Literal[True] = True,
273
+ width: WidthWithoutContent = "stretch",
274
+ bind: BindOption = None,
275
+ ) -> T | str | None: ...
276
+
277
+ @overload
278
+ def selectbox(
279
+ self,
280
+ label: str,
281
+ options: OptionSequence[T],
282
+ index: int | None = 0,
283
+ format_func: Callable[[Any], str] = str,
284
+ key: Key | None = None,
285
+ help: str | None = None,
286
+ on_change: WidgetCallback | None = None,
287
+ args: WidgetArgs | None = None,
288
+ kwargs: WidgetKwargs | None = None,
289
+ *, # keyword-only arguments:
290
+ placeholder: str | None = None,
291
+ disabled: bool = False,
292
+ label_visibility: LabelVisibility = "visible",
293
+ accept_new_options: bool = False,
294
+ width: WidthWithoutContent = "stretch",
295
+ bind: BindOption = None,
296
+ ) -> T | str | None: ...
297
+
298
+ @gather_metrics("selectbox")
299
+ def selectbox(
300
+ self,
301
+ label: str,
302
+ options: OptionSequence[T],
303
+ index: int | None = 0,
304
+ format_func: Callable[[Any], str] = str,
305
+ key: Key | None = None,
306
+ help: str | None = None,
307
+ on_change: WidgetCallback | None = None,
308
+ args: WidgetArgs | None = None,
309
+ kwargs: WidgetKwargs | None = None,
310
+ *, # keyword-only arguments:
311
+ placeholder: str | None = None,
312
+ disabled: bool = False,
313
+ label_visibility: LabelVisibility = "visible",
314
+ accept_new_options: bool = False,
315
+ width: WidthWithoutContent = "stretch",
316
+ bind: BindOption = None,
317
+ ) -> T | str | None:
318
+ r"""Display a select widget.
319
+
320
+ Parameters
321
+ ----------
322
+ label : str
323
+ A short label explaining to the user what this select widget is for.
324
+ The label can optionally contain GitHub-flavored Markdown of the
325
+ following types: Bold, Italics, Strikethroughs, Inline Code, Links,
326
+ and Images. Images display like icons, with a max height equal to
327
+ the font height.
328
+
329
+ Unsupported Markdown elements are unwrapped so only their children
330
+ (text contents) render. Display unsupported elements as literal
331
+ characters by backslash-escaping them. E.g.,
332
+ ``"1\. Not an ordered list"``.
333
+
334
+ See the ``body`` parameter of |st.markdown|_ for additional,
335
+ supported Markdown directives.
336
+
337
+ For accessibility reasons, you should never set an empty label, but
338
+ you can hide it with ``label_visibility`` if needed. In the future,
339
+ we may disallow empty labels by raising an exception.
340
+
341
+ .. |st.markdown| replace:: ``st.markdown``
342
+ .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
343
+
344
+ options : Iterable
345
+ Labels for the select options in an ``Iterable``. This can be a
346
+ ``list``, ``set``, or anything supported by ``st.dataframe``. If
347
+ ``options`` is dataframe-like, the first column will be used. Each
348
+ label will be cast to ``str`` internally by default.
349
+
350
+ index : int or None
351
+ The index of the preselected option on first render. If ``None``,
352
+ will initialize empty and return ``None`` until the user selects an option.
353
+ Defaults to 0 (the first option).
354
+
355
+ format_func : function
356
+ Function to modify the display of the options. It receives
357
+ the raw option as an argument and should output the label to be
358
+ shown for that option. This has no impact on the return value of
359
+ the command.
360
+
361
+ key : str or int
362
+ An optional string or integer to use as the unique key for the widget.
363
+ If this is omitted, a key will be generated for the widget
364
+ based on its content. No two widgets may have the same key.
365
+
366
+ help : str or None
367
+ A tooltip that gets displayed next to the widget label. Streamlit
368
+ only displays the tooltip when ``label_visibility="visible"``. If
369
+ this is ``None`` (default), no tooltip is displayed.
370
+
371
+ The tooltip can optionally contain GitHub-flavored Markdown,
372
+ including the Markdown directives described in the ``body``
373
+ parameter of ``st.markdown``.
374
+
375
+ on_change : callable
376
+ An optional callback invoked when this selectbox's value changes.
377
+
378
+ args : list or tuple
379
+ An optional list or tuple of args to pass to the callback.
380
+
381
+ kwargs : dict
382
+ An optional dict of kwargs to pass to the callback.
383
+
384
+ placeholder : str or None
385
+ A string to display when no options are selected.
386
+ If this is ``None`` (default), the widget displays placeholder text
387
+ based on the widget's configuration:
388
+
389
+ - "Choose an option" is displayed when options are available and
390
+ ``accept_new_options=False``.
391
+ - "Choose or add an option" is displayed when options are available
392
+ and ``accept_new_options=True``.
393
+ - "Add an option" is displayed when no options are available and
394
+ ``accept_new_options=True``.
395
+ - "No options to select" is displayed when no options are available
396
+ and ``accept_new_options=False``. The widget is also disabled in
397
+ this case.
398
+
399
+ disabled : bool
400
+ An optional boolean that disables the selectbox if set to ``True``.
401
+ The default is ``False``.
402
+
403
+ label_visibility : "visible", "hidden", or "collapsed"
404
+ The visibility of the label. The default is ``"visible"``. If this
405
+ is ``"hidden"``, Streamlit displays an empty spacer instead of the
406
+ label, which can help keep the widget aligned with other widgets.
407
+ If this is ``"collapsed"``, Streamlit displays no label or spacer.
408
+
409
+ accept_new_options : bool
410
+ Whether the user can add a selection that isn't included in ``options``.
411
+ If this is ``False`` (default), the user can only select from the
412
+ items in ``options``. If this is ``True``, the user can enter a new
413
+ item that doesn't exist in ``options``.
414
+
415
+ When a user enters a new item, it is returned by the widget as a
416
+ string. The new item is not added to the widget's drop-down menu.
417
+ Streamlit will use a case-insensitive match from ``options`` before
418
+ adding a new item.
419
+
420
+ width : "stretch" or int
421
+ The width of the selectbox widget. This can be one of the
422
+ following:
423
+
424
+ - ``"stretch"`` (default): The width of the widget matches the
425
+ width of the parent container.
426
+ - An integer specifying the width in pixels: The widget has a
427
+ fixed width. If the specified width is greater than the width of
428
+ the parent container, the width of the widget matches the width
429
+ of the parent container.
430
+
431
+ bind : "query-params" or None
432
+ Enables two-way binding between the widget value and the URL
433
+ query string. When set to ``"query-params"``, the widget's
434
+ ``key`` is used as the URL parameter name. Requires ``key``
435
+ to be set. The URL displays the formatted option string
436
+ (e.g., ``?color=Red``). Invalid URL values are reset to the
437
+ default option and removed from the URL.
438
+
439
+ Returns
440
+ -------
441
+ any
442
+ The selected option or ``None`` if no option is selected.
443
+
444
+ This is a copy of the selected option, not the original.
445
+
446
+ Examples
447
+ --------
448
+ **Example 1: Use a basic selectbox widget**
449
+
450
+ If no index is provided, the first option is selected by default.
451
+
452
+ >>> import streamlit as st
453
+ >>>
454
+ >>> option = st.selectbox(
455
+ ... "How would you like to be contacted?",
456
+ ... ("Email", "Home phone", "Mobile phone"),
457
+ ... )
458
+ >>>
459
+ >>> st.write("You selected:", option)
460
+
461
+ .. output::
462
+ https://doc-selectbox.streamlit.app/
463
+ height: 320px
464
+
465
+ **Example 2: Use a selectbox widget with no initial selection**
466
+
467
+ To initialize an empty selectbox, use ``None`` as the index value.
468
+
469
+ >>> import streamlit as st
470
+ >>>
471
+ >>> option = st.selectbox(
472
+ ... "How would you like to be contacted?",
473
+ ... ("Email", "Home phone", "Mobile phone"),
474
+ ... index=None,
475
+ ... placeholder="Select contact method...",
476
+ ... )
477
+ >>>
478
+ >>> st.write("You selected:", option)
479
+
480
+ .. output::
481
+ https://doc-selectbox-empty.streamlit.app/
482
+ height: 320px
483
+
484
+ **Example 3: Let users add a new option**
485
+
486
+ To allow users to add a new option that isn't included in the
487
+ ``options`` list, use the ``accept_new_options=True`` parameter. You
488
+ can also customize the placeholder text.
489
+
490
+ >>> import streamlit as st
491
+ >>>
492
+ >>> option = st.selectbox(
493
+ ... "Default email",
494
+ ... ["foo@example.com", "bar@example.com", "baz@example.com"],
495
+ ... index=None,
496
+ ... placeholder="Select a saved email or enter a new one",
497
+ ... accept_new_options=True,
498
+ ... )
499
+ >>>
500
+ >>> st.write("You selected:", option)
501
+
502
+ .. output::
503
+ https://doc-selectbox-accept-new-options.streamlit.app/
504
+ height: 320px
505
+
506
+ """
507
+ ctx = get_script_run_ctx()
508
+ return self._selectbox(
509
+ label=label,
510
+ options=options,
511
+ index=index,
512
+ format_func=format_func,
513
+ key=key,
514
+ help=help,
515
+ on_change=on_change,
516
+ args=args,
517
+ kwargs=kwargs,
518
+ placeholder=placeholder,
519
+ disabled=disabled,
520
+ label_visibility=label_visibility,
521
+ accept_new_options=accept_new_options,
522
+ width=width,
523
+ bind=bind,
524
+ ctx=ctx,
525
+ )
526
+
527
+ def _selectbox(
528
+ self,
529
+ label: str,
530
+ options: OptionSequence[T],
531
+ index: int | None = 0,
532
+ format_func: Callable[[Any], Any] = str,
533
+ key: Key | None = None,
534
+ help: str | None = None,
535
+ on_change: WidgetCallback | None = None,
536
+ args: WidgetArgs | None = None,
537
+ kwargs: WidgetKwargs | None = None,
538
+ *, # keyword-only arguments:
539
+ placeholder: str | None = None,
540
+ disabled: bool = False,
541
+ label_visibility: LabelVisibility = "visible",
542
+ accept_new_options: bool = False,
543
+ width: WidthWithoutContent = "stretch",
544
+ bind: BindOption = None,
545
+ ctx: ScriptRunContext | None = None,
546
+ ) -> T | str | None:
547
+ key = to_key(key)
548
+
549
+ check_widget_policies(
550
+ self.dg,
551
+ key,
552
+ on_change,
553
+ default_value=None if index == 0 else index,
554
+ )
555
+ maybe_raise_label_warnings(label, label_visibility)
556
+
557
+ opt = convert_anything_to_list(options)
558
+ check_python_comparable(opt)
559
+
560
+ if not isinstance(index, int) and index is not None:
561
+ raise StreamlitAPIException(
562
+ f"Selectbox Value has invalid type: {type(index).__name__}"
563
+ )
564
+
565
+ if index is not None and len(opt) > 0 and not 0 <= index < len(opt):
566
+ raise StreamlitAPIException(
567
+ "Selectbox index must be greater than or equal to 0 "
568
+ "and less than the length of options."
569
+ )
570
+
571
+ # Convert empty string to single space to distinguish from None:
572
+ # - None (default) → "" → Frontend shows contextual placeholders
573
+ # - "" (explicit empty) → " " → Frontend shows empty placeholder
574
+ # - "Custom" → "Custom" → Frontend shows custom placeholder
575
+ if placeholder == "":
576
+ placeholder = " "
577
+
578
+ formatted_options, formatted_option_to_option_index = create_mappings(
579
+ opt, format_func
580
+ )
581
+
582
+ element_id = compute_and_register_element_id(
583
+ "selectbox",
584
+ user_key=key,
585
+ # Treat the provided key as the main identity. Only include
586
+ # accept_new_options in the identity computation as it
587
+ # can invalidate the current selection and complex to support.
588
+ key_as_main_identity={"accept_new_options"},
589
+ dg=self.dg,
590
+ label=label,
591
+ options=formatted_options,
592
+ index=index,
593
+ help=help,
594
+ placeholder=placeholder,
595
+ accept_new_options=accept_new_options,
596
+ width=width,
597
+ )
598
+
599
+ session_state = get_session_state().filtered_state
600
+ if key is not None and key in session_state and session_state[key] is None:
601
+ index = None
602
+
603
+ selectbox_proto = SelectboxProto()
604
+ selectbox_proto.id = element_id
605
+ selectbox_proto.label = label
606
+ if index is not None:
607
+ selectbox_proto.default = index
608
+ selectbox_proto.options[:] = formatted_options
609
+ selectbox_proto.form_id = current_form_id(self.dg)
610
+ selectbox_proto.placeholder = placeholder or ""
611
+ selectbox_proto.disabled = disabled
612
+ selectbox_proto.label_visibility.value = get_label_visibility_proto_value(
613
+ label_visibility
614
+ )
615
+ selectbox_proto.accept_new_options = accept_new_options
616
+
617
+ if help is not None:
618
+ selectbox_proto.help = dedent(help)
619
+
620
+ # Set query param key if bound
621
+ if bind == "query-params" and key is not None:
622
+ selectbox_proto.query_param_key = str(key)
623
+
624
+ serde = SelectboxSerde(
625
+ opt,
626
+ formatted_options=formatted_options,
627
+ formatted_option_to_option_index=formatted_option_to_option_index,
628
+ default_option_index=index,
629
+ format_func=format_func,
630
+ )
631
+ widget_state = register_widget(
632
+ selectbox_proto.id,
633
+ on_change_handler=on_change,
634
+ args=args,
635
+ kwargs=kwargs,
636
+ deserializer=serde.deserialize,
637
+ serializer=serde.serialize,
638
+ ctx=ctx,
639
+ value_type="string_value",
640
+ bind=bind,
641
+ # Clearable when index=None: the widget can be in an empty state,
642
+ # so ?key= (empty URL param) should clear the widget to None.
643
+ clearable=(index is None),
644
+ # Pass formatted_options so _seed_widget_from_url can reject
645
+ # invalid option strings from URLs. Not passed when
646
+ # accept_new_options=True since any string is valid.
647
+ formatted_options=None if accept_new_options else formatted_options,
648
+ )
649
+ widget_state = maybe_coerce_enum(widget_state, options, opt)
650
+
651
+ if accept_new_options:
652
+ current_value = widget_state.value
653
+ value_needs_reset = False
654
+ else:
655
+ # Validate the current value against the new options.
656
+ # If the value is no longer valid (not in options), reset to default.
657
+ # This handles the case where options change dynamically and the
658
+ # previously selected value is no longer available.
659
+ current_value, value_needs_reset = validate_and_sync_value_with_options(
660
+ widget_state.value, opt, index, key, format_func
661
+ )
662
+
663
+ if value_needs_reset or widget_state.value_changed:
664
+ serialized_value = serde.serialize(current_value)
665
+ if serialized_value is not None:
666
+ selectbox_proto.raw_value = serialized_value
667
+ selectbox_proto.set_value = True
668
+
669
+ validate_width(width)
670
+ layout_config = LayoutConfig(width=width)
671
+
672
+ if ctx:
673
+ save_for_app_testing(ctx, element_id, format_func)
674
+ self.dg._enqueue("selectbox", selectbox_proto, layout_config=layout_config)
675
+ return current_value
676
+
677
+ @property
678
+ def dg(self) -> DeltaGenerator:
679
+ """Get our DeltaGenerator."""
680
+ return cast("DeltaGenerator", self)