streamlit-nightly 1.42.3.dev20250301__py2.py3-none-any.whl → 1.43.1.dev20250306__py2.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 (98) hide show
  1. streamlit/commands/navigation.py +138 -98
  2. streamlit/components/v1/component_arrow.py +3 -1
  3. streamlit/config.py +33 -11
  4. streamlit/dataframe_util.py +12 -4
  5. streamlit/elements/lib/built_in_chart_utils.py +3 -3
  6. streamlit/elements/lib/pandas_styler_utils.py +4 -4
  7. streamlit/elements/map.py +4 -2
  8. streamlit/elements/media.py +4 -2
  9. streamlit/elements/widgets/button.py +92 -28
  10. streamlit/elements/widgets/data_editor.py +4 -4
  11. streamlit/proto/ClientState_pb2.py +5 -5
  12. streamlit/proto/ClientState_pb2.pyi +7 -2
  13. streamlit/proto/NewSession_pb2.py +16 -16
  14. streamlit/proto/NewSession_pb2.pyi +8 -3
  15. streamlit/runtime/caching/hashing.py +1 -1
  16. streamlit/runtime/context.py +9 -0
  17. streamlit/static/index.html +1 -1
  18. streamlit/static/static/js/{FileDownload.esm.CUiEWbzl.js → FileDownload.esm.D90ZPlvX.js} +1 -1
  19. streamlit/static/static/js/{FileHelper.B6bBsK7b.js → FileHelper.B7wMHnJf.js} +1 -1
  20. streamlit/static/static/js/{FormClearHelper.B_9Ez6vr.js → FormClearHelper.DiTttn8n.js} +1 -1
  21. streamlit/static/static/js/{Hooks.VwVTTUgt.js → Hooks.DlsrQbRk.js} +1 -1
  22. streamlit/static/static/js/{InputInstructions.vmQUtJfB.js → InputInstructions.DABeMich.js} +1 -1
  23. streamlit/static/static/js/{ProgressBar.CrEUq34O.js → ProgressBar.B0_wzszZ.js} +2 -2
  24. streamlit/static/static/js/{RenderInPortalIfExists.uSIUxO87.js → RenderInPortalIfExists.Ct3yXHYV.js} +1 -1
  25. streamlit/static/static/js/{Toolbar.DDSvrD0E.js → Toolbar.BhJd2eBO.js} +1 -1
  26. streamlit/static/static/js/{base-input.JpWAqJ0N.js → base-input.BT0Fve4h.js} +1 -1
  27. streamlit/static/static/js/{checkbox.CWR-VT1j.js → checkbox.DytiXgc4.js} +2 -2
  28. streamlit/static/static/js/{createSuper.HcF5WnqF.js → createSuper.Dey_Nchq.js} +1 -1
  29. streamlit/static/static/js/{data-grid-overlay-editor.DminHUYw.js → data-grid-overlay-editor.DHaS0Xdu.js} +1 -1
  30. streamlit/static/static/js/{downloader._SGckIiV.js → downloader.CpXHg7_L.js} +1 -1
  31. streamlit/static/static/js/{es6.b4hv8be8.js → es6.B12jZN2H.js} +2 -2
  32. streamlit/static/static/js/{iframeResizer.contentWindow.BqakL47H.js → iframeResizer.contentWindow.Dp7IrKgg.js} +1 -1
  33. streamlit/static/static/js/{index.BL2LjKzZ.js → index.3smrX8Wb.js} +1 -1
  34. streamlit/static/static/js/index.6GcOZfbK.js +1 -0
  35. streamlit/static/static/js/index.9aouXH1R.js +1 -0
  36. streamlit/static/static/js/{index.cVjFgmUG.js → index.B0Dq5tyz.js} +1 -1
  37. streamlit/static/static/js/index.B0vUg2Y3.js +1 -0
  38. streamlit/static/static/js/index.BEjwL3_Z.js +1 -0
  39. streamlit/static/static/js/{index.C7GAgXnu.js → index.BFTv_Z_e.js} +1 -1
  40. streamlit/static/static/js/{index.C59Ya3CM.js → index.BWJyhyqF.js} +1 -1
  41. streamlit/static/static/js/{index.Dl9vrclR.js → index.Bb8aDqLI.js} +1 -1
  42. streamlit/static/static/js/{index.Cr9buiVv.js → index.Bd3HEJHM.js} +53 -53
  43. streamlit/static/static/js/index.BpUFb67U.js +1 -0
  44. streamlit/static/static/js/{index.CqU47T61.js → index.BpcIvL5C.js} +135 -170
  45. streamlit/static/static/js/{index.3M6TVRo2.js → index.BtGwo9mt.js} +1 -1
  46. streamlit/static/static/js/{index.D7yQTfz7.js → index.Bx2jHxuL.js} +1 -1
  47. streamlit/static/static/js/{index.Dph-QYbt.js → index.C8NedCpe.js} +2 -2
  48. streamlit/static/static/js/{index.D4vb0WQf.js → index.C8i44-aA.js} +1 -1
  49. streamlit/static/static/js/{index.Dev73dEg.js → index.CCzbz0re.js} +1 -1
  50. streamlit/static/static/js/{index.J3DKPewF.js → index.CKTE0OmI.js} +1 -1
  51. streamlit/static/static/js/{index.CpyxO9i-.js → index.Chro-AQL.js} +1 -1
  52. streamlit/static/static/js/{index.C-MV6qmR.js → index.D1pT2XNV.js} +1 -1
  53. streamlit/static/static/js/{index.CAxOUw_O.js → index.D2zBv6ha.js} +1 -1
  54. streamlit/static/static/js/{index.E5dz2muJ.js → index.D6F98iFW.js} +1 -1
  55. streamlit/static/static/js/{index.D4Nzp4K3.js → index.DDLiQS9D.js} +1 -1
  56. streamlit/static/static/js/{index.Cs86Rh1I.js → index.DVFO4dUf.js} +1 -1
  57. streamlit/static/static/js/index.DcZtLSnI.js +1 -0
  58. streamlit/static/static/js/index.Dnp2nMgW.js +1 -0
  59. streamlit/static/static/js/{index.SYnyLAtV.js → index.DpvAFLbG.js} +1 -1
  60. streamlit/static/static/js/{index.B5U4WHdm.js → index.Jj9qMZu5.js} +1 -1
  61. streamlit/static/static/js/{index.BFysNJg1.js → index.SSx319oy.js} +1 -1
  62. streamlit/static/static/js/{index.B4fN2DMS.js → index.U8Sox-zm.js} +1 -1
  63. streamlit/static/static/js/{index.BV5mA8ty.js → index.VRF0kACr.js} +5 -5
  64. streamlit/static/static/js/{index.BLVbwbeW.js → index.d4FK8xGd.js} +2 -2
  65. streamlit/static/static/js/index.ep0QJQk3.js +203 -0
  66. streamlit/static/static/js/index.f0VnAfoO.js +1 -0
  67. streamlit/static/static/js/index.l49xBSOh.js +73 -0
  68. streamlit/static/static/js/{index.Cb8hCZyO.js → index.v5B-faMq.js} +1 -1
  69. streamlit/static/static/js/{index.BgLbohq1.js → index.ydk_VgsB.js} +1 -1
  70. streamlit/static/static/js/{input.Dfd0mQ2M.js → input.D6h4j3mu.js} +2 -2
  71. streamlit/static/static/js/{memory.DFfwDfdX.js → memory.BE4D3Ruc.js} +1 -1
  72. streamlit/static/static/js/{mergeWith.B3E2fSKt.js → mergeWith.CfZBFCuT.js} +1 -1
  73. streamlit/static/static/js/{number-overlay-editor.DG8NE_c_.js → number-overlay-editor.BGuXja4w.js} +1 -1
  74. streamlit/static/static/js/{possibleConstructorReturn.CJ1f9cWL.js → possibleConstructorReturn.GfM_znXN.js} +1 -1
  75. streamlit/static/static/js/{sandbox.-T0hcQrx.js → sandbox.SNug_eHS.js} +1 -1
  76. streamlit/static/static/js/{textarea.CCPaMMRd.js → textarea.C9gOMijs.js} +2 -2
  77. streamlit/static/static/js/{timepicker.BrQl1vN-.js → timepicker.DnkicraE.js} +1 -1
  78. streamlit/static/static/js/{toConsumableArray.UwlRgC7o.js → toConsumableArray.CwiePuJG.js} +1 -1
  79. streamlit/static/static/js/{uniqueId.C5B1A1oI.js → uniqueId.BzT4v6M6.js} +1 -1
  80. streamlit/static/static/js/{useBasicWidgetState.Czrslgva.js → useBasicWidgetState.DKA7kWgD.js} +1 -1
  81. streamlit/static/static/js/{useOnInputChange.Dw8zLgsb.js → useOnInputChange.mkVXolML.js} +1 -1
  82. streamlit/static/static/js/{withFullScreenWrapper.t6HIFyK0.js → withFullScreenWrapper.CfWBIrsM.js} +1 -1
  83. {streamlit_nightly-1.42.3.dev20250301.dist-info → streamlit_nightly-1.43.1.dev20250306.dist-info}/METADATA +1 -1
  84. {streamlit_nightly-1.42.3.dev20250301.dist-info → streamlit_nightly-1.43.1.dev20250306.dist-info}/RECORD +88 -88
  85. streamlit/static/static/js/index.BVLYWr2w.js +0 -1
  86. streamlit/static/static/js/index.BWfK_Obw.js +0 -203
  87. streamlit/static/static/js/index.BXSIv1Yj.js +0 -1
  88. streamlit/static/static/js/index.BhVVEe37.js +0 -1
  89. streamlit/static/static/js/index.BkDOb1MH.js +0 -73
  90. streamlit/static/static/js/index.C2ti2ux-.js +0 -1
  91. streamlit/static/static/js/index.CA_X6A4G.js +0 -1
  92. streamlit/static/static/js/index.CpN57BL8.js +0 -1
  93. streamlit/static/static/js/index.D6kHe3jN.js +0 -1
  94. streamlit/static/static/js/index._Q_M1OIX.js +0 -1
  95. {streamlit_nightly-1.42.3.dev20250301.data → streamlit_nightly-1.43.1.dev20250306.data}/scripts/streamlit.cmd +0 -0
  96. {streamlit_nightly-1.42.3.dev20250301.dist-info → streamlit_nightly-1.43.1.dev20250306.dist-info}/WHEEL +0 -0
  97. {streamlit_nightly-1.42.3.dev20250301.dist-info → streamlit_nightly-1.43.1.dev20250306.dist-info}/entry_points.txt +0 -0
  98. {streamlit_nightly-1.42.3.dev20250301.dist-info → streamlit_nightly-1.43.1.dev20250306.dist-info}/top_level.txt +0 -0
@@ -88,132 +88,172 @@ def navigation(
88
88
  """
89
89
  Configure the available pages in a multipage app.
90
90
 
91
- Call ``st.navigation`` in your entrypoint file to define the structure and navigation
92
- of your multipage application. The function accepts pages defined as file paths,
93
- callable functions, or StreamlitPage objects. It returns the current page, which
94
- can be executed using the ``.run()`` method.
95
-
96
- When using ``st.navigation``, your entrypoint file acts as a router or frame
97
- containing common elements for all pages. Streamlit executes the entrypoint file
98
- with every app rerun. To execute the current page, call the ``.run()`` method on
91
+ Call ``st.navigation`` in your entrypoint file to define the available
92
+ pages for your app. ``st.navigation`` returns the current page, which can
93
+ be executed using ``.run()`` method.
94
+
95
+ When using ``st.navigation``, your entrypoint file (the file passed to
96
+ ``streamlit run``) acts like a router or frame of common elements around
97
+ each of your pages. Streamlit executes the entrypoint file with every app
98
+ rerun. To execute the current page, you must call the ``.run()`` method on
99
99
  the ``StreamlitPage`` object returned by ``st.navigation``.
100
100
 
101
- The set of available pages can be dynamically updated with each rerun.
102
- By default, the navigation menu appears in the sidebar if there is more than
103
- one page. This behavior can be modified using the ``position`` parameter.
101
+ The set of available pages can be updated with each rerun for dynamic
102
+ navigation. By default, ``st.navigation`` displays the available pages in
103
+ the sidebar if there is more than one page. This behavior can be changed
104
+ using the ``position`` keyword argument.
104
105
 
105
- Note: When any session of your app executes ``st.navigation``, the app will
106
- ignore the ``pages/`` directory across all sessions.
106
+ As soon as any session of your app executes the ``st.navigation`` command,
107
+ your app will ignore the ``pages/`` directory (across all sessions).
107
108
 
108
109
  Parameters
109
110
  ----------
110
- pages : Union[List[Union[str, Path, Callable, StreamlitPage]], Dict[str, List[Union[str, Path, Callable, StreamlitPage]]]]
111
- The available pages for the app. Can be specified in several ways:
112
-
113
- As a list:
114
- - List of file paths as strings or Path objects (e.g., ["page1.py", Path("page2.py")])
115
- - List of callable functions (e.g., [page1_func, page2_func])
116
- - List of StreamlitPage objects (e.g., [st.Page("page1.py"), st.Page(page2_func)])
117
- - Mixed list of the above types
118
-
119
- As a dictionary for grouped sections:
120
- - Keys are section labels
121
- - Values are lists containing any combination of the above types
122
-
123
- Example dictionary:
124
- {
125
- "Section 1": ["page1.py", Path("page2.py"), page3_func],
126
- "Section 2": [st.Page("page3.py")]
127
- }
111
+ pages : list[page-like], dict[str, list[page-like]]
112
+ The available pages for the app.
113
+
114
+ To create a navigation menu with no sections or page groupings,
115
+ ``pages`` must be a list of page-like objects. Page-like objects are
116
+ anything that can be passed to ``st.Page`` or a ``StreamlitPage``
117
+ object returned by ``st.Page``.
118
+
119
+ To create labeled sections or page groupings within the navigation
120
+ menu, ``pages`` must be a dictionary. Each key is the label of a
121
+ section and each value is the list of page-like objects for
122
+ that section.
123
+
124
+ When you use a string or path as a page-like object, they are
125
+ internally passed to ``st.Page`` and converted to ``StreamlitPage``
126
+ objects. In this case, the page will have the default title, icon, and
127
+ path inferred from its path or filename. To customize these attributes
128
+ for your page, initialize your page with ``st.Page``.
129
+
130
+ position : "sidebar" or "hidden"
131
+ The position of the navigation menu. If this is ``"sidebar"``
132
+ (default), the navigation widget appears at the top of the sidebar. If
133
+ this is ``"hidden"``, the navigation widget is not displayed.
128
134
 
129
- position : Literal["sidebar", "hidden"]
130
- Controls the navigation menu position:
131
- - "sidebar" (default): Places the navigation at the top of the sidebar
132
- - "hidden": Hides the navigation widget
133
- Note: Navigation is always hidden when there's only one page.
135
+ If there is only one page in ``pages``, the navigation will be hidden
136
+ for any value of ``position``.
134
137
 
135
138
  expanded : bool
136
- Controls the navigation menu's expansion state:
137
- - False (default): Menu starts collapsed with a "more" button
138
- - True: Menu stays permanently expanded
139
- Note: When changing from True to False, the menu remains expanded
140
- but displays a collapse button.
139
+ Whether the navigation menu should be expanded. If this is ``False``
140
+ (default), the navigation menu will be collapsed and will include a
141
+ button to view more options when there are too many pages to display.
142
+ If this is ``True``, the navigation menu will always be expanded; no
143
+ button to collapse the menu will be displayed.
144
+
145
+ If ``st.navigation`` changes from ``expanded=True`` to
146
+ ``expanded=False`` on a rerun, the menu will stay expanded and a
147
+ collapse button will be displayed.
141
148
 
142
149
  Returns
143
150
  -------
144
151
  StreamlitPage
145
- The currently selected page object that can be executed with .run()
152
+ The current page selected by the user. To run the page, you must use
153
+ the ``.run()`` method on it.
146
154
 
147
155
  Examples
148
156
  --------
149
- Basic usage with file paths:
157
+ The following examples show different possible entrypoint files, each named
158
+ ``streamlit_app.py``. An entrypoint file is passed to ``streamlit run``. It
159
+ manages your app's navigation and serves as a router between pages.
160
+
161
+ **Example 1: Use a callable or Python file as a page**
162
+
163
+ You can declare pages from callables or file paths. If you pass callables
164
+ or paths to ``st.navigation`` as a page-like objects, they are internally
165
+ converted to ``StreamlitPage`` objects using ``st.Page``. In this case, the
166
+ page titles, icons, and paths are inferred from the file or callable names.
167
+
168
+ ``page_1.py`` (in the same directory as your entrypoint file):
169
+
170
+ >>> import streamlit as st
171
+ >>>
172
+ >>> st.title("Page 1")
173
+
174
+ ``streamlit_app.py``:
175
+
150
176
  >>> import streamlit as st
151
- >>> pages = ["home.py", "about.py", "contact.py"]
152
- >>> page = st.navigation(pages)
153
- >>> page.run()
154
-
155
- Using functions as pages:
156
- >>> def home():
157
- ... st.title("Home")
158
- >>> def about():
159
- ... st.title("About")
160
177
  >>>
161
- >>> pages = [home, about]
162
- >>> page = st.navigation(pages)
163
- >>> page.run()
178
+ >>> def page_2():
179
+ ... st.title("Page 2")
180
+ >>>
181
+ >>> pg = st.navigation(["page_1.py", page_2])
182
+ >>> pg.run()
183
+
184
+ .. output::
185
+ https://doc-navigation-example-1.streamlit.app/
186
+ height: 200px
187
+
188
+ **Example 2: Group pages into sections and customize them with ``st.Page``**
164
189
 
165
- Mixed usage with sections:
190
+ You can use a dictionary to create sections within your navigation menu. In
191
+ the following example, each page is similar to Page 1 in Example 1, and all
192
+ pages are in the same directory. However, you can use Python files from
193
+ anywhere in your repository. ``st.Page`` is used to give each page a custom
194
+ title. For more information, see |st.Page|_.
195
+
196
+ Directory structure:
197
+
198
+ >>> your_repository/
199
+ >>> ├── create_account.py
200
+ >>> ├── learn.py
201
+ >>> ├── manage_account.py
202
+ >>> ├── streamlit_app.py
203
+ >>> └── trial.py
204
+
205
+ ``streamlit_app.py``:
206
+
207
+ >>> import streamlit as st
208
+ >>>
166
209
  >>> pages = {
167
- ... "Main": ["home.py", about_func],Page
168
- ... "Info": [st.Page("help.py", title="Help Center")],
210
+ ... "Your account": [
211
+ ... st.Page("create_account.py", title="Create your account"),
212
+ ... st.Page("manage_account.py", title="Manage your account"),
213
+ ... ],
214
+ ... "Resources": [
215
+ ... st.Page("learn.py", title="Learn about us"),
216
+ ... st.Page("trial.py", title="Try it out"),
217
+ ... ],
169
218
  ... }
170
- >>> page = st.navigation(pages)
171
- >>> page.run()
219
+ >>>
220
+ >>> pg = st.navigation(pages)
221
+ >>> pg.run()
222
+
223
+ .. output::
224
+ https://doc-navigation-example-2.streamlit.app/
225
+ height: 300px
226
+
227
+ **Example 3: Stateful widgets across multiple pages**
172
228
 
173
- Stateful widgets across pages:
229
+ Call widget functions in your entrypoint file when you want a widget to be
230
+ stateful across pages. Assign keys to your common widgets and access their
231
+ values through Session State within your pages.
232
+
233
+ ``streamlit_app.py``:
234
+
235
+ >>> import streamlit as st
236
+ >>>
174
237
  >>> def page1():
175
- ... st.write(st.session_state.user_name)
238
+ >>> st.write(st.session_state.foo)
239
+ >>>
176
240
  >>> def page2():
177
- ... st.write(st.session_state.user_email)
241
+ >>> st.write(st.session_state.bar)
178
242
  >>>
179
- >>> # Common widgets in entrypoint
180
- >>> st.text_input("Name", key="user_name")
181
- >>> st.text_input("Email", key="user_email")
243
+ >>> # Widgets shared by all the pages
244
+ >>> st.sidebar.selectbox("Foo", ["A", "B", "C"], key="foo")
245
+ >>> st.sidebar.checkbox("Bar", key="bar")
182
246
  >>>
183
- >>> page = st.navigation([page1, page2])
184
- >>> page.run()
247
+ >>> pg = st.navigation([page1, page2])
248
+ >>> pg.run()
185
249
 
186
- Using Path objects:
187
- >>> from pathlib import Path
188
- >>> pages = [Path("home.py"), Path("about.py")]
189
- >>> page = st.navigation(pages)
190
- >>> page.run()
250
+ .. output::
251
+ https://doc-navigation-multipage-widgets.streamlit.app/
252
+ height: 350px
253
+
254
+ .. |st.Page| replace:: ``st.Page``
255
+ .. _st.Page: https://docs.streamlit.io/develop/api-reference/navigation/st.page
191
256
 
192
- Mixed usage with Path and sections:
193
- >>> pages = {
194
- ... "Main": [Path("home.py"), about_func],
195
- ... "Info": [st.Page(Path("help.py"), title="Help Center")],
196
- ... }
197
- >>> page = st.navigation(pages)
198
- >>> page.run()
199
-
200
- Raises
201
- ------
202
- StreamlitAPIException
203
- In the following cases:
204
- - No pages provided
205
- - Multiple pages set as default
206
- - Duplicate URL pathnames
207
- - Invalid page type provided
208
-
209
- Notes
210
- -----
211
- - File paths can be relative or absolute
212
- - Function names are used as default page titles
213
- - URL pathnames must be unique across all pages
214
- - Only one page can be set as default
215
- - The first page is automatically set as default if none specified
216
- - Common widgets should be defined in the entrypoint file for state sharing
217
257
  """
218
258
  # Disable the use of the pages feature (ie disregard v1 behavior of Multipage Apps)
219
259
  PagesManager.uses_pages_directory = False
@@ -135,5 +135,7 @@ def arrow_proto_to_dataframe(proto: ArrowTableProto) -> DataFrame:
135
135
  columns = dataframe_util.convert_arrow_bytes_to_pandas_df(proto.columns)
136
136
 
137
137
  return pd.DataFrame(
138
- data.values, index=index.values.T.tolist(), columns=columns.values.T.tolist()
138
+ data.to_numpy(),
139
+ index=index.to_numpy().T.tolist(),
140
+ columns=columns.to_numpy().T.tolist(),
139
141
  )
streamlit/config.py CHANGED
@@ -469,22 +469,35 @@ def _logger_message_format() -> str:
469
469
  return "%(asctime)s %(message)s"
470
470
 
471
471
 
472
- _create_option(
472
+ @_create_option(
473
473
  "logger.enableRich",
474
- description="""
475
- Controls whether uncaught app exceptions are logged via the rich library.
476
-
477
- If True and if rich is installed, exception tracebacks will be logged with
478
- syntax highlighting and formatting. Rich tracebacks are easier to read and
479
- show more code than standard Python tracebacks.
480
-
481
- If set to False, the default Python traceback formatting will be used.
482
- """,
483
- default_val=False,
484
474
  visibility="hidden",
485
475
  type_=bool,
486
476
  scriptable=True,
487
477
  )
478
+ def _logger_enable_rich() -> bool:
479
+ """
480
+ Controls whether uncaught app exceptions are logged via the rich library.
481
+
482
+ If True and if rich is installed, exception tracebacks will be logged with
483
+ syntax highlighting and formatting. Rich tracebacks are easier to read and
484
+ show more code than standard Python tracebacks.
485
+
486
+ If set to False, the default Python traceback formatting will be used.
487
+
488
+ Defaults to True if rich is installed, False otherwise.
489
+ """
490
+ try:
491
+ import rich # noqa: F401
492
+
493
+ # Rich is importable, activate rich logging.
494
+ return True
495
+ except Exception:
496
+ # We are extra broad in catching exceptions here because we don't want
497
+ # that this causes Streamlit to crash if there is any unexpected
498
+ # exception thrown by the import
499
+ return False
500
+
488
501
 
489
502
  # Config Section: Client #
490
503
 
@@ -1089,6 +1102,15 @@ _create_option(
1089
1102
  visibility="hidden",
1090
1103
  )
1091
1104
 
1105
+ _create_option(
1106
+ "theme.showSidebarSeparator",
1107
+ description="""
1108
+ Whether to show a vertical separator between the sidebar and the main content.
1109
+ """,
1110
+ type_=bool,
1111
+ visibility="hidden",
1112
+ )
1113
+
1092
1114
  # Config Section: Secrets #
1093
1115
 
1094
1116
  _create_section("secrets", "Secrets configuration.")
@@ -67,9 +67,14 @@ _MAX_UNEVALUATED_DF_ROWS = 10000
67
67
 
68
68
  _PANDAS_DATA_OBJECT_TYPE_RE: Final = re.compile(r"^pandas.*$")
69
69
 
70
- _DASK_DATAFRAME: Final = "dask.dataframe.core.DataFrame"
71
- _DASK_INDEX: Final = "dask.dataframe.core.Index"
72
- _DASK_SERIES: Final = "dask.dataframe.core.Series"
70
+ _DASK_DATAFRAME: Final = "dask.dataframe.dask_expr._collection.DataFrame"
71
+ _DASK_SERIES: Final = "dask.dataframe.dask_expr._collection.Series"
72
+ _DASK_INDEX: Final = "dask.dataframe.dask_expr._collection.Index"
73
+ # Dask removed the old legacy types, to support older and newer versions
74
+ # we are still supporting the old an new types.
75
+ _DASK_DATAFRAME_LEGACY: Final = "dask.dataframe.core.DataFrame"
76
+ _DASK_SERIES_LEGACY: Final = "dask.dataframe.core.Series"
77
+ _DASK_INDEX_LEGACY: Final = "dask.dataframe.core.Index"
73
78
  _DUCKDB_RELATION: Final = "duckdb.duckdb.DuckDBPyRelation"
74
79
  _MODIN_DF_TYPE_STR: Final = "modin.pandas.dataframe.DataFrame"
75
80
  _MODIN_SERIES_TYPE_STR: Final = "modin.pandas.series.Series"
@@ -377,8 +382,11 @@ def is_dask_object(obj: object) -> bool:
377
382
  """True if obj is a Dask DataFrame, Series, or Index."""
378
383
  return (
379
384
  is_type(obj, _DASK_DATAFRAME)
385
+ or is_type(obj, _DASK_DATAFRAME_LEGACY)
380
386
  or is_type(obj, _DASK_SERIES)
387
+ or is_type(obj, _DASK_SERIES_LEGACY)
381
388
  or is_type(obj, _DASK_INDEX)
389
+ or is_type(obj, _DASK_INDEX_LEGACY)
382
390
  )
383
391
 
384
392
 
@@ -498,7 +506,7 @@ def _fix_column_naming(data_df: DataFrame) -> DataFrame:
498
506
  # Pandas automatically names the first column with 0 if it is not named.
499
507
  # We rename it to "value" to make it more descriptive if there is only
500
508
  # one column in the dataframe.
501
- data_df.rename(columns={0: "value"}, inplace=True)
509
+ data_df = data_df.rename(columns={0: "value"})
502
510
  return data_df
503
511
 
504
512
 
@@ -567,7 +567,7 @@ def _maybe_reset_index_in_place(
567
567
  x_column = df.index.name
568
568
 
569
569
  df.index.name = x_column
570
- df.reset_index(inplace=True)
570
+ df.reset_index(inplace=True) # noqa: PD002
571
571
 
572
572
  return x_column
573
573
 
@@ -598,7 +598,7 @@ def _maybe_convert_color_column_in_place(df: pd.DataFrame, color_column: str | N
598
598
  if color_column is None or len(df[color_column]) == 0:
599
599
  return
600
600
 
601
- first_color_datum = df[color_column].iat[0]
601
+ first_color_datum = df[color_column].iloc[0]
602
602
 
603
603
  if is_hex_color_like(first_color_datum):
604
604
  # Hex is already CSS-valid.
@@ -988,7 +988,7 @@ def _get_color_encoding(
988
988
 
989
989
  # If the 0th element in the color column looks like a color, we'll use the color column's
990
990
  # values as the colors in our chart.
991
- elif len(df[color_column]) and is_color_like(df[color_column].iat[0]):
991
+ elif len(df[color_column]) and is_color_like(df[color_column].iloc[0]):
992
992
  color_range = [to_css_color(c) for c in df[color_column].unique()]
993
993
  color_enc["scale"] = alt.Scale(range=color_range)
994
994
  # Don't show the color legend, because it will just show text with the color values,
@@ -139,7 +139,7 @@ def _marshall_styles(
139
139
  cellstyle = styles["cellstyle"]
140
140
  cellstyle = _trim_pandas_styles(cellstyle)
141
141
  for style in cellstyle:
142
- rule = _pandas_style_to_css("cell_style", style, styler.uuid)
142
+ rule = _pandas_style_to_css("cell_style", style, styler.uuid, separator="_")
143
143
  css_rules.append(rule)
144
144
 
145
145
  if len(css_rules) > 0:
@@ -168,7 +168,7 @@ def _pandas_style_to_css(
168
168
  style_type: str,
169
169
  style: Mapping[str, Any],
170
170
  uuid: str,
171
- separator: str = "",
171
+ separator: str = "_",
172
172
  ) -> str:
173
173
  """Convert pandas.Styler translated style to CSS.
174
174
 
@@ -189,7 +189,7 @@ def _pandas_style_to_css(
189
189
  """
190
190
  declarations = []
191
191
  for css_property, css_value in style["props"]:
192
- declaration = css_property.strip() + ": " + css_value.strip()
192
+ declaration = str(css_property).strip() + ": " + str(css_value).strip()
193
193
  declarations.append(declaration)
194
194
 
195
195
  table_selector = f"#T_{uuid}"
@@ -269,6 +269,6 @@ def _use_display_values(df: DataFrame, styles: Mapping[str, Any]) -> DataFrame:
269
269
  if "id" in cell:
270
270
  if match := cell_selector_regex.match(cell["id"]):
271
271
  r, c = map(int, match.groups())
272
- new_df.iat[r, c] = str(cell["display_value"])
272
+ new_df.iloc[r, c] = str(cell["display_value"])
273
273
 
274
274
  return new_df
streamlit/elements/map.py CHANGED
@@ -361,7 +361,7 @@ def _get_lat_or_lon_col_name(
361
361
  # (Read about ExtensionArrays here: # https://pandas.pydata.org/community/blog/extension-arrays.html)
362
362
  # However, after a performance test I found the solution below runs basically as
363
363
  # fast as .values.any().
364
- if any(data[col_name].isnull().array):
364
+ if any(data[col_name].isna().array):
365
365
  raise StreamlitAPIException(
366
366
  f"Column {col_name} is not allowed to contain null values, such "
367
367
  "as NaN, NaT, or None."
@@ -421,7 +421,9 @@ def _convert_color_arg_or_column(
421
421
 
422
422
  if color_col_name is not None:
423
423
  # Convert color column to the right format.
424
- if len(data[color_col_name]) > 0 and is_color_like(data[color_col_name].iat[0]):
424
+ if len(data[color_col_name]) > 0 and is_color_like(
425
+ data[color_col_name].iloc[0]
426
+ ):
425
427
  # Use .loc[] to avoid a SettingWithCopyWarning in some cases.
426
428
  data.loc[:, color_col_name] = data.loc[:, color_col_name].map(
427
429
  to_int_color_tuple
@@ -103,7 +103,8 @@ class MediaMixin:
103
103
 
104
104
  format : str
105
105
  The MIME type for the audio file. This defaults to ``"audio/wav"``.
106
- For more information, see https://tools.ietf.org/html/rfc4281.
106
+ For more information about MIME types, see
107
+ https://www.iana.org/assignments/media-types/media-types.xhtml.
107
108
 
108
109
  start_time: int, float, timedelta, str, or None
109
110
  The time from which the element should start playing. This can be
@@ -238,7 +239,8 @@ class MediaMixin:
238
239
 
239
240
  format : str
240
241
  The MIME type for the video file. This defaults to ``"video/mp4"``.
241
- For more information, see https://tools.ietf.org/html/rfc4281.
242
+ For more information about MIME types, see
243
+ https://www.iana.org/assignments/media-types/media-types.xhtml.
242
244
 
243
245
  start_time: int, float, timedelta, str, or None
244
246
  The time from which the element should start playing. This can be
@@ -307,20 +307,31 @@ class ButtonMixin:
307
307
  .. |st.markdown| replace:: ``st.markdown``
308
308
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
309
309
 
310
- data : str or bytes or file
311
- The contents of the file to be downloaded. See example below for
312
- caching techniques to avoid recomputing this data unnecessarily.
310
+ data : str, bytes, or file
311
+ The contents of the file to be downloaded.
312
+
313
+ To prevent unncecessary recomputation, use caching when converting
314
+ your data for download. For more information, see the Example 1
315
+ below.
313
316
 
314
317
  file_name: str
315
318
  An optional string to use as the name of the file to be downloaded,
316
- such as 'my_file.csv'. If not specified, the name will be
319
+ such as ``"my_file.csv"``. If not specified, the name will be
317
320
  automatically generated.
318
321
 
319
322
  mime : str or None
320
- The MIME type of the data. If None, defaults to "text/plain"
321
- (if data is of type *str* or is a textual *file*) or
322
- "application/octet-stream" (if data is of type *bytes* or is a
323
- binary *file*).
323
+ The MIME type of the data. If this is ``None`` (default), Streamlit
324
+ sets the MIME type depending on the value of ``data`` as follows:
325
+
326
+ - If ``data`` is a string or textual file (i.e. ``str`` or
327
+ ``io.TextIOWrapper`` object), Streamlit uses the "text/plain"
328
+ MIME type.
329
+ - If ``data`` is a binary file or bytes (i.e. ``bytes``,
330
+ ``io.BytesIO``, ``io.BufferedReader``, or ``io.RawIOBase``
331
+ object), Streamlit uses the "application/octet-stream" MIME type.
332
+
333
+ For more information about MIME types, see
334
+ https://www.iana.org/assignments/media-types/media-types.xhtml.
324
335
 
325
336
  key : str or int
326
337
  An optional string or integer to use as the unique key for the widget.
@@ -404,45 +415,98 @@ class ButtonMixin:
404
415
 
405
416
  Examples
406
417
  --------
407
- Download a large DataFrame as a CSV:
418
+ **Example 1: Download a dataframe as a CSV file**
419
+
420
+ When working with a large dataframe, it's recommended to fetch your
421
+ data with a cached function. When working with a download button, it's
422
+ similarly recommended to convert your data into a downloadable format
423
+ with a cached function. Caching ensures that the app reruns
424
+ effeciently.
408
425
 
409
426
  >>> import streamlit as st
427
+ >>> import pandas as pd
428
+ >>> import numpy as np
429
+ >>>
430
+ >>> @st.cache_data
431
+ >>> def get_data():
432
+ >>> df = pd.DataFrame(
433
+ ... np.random.randn(50, 20), columns=("col %d" % i for i in range(20))
434
+ ... )
435
+ >>> return df
410
436
  >>>
411
437
  >>> @st.cache_data
412
- ... def convert_df(df):
413
- ... # IMPORTANT: Cache the conversion to prevent computation on every rerun
414
- ... return df.to_csv().encode("utf-8")
438
+ >>> def convert_for_download(df):
439
+ >>> return df.to_csv().encode("utf-8")
415
440
  >>>
416
- >>> csv = convert_df(my_large_df)
441
+ >>> df = get_data()
442
+ >>> csv = convert_for_download(df)
417
443
  >>>
418
444
  >>> st.download_button(
419
- ... label="Download data as CSV",
445
+ ... label="Download CSV",
420
446
  ... data=csv,
421
- ... file_name="large_df.csv",
447
+ ... file_name="data.csv",
422
448
  ... mime="text/csv",
449
+ ... icon=":material/download:",
423
450
  ... )
424
451
 
425
- Download a string as a file:
452
+ .. output::
453
+ https://doc-download-button-csv.streamlit.app/
454
+ height: 200px
426
455
 
427
- >>> import streamlit as st
428
- >>>
429
- >>> text_contents = '''This is some text'''
430
- >>> st.download_button("Download some text", text_contents)
456
+ **Example 2: Download a string as a text file**
457
+
458
+ If you pass a string to the ``data`` argument, Streamlit will
459
+ automatically use the "text/plain" MIME type.
460
+
461
+ When you have a widget (like a text area) affecting the value of your
462
+ download, it's recommended to use another button to prepare the
463
+ download. In this case, use ``on_click="ignore"`` in your download
464
+ button to prevent the download button from rerunning your app. This
465
+ turns the download button into a frontend-only element that can be
466
+ nested in another button.
431
467
 
432
- Download a binary file:
468
+ Without a preparation button, a user can type something into the text
469
+ area and immediately click the download button. Because a download is
470
+ initiated concurrently with the app rerun, this can create a race-like
471
+ condition where the user doesn't see the updated data in their
472
+ download.
473
+
474
+ .. important::
475
+ Even when you prevent your download button from triggering a rerun,
476
+ another widget with a pending change can still trigger a rerun. For
477
+ example, if a text area has a pending change when a user clicks a
478
+ download button, the text area will trigger a rerun.
433
479
 
434
480
  >>> import streamlit as st
435
481
  >>>
436
- >>> binary_contents = b"example content"
437
- >>> # Defaults to "application/octet-stream"
438
- >>> st.download_button("Download binary file", binary_contents)
482
+ >>> message = st.text_area("Message", value="Lorem ipsum.\nStreamlit is cool.")
483
+ >>>
484
+ >>> if st.button("Prepare download"):
485
+ >>> st.download_button(
486
+ ... label="Download text",
487
+ ... data=message,
488
+ ... file_name="message.txt",
489
+ ... on_click="ignore",
490
+ ... type="primary",
491
+ ... icon=":material/download:",
492
+ ... )
493
+
494
+ .. output::
495
+ https://doc-download-button-text.streamlit.app/
496
+ height: 250px
439
497
 
440
- Download an image:
498
+ **Example 3: Download a file**
499
+
500
+ Use a context manager to open and read a local file on your Streamlit
501
+ server. Pass the ``io.BufferedReader`` object directly to ``data``.
502
+ Remember to specify the MIME type if you don't want the default
503
+ type of ``"application/octet-stream"`` for generic binary data. In the
504
+ example below, the MIME type is set to ``"image/png"`` for a PNG file.
441
505
 
442
506
  >>> import streamlit as st
443
507
  >>>
444
508
  >>> with open("flower.png", "rb") as file:
445
- ... btn = st.download_button(
509
+ ... st.download_button(
446
510
  ... label="Download image",
447
511
  ... data=file,
448
512
  ... file_name="flower.png",
@@ -450,8 +514,8 @@ class ButtonMixin:
450
514
  ... )
451
515
 
452
516
  .. output::
453
- https://doc-download-buton.streamlit.app/
454
- height: 335px
517
+ https://doc-download-button-file.streamlit.app/
518
+ height: 200px
455
519
 
456
520
  """
457
521
  ctx = get_script_run_ctx()