streamlit-nightly 1.42.2.dev20250219__py2.py3-none-any.whl → 1.42.3.dev20250221__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.
- streamlit/column_config.py +2 -0
- streamlit/commands/navigation.py +134 -129
- streamlit/elements/lib/column_types.py +88 -0
- streamlit/elements/widgets/button.py +14 -4
- streamlit/navigation/page.py +1 -1
- streamlit/proto/DownloadButton_pb2.py +2 -2
- streamlit/proto/DownloadButton_pb2.pyi +4 -1
- streamlit/runtime/credentials.py +15 -16
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{FileDownload.esm.gA2YL2Ws.js → FileDownload.esm.DuVgDmcS.js} +1 -1
- streamlit/static/static/js/{FileDropzone.CFdsfZRc.js → FileDropzone.BS-xq2Wx.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.CUy5uXTm.js → FormClearHelper.J8fZuqYI.js} +1 -1
- streamlit/static/static/js/{Hooks.DK2XYjwG.js → Hooks.CNPngtZ4.js} +1 -1
- streamlit/static/static/js/{InputInstructions.BliBOyQ3.js → InputInstructions.DxmXu3Kw.js} +1 -1
- streamlit/static/static/js/{ProgressBar.x1Isa69D.js → ProgressBar.CP8g842E.js} +2 -2
- streamlit/static/static/js/{RenderInPortalIfExists.BAeceYUy.js → RenderInPortalIfExists.BmyUtUFH.js} +1 -1
- streamlit/static/static/js/{Toolbar.CT8DybSu.js → Toolbar.Blrz1JFA.js} +1 -1
- streamlit/static/static/js/{base-input.DCz9tkLd.js → base-input.DAIA4gfk.js} +4 -4
- streamlit/static/static/js/{createSuper.C7LhI0EH.js → createSuper.BswKD9F8.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.BCdg4YOG.js → data-grid-overlay-editor.ZgD3BQ2B.js} +1 -1
- streamlit/static/static/js/{downloader.vdos0sUi.js → downloader.inME8iMy.js} +1 -1
- streamlit/static/static/js/{es6.DwFVXqV3.js → es6.dJLzqtYk.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.RYpo13Tx.js → iframeResizer.contentWindow.cu30BTN5.js} +1 -1
- streamlit/static/static/js/{index.C5SUBN7c.js → index.15SsDzez.js} +2 -2
- streamlit/static/static/js/{index.DuxM9Tnh.js → index.8XyAnl0R.js} +1 -1
- streamlit/static/static/js/{index.CpJnG_8d.js → index.B3VXnAul.js} +1 -1
- streamlit/static/static/js/{index.zBfRJuNm.js → index.B6uPGZtQ.js} +1 -1
- streamlit/static/static/js/{index.BZeSmopR.js → index.BEt2OXG5.js} +2 -2
- streamlit/static/static/js/index.BlB7rnTn.js +1 -0
- streamlit/static/static/js/{index.DCnVdrNR.js → index.BpzSSPzO.js} +1 -1
- streamlit/static/static/js/{index.BkCG7aTj.js → index.BsvDo8AN.js} +1 -1
- streamlit/static/static/js/{index.DA71zvn-.js → index.C7zdEYEp.js} +1 -1
- streamlit/static/static/js/{index.DSORXUAZ.js → index.CEppeFo7.js} +3 -3
- streamlit/static/static/js/{index.BGAu9NKr.js → index.COuF5EvL.js} +132 -132
- streamlit/static/static/js/{index.C-qg2uWr.js → index.CSHKQq-E.js} +1 -1
- streamlit/static/static/js/{index.Ya6ZDkVG.js → index.CXN1_deM.js} +2 -2
- streamlit/static/static/js/{index.XBfbnu7R.js → index.CaOtLhyp.js} +1 -1
- streamlit/static/static/js/index.CiQ5wFJ4.js +197 -0
- streamlit/static/static/js/{index.CO-uFT7b.js → index.CkkCzLC4.js} +1 -1
- streamlit/static/static/js/{index.CYAXfbfU.js → index.D0JGWsXt.js} +1 -1
- streamlit/static/static/js/{index.B7_aOrfa.js → index.D3ck1U_t.js} +1 -1
- streamlit/static/static/js/{index.BpjiEyUX.js → index.DCSd7Qvs.js} +1 -1
- streamlit/static/static/js/{index.B6ax18R8.js → index.DKSgHmwp.js} +2 -2
- streamlit/static/static/js/{index.D8iwKK7d.js → index.DOR9yDu0.js} +1 -1
- streamlit/static/static/js/index.DP8260wA.js +1 -0
- streamlit/static/static/js/{index.D0h2TgPB.js → index.DTLj_1B2.js} +1 -1
- streamlit/static/static/js/{index.CYBSRaVx.js → index.DVbJ3S8t.js} +1 -1
- streamlit/static/static/js/{index.DTik05yh.js → index.DYt-QfCo.js} +1 -1
- streamlit/static/static/js/{index.DFovZsvy.js → index.DodktFqu.js} +1 -1
- streamlit/static/static/js/{index.CTtluRFB.js → index.DrBQDoQQ.js} +118 -118
- streamlit/static/static/js/{index.DGog6RGy.js → index.DuUWd9QG.js} +1 -1
- streamlit/static/static/js/{index.rOQjzSJF.js → index.DwtqIbpw.js} +1 -1
- streamlit/static/static/js/{index.C53pKB0j.js → index.DzNuTqK_.js} +1 -1
- streamlit/static/static/js/{index.CaA1VIZR.js → index.FAZrrIPA.js} +1 -1
- streamlit/static/static/js/{index.CP5mPDkY.js → index.FWCmBif3.js} +3 -3
- streamlit/static/static/js/{index.BdXu9OaH.js → index.IxWSvNzu.js} +1 -1
- streamlit/static/static/js/index.R2TOukZ5.js +1 -0
- streamlit/static/static/js/{index.CbM0IQPr.js → index.Uaqj8cqD.js} +1 -1
- streamlit/static/static/js/{index.Dh8M84uS.js → index.eyZOSwoi.js} +1 -1
- streamlit/static/static/js/{index.DTMcwebh.js → index.z1uqruy0.js} +1 -1
- streamlit/static/static/js/{input.DI1DKx6K.js → input.CQjL36Th.js} +2 -2
- streamlit/static/static/js/{memory.Bys8G1q2.js → memory.579OACx4.js} +1 -1
- streamlit/static/static/js/{mergeWith.CQCg1Krv.js → mergeWith.B8KJCMOJ.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.C7xqWB6m.js → number-overlay-editor.Dv1b6l7M.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.CoBITkSn.js → possibleConstructorReturn.CYnI8sYw.js} +1 -1
- streamlit/static/static/js/{sandbox.DhWaUNlZ.js → sandbox.V2eglMiZ.js} +1 -1
- streamlit/static/static/js/{textarea.BBYT1EyU.js → textarea.DpOEcgWS.js} +2 -2
- streamlit/static/static/js/{timepicker.BNm3w13Y.js → timepicker.CVUWU8gJ.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CdvkF-LC.js → toConsumableArray.BuIIwYQO.js} +1 -1
- streamlit/static/static/js/{uniqueId.C4bthDRw.js → uniqueId.DzFqVlA_.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.B8drr2-Z.js → useBasicWidgetState.Clt8VY2K.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.DxZMmV5y.js → useOnInputChange.B7h174Ym.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.KpXeL4S_.js → withFullScreenWrapper.md187TEa.js} +1 -1
- streamlit/web/bootstrap.py +10 -6
- {streamlit_nightly-1.42.2.dev20250219.dist-info → streamlit_nightly-1.42.3.dev20250221.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.42.2.dev20250219.dist-info → streamlit_nightly-1.42.3.dev20250221.dist-info}/RECORD +80 -80
- streamlit/static/static/js/index.C1c-PWwv.js +0 -1
- streamlit/static/static/js/index.C5Vmgs5Q.js +0 -1
- streamlit/static/static/js/index.Dc1YdleN.js +0 -197
- streamlit/static/static/js/index.DgLxA-9p.js +0 -1
- {streamlit_nightly-1.42.2.dev20250219.data → streamlit_nightly-1.42.3.dev20250221.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.42.2.dev20250219.dist-info → streamlit_nightly-1.42.3.dev20250221.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.42.2.dev20250219.dist-info → streamlit_nightly-1.42.3.dev20250221.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.42.2.dev20250219.dist-info → streamlit_nightly-1.42.3.dev20250221.dist-info}/top_level.txt +0 -0
streamlit/column_config.py
CHANGED
@@ -32,6 +32,7 @@ __all__ = [
|
|
32
32
|
"ListColumn",
|
33
33
|
"DateColumn",
|
34
34
|
"TimeColumn",
|
35
|
+
"JsonColumn",
|
35
36
|
]
|
36
37
|
|
37
38
|
|
@@ -43,6 +44,7 @@ from streamlit.elements.lib.column_types import (
|
|
43
44
|
DateColumn,
|
44
45
|
DatetimeColumn,
|
45
46
|
ImageColumn,
|
47
|
+
JsonColumn,
|
46
48
|
LineChartColumn,
|
47
49
|
LinkColumn,
|
48
50
|
ListColumn,
|
streamlit/commands/navigation.py
CHANGED
@@ -15,12 +15,13 @@
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
17
|
from pathlib import Path
|
18
|
-
from typing import TYPE_CHECKING, Literal
|
18
|
+
from typing import TYPE_CHECKING, Callable, Literal
|
19
19
|
|
20
20
|
from typing_extensions import TypeAlias
|
21
21
|
|
22
22
|
from streamlit import config
|
23
23
|
from streamlit.errors import StreamlitAPIException
|
24
|
+
from streamlit.navigation.page import StreamlitPage
|
24
25
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
25
26
|
from streamlit.proto.Navigation_pb2 import Navigation as NavigationProto
|
26
27
|
from streamlit.runtime.metrics_util import gather_metrics
|
@@ -30,12 +31,34 @@ from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
|
30
31
|
)
|
31
32
|
|
32
33
|
if TYPE_CHECKING:
|
33
|
-
from streamlit.navigation.page import StreamlitPage
|
34
34
|
from streamlit.source_util import PageHash, PageInfo
|
35
35
|
|
36
36
|
SectionHeader: TypeAlias = str
|
37
37
|
|
38
38
|
|
39
|
+
def convert_to_streamlit_page(
|
40
|
+
page_input: str | Path | Callable[[], None] | StreamlitPage,
|
41
|
+
) -> StreamlitPage:
|
42
|
+
"""Convert various input types to StreamlitPage objects."""
|
43
|
+
if isinstance(page_input, StreamlitPage):
|
44
|
+
return page_input
|
45
|
+
|
46
|
+
if isinstance(page_input, str):
|
47
|
+
return StreamlitPage(page_input)
|
48
|
+
|
49
|
+
if isinstance(page_input, Path):
|
50
|
+
return StreamlitPage(page_input)
|
51
|
+
|
52
|
+
if callable(page_input):
|
53
|
+
# Convert function to StreamlitPage
|
54
|
+
return StreamlitPage(page_input)
|
55
|
+
|
56
|
+
raise StreamlitAPIException(
|
57
|
+
f"Invalid page type: {type(page_input)}. Must be either a string path, "
|
58
|
+
"a pathlib.Path, a callable function, or a st.Page object."
|
59
|
+
)
|
60
|
+
|
61
|
+
|
39
62
|
def pages_from_nav_sections(
|
40
63
|
nav_sections: dict[SectionHeader, list[StreamlitPage]],
|
41
64
|
) -> list[StreamlitPage]:
|
@@ -55,7 +78,8 @@ def send_page_not_found(ctx: ScriptRunContext):
|
|
55
78
|
|
56
79
|
@gather_metrics("navigation")
|
57
80
|
def navigation(
|
58
|
-
pages: list[
|
81
|
+
pages: list[str | Path | Callable[[], None] | StreamlitPage]
|
82
|
+
| dict[SectionHeader, list[str | Path | Callable[[], None] | StreamlitPage]],
|
59
83
|
*,
|
60
84
|
position: Literal["sidebar", "hidden"] = "sidebar",
|
61
85
|
expanded: bool = False,
|
@@ -63,161 +87,142 @@ def navigation(
|
|
63
87
|
"""
|
64
88
|
Configure the available pages in a multipage app.
|
65
89
|
|
66
|
-
Call ``st.navigation`` in your entrypoint file
|
67
|
-
|
68
|
-
|
90
|
+
Call ``st.navigation`` in your entrypoint file to define the structure and navigation
|
91
|
+
of your multipage application. The function accepts pages defined as file paths,
|
92
|
+
callable functions, or StreamlitPage objects. It returns the current page, which
|
93
|
+
can be executed using the ``.run()`` method.
|
69
94
|
|
70
|
-
When using ``st.navigation``, your entrypoint file
|
71
|
-
|
72
|
-
|
73
|
-
rerun. To execute the current page, you must call the ``.run()`` method on
|
95
|
+
When using ``st.navigation``, your entrypoint file acts as a router or frame
|
96
|
+
containing common elements for all pages. Streamlit executes the entrypoint file
|
97
|
+
with every app rerun. To execute the current page, call the ``.run()`` method on
|
74
98
|
the ``StreamlitPage`` object returned by ``st.navigation``.
|
75
99
|
|
76
|
-
The set of available pages can be updated with each rerun
|
77
|
-
|
78
|
-
|
79
|
-
changed using the ``position`` keyword argument.
|
100
|
+
The set of available pages can be dynamically updated with each rerun.
|
101
|
+
By default, the navigation menu appears in the sidebar if there is more than
|
102
|
+
one page. This behavior can be modified using the ``position`` parameter.
|
80
103
|
|
81
|
-
|
82
|
-
|
104
|
+
Note: When any session of your app executes ``st.navigation``, the app will
|
105
|
+
ignore the ``pages/`` directory across all sessions.
|
83
106
|
|
84
107
|
Parameters
|
85
108
|
----------
|
86
|
-
pages :
|
87
|
-
The available pages for the app.
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
109
|
+
pages : Union[List[Union[str, Path, Callable, StreamlitPage]], Dict[str, List[Union[str, Path, Callable, StreamlitPage]]]]
|
110
|
+
The available pages for the app. Can be specified in several ways:
|
111
|
+
|
112
|
+
As a list:
|
113
|
+
- List of file paths as strings or Path objects (e.g., ["page1.py", Path("page2.py")])
|
114
|
+
- List of callable functions (e.g., [page1_func, page2_func])
|
115
|
+
- List of StreamlitPage objects (e.g., [st.Page("page1.py"), st.Page(page2_func)])
|
116
|
+
- Mixed list of the above types
|
117
|
+
|
118
|
+
As a dictionary for grouped sections:
|
119
|
+
- Keys are section labels
|
120
|
+
- Values are lists containing any combination of the above types
|
121
|
+
|
122
|
+
Example dictionary:
|
123
|
+
{
|
124
|
+
"Section 1": ["page1.py", Path("page2.py"), page3_func],
|
125
|
+
"Section 2": [st.Page("page3.py")]
|
126
|
+
}
|
127
|
+
|
128
|
+
position : Literal["sidebar", "hidden"]
|
129
|
+
Controls the navigation menu position:
|
130
|
+
- "sidebar" (default): Places the navigation at the top of the sidebar
|
131
|
+
- "hidden": Hides the navigation widget
|
132
|
+
Note: Navigation is always hidden when there's only one page.
|
106
133
|
|
107
134
|
expanded : bool
|
108
|
-
|
109
|
-
(default)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
If ``st.navigation`` changes from ``expanded=True`` to
|
115
|
-
``expanded=False`` on a rerun, the menu will stay expanded and a
|
116
|
-
collapse button will be displayed.
|
135
|
+
Controls the navigation menu's expansion state:
|
136
|
+
- False (default): Menu starts collapsed with a "more" button
|
137
|
+
- True: Menu stays permanently expanded
|
138
|
+
Note: When changing from True to False, the menu remains expanded
|
139
|
+
but displays a collapse button.
|
117
140
|
|
118
141
|
Returns
|
119
142
|
-------
|
120
143
|
StreamlitPage
|
121
|
-
The
|
144
|
+
The currently selected page object that can be executed with .run()
|
122
145
|
|
123
146
|
Examples
|
124
147
|
--------
|
125
|
-
|
126
|
-
you pass to ``streamlit run``. Your entrypoint file manages your app's
|
127
|
-
navigation and serves as a router between pages.
|
128
|
-
|
129
|
-
**Example 1: Use a callable or Python file as a page**
|
130
|
-
|
131
|
-
You can declare pages from callables or file paths.
|
132
|
-
|
133
|
-
``page_1.py`` (in the same directory as your entrypoint file):
|
134
|
-
|
148
|
+
Basic usage with file paths:
|
135
149
|
>>> import streamlit as st
|
150
|
+
>>> pages = ["home.py", "about.py", "contact.py"]
|
151
|
+
>>> page = st.navigation(pages)
|
152
|
+
>>> page.run()
|
153
|
+
|
154
|
+
Using functions as pages:
|
155
|
+
>>> def home():
|
156
|
+
... st.title("Home")
|
157
|
+
>>> def about():
|
158
|
+
... st.title("About")
|
136
159
|
>>>
|
137
|
-
>>>
|
138
|
-
|
139
|
-
|
160
|
+
>>> pages = [home, about]
|
161
|
+
>>> page = st.navigation(pages)
|
162
|
+
>>> page.run()
|
140
163
|
|
141
|
-
|
142
|
-
>>>
|
143
|
-
>>> def page_2():
|
144
|
-
... st.title("Page 2")
|
145
|
-
>>>
|
146
|
-
>>> pg = st.navigation([st.Page("page_1.py"), st.Page(page_2)])
|
147
|
-
>>> pg.run()
|
148
|
-
|
149
|
-
.. output::
|
150
|
-
https://doc-navigation-example-1.streamlit.app/
|
151
|
-
height: 200px
|
152
|
-
|
153
|
-
**Example 2: Group pages into sections**
|
154
|
-
|
155
|
-
You can use a dictionary to create sections within your navigation menu. In
|
156
|
-
the following example, each page is similar to Page 1 in Example 1, and all
|
157
|
-
pages are in the same directory. However, you can use Python files from
|
158
|
-
anywhere in your repository. For more information, see |st.Page|_.
|
159
|
-
|
160
|
-
Directory structure:
|
161
|
-
|
162
|
-
>>> your_repository/
|
163
|
-
>>> ├── create_account.py
|
164
|
-
>>> ├── learn.py
|
165
|
-
>>> ├── manage_account.py
|
166
|
-
>>> ├── streamlit_app.py
|
167
|
-
>>> └── trial.py
|
168
|
-
|
169
|
-
``streamlit_app.py``:
|
170
|
-
|
171
|
-
>>> import streamlit as st
|
172
|
-
>>>
|
164
|
+
Mixed usage with sections:
|
173
165
|
>>> pages = {
|
174
|
-
... "
|
175
|
-
...
|
176
|
-
... st.Page("manage_account.py", title="Manage your account"),
|
177
|
-
... ],
|
178
|
-
... "Resources": [
|
179
|
-
... st.Page("learn.py", title="Learn about us"),
|
180
|
-
... st.Page("trial.py", title="Try it out"),
|
181
|
-
... ],
|
166
|
+
... "Main": ["home.py", about_func],Page
|
167
|
+
... "Info": [st.Page("help.py", title="Help Center")],
|
182
168
|
... }
|
183
|
-
>>>
|
184
|
-
>>>
|
185
|
-
>>> pg.run()
|
186
|
-
|
187
|
-
.. output::
|
188
|
-
https://doc-navigation-example-2.streamlit.app/
|
189
|
-
height: 300px
|
169
|
+
>>> page = st.navigation(pages)
|
170
|
+
>>> page.run()
|
190
171
|
|
191
|
-
|
192
|
-
|
193
|
-
Call widget functions in your entrypoint file when you want a widget to be
|
194
|
-
stateful across pages. Assign keys to your common widgets and access their
|
195
|
-
values through Session State within your pages.
|
196
|
-
|
197
|
-
>>> import streamlit as st
|
198
|
-
>>>
|
172
|
+
Stateful widgets across pages:
|
199
173
|
>>> def page1():
|
200
|
-
|
201
|
-
>>>
|
174
|
+
... st.write(st.session_state.user_name)
|
202
175
|
>>> def page2():
|
203
|
-
|
176
|
+
... st.write(st.session_state.user_email)
|
204
177
|
>>>
|
205
|
-
>>> #
|
206
|
-
>>> st.
|
207
|
-
>>> st.
|
178
|
+
>>> # Common widgets in entrypoint
|
179
|
+
>>> st.text_input("Name", key="user_name")
|
180
|
+
>>> st.text_input("Email", key="user_email")
|
208
181
|
>>>
|
209
|
-
>>>
|
210
|
-
>>>
|
182
|
+
>>> page = st.navigation([page1, page2])
|
183
|
+
>>> page.run()
|
211
184
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
.. _st.Page: https://docs.streamlit.io/develop/api-reference/navigation/st.page
|
185
|
+
Using Path objects:
|
186
|
+
>>> from pathlib import Path
|
187
|
+
>>> pages = [Path("home.py"), Path("about.py")]
|
188
|
+
>>> page = st.navigation(pages)
|
189
|
+
>>> page.run()
|
218
190
|
|
191
|
+
Mixed usage with Path and sections:
|
192
|
+
>>> pages = {
|
193
|
+
... "Main": [Path("home.py"), about_func],
|
194
|
+
... "Info": [st.Page(Path("help.py"), title="Help Center")],
|
195
|
+
... }
|
196
|
+
>>> page = st.navigation(pages)
|
197
|
+
>>> page.run()
|
198
|
+
|
199
|
+
Raises
|
200
|
+
------
|
201
|
+
StreamlitAPIException
|
202
|
+
In the following cases:
|
203
|
+
- No pages provided
|
204
|
+
- Multiple pages set as default
|
205
|
+
- Duplicate URL pathnames
|
206
|
+
- Invalid page type provided
|
207
|
+
|
208
|
+
Notes
|
209
|
+
-----
|
210
|
+
- File paths can be relative or absolute
|
211
|
+
- Function names are used as default page titles
|
212
|
+
- URL pathnames must be unique across all pages
|
213
|
+
- Only one page can be set as default
|
214
|
+
- The first page is automatically set as default if none specified
|
215
|
+
- Common widgets should be defined in the entrypoint file for state sharing
|
219
216
|
"""
|
220
|
-
|
217
|
+
if isinstance(pages, list):
|
218
|
+
converted_pages = [convert_to_streamlit_page(p) for p in pages]
|
219
|
+
nav_sections = {"": converted_pages}
|
220
|
+
else:
|
221
|
+
nav_sections = {
|
222
|
+
section: [convert_to_streamlit_page(p) for p in section_pages]
|
223
|
+
for section, section_pages in pages.items()
|
224
|
+
}
|
225
|
+
|
221
226
|
page_list = pages_from_nav_sections(nav_sections)
|
222
227
|
|
223
228
|
if not page_list:
|
@@ -56,6 +56,7 @@ ColumnType: TypeAlias = Literal[
|
|
56
56
|
"area_chart",
|
57
57
|
"image",
|
58
58
|
"progress",
|
59
|
+
"json",
|
59
60
|
]
|
60
61
|
|
61
62
|
|
@@ -149,6 +150,10 @@ class ProgressColumnConfig(TypedDict):
|
|
149
150
|
max_value: NotRequired[int | float | None]
|
150
151
|
|
151
152
|
|
153
|
+
class JsonColumnConfig(TypedDict):
|
154
|
+
type: Literal["json"]
|
155
|
+
|
156
|
+
|
152
157
|
class ColumnConfig(TypedDict, total=False):
|
153
158
|
"""Configuration options for columns in ``st.dataframe`` and ``st.data_editor``.
|
154
159
|
|
@@ -232,6 +237,7 @@ class ColumnConfig(TypedDict, total=False):
|
|
232
237
|
| BarChartColumnConfig
|
233
238
|
| AreaChartColumnConfig
|
234
239
|
| ImageColumnConfig
|
240
|
+
| JsonColumnConfig
|
235
241
|
| None
|
236
242
|
)
|
237
243
|
|
@@ -2067,3 +2073,85 @@ def ProgressColumn(
|
|
2067
2073
|
max_value=max_value,
|
2068
2074
|
),
|
2069
2075
|
)
|
2076
|
+
|
2077
|
+
|
2078
|
+
@gather_metrics("column_config.JsonColumn")
|
2079
|
+
def JsonColumn(
|
2080
|
+
label: str | None = None,
|
2081
|
+
*,
|
2082
|
+
width: ColumnWidth | None = None,
|
2083
|
+
help: str | None = None,
|
2084
|
+
pinned: bool | None = None,
|
2085
|
+
) -> ColumnConfig:
|
2086
|
+
"""Configure a JSON column in ``st.dataframe`` or ``st.data_editor``.
|
2087
|
+
|
2088
|
+
Cells need to contain a JSON string or JSON-compatible objects.
|
2089
|
+
JSON columns are not editable at the moment. This command needs to be used in the
|
2090
|
+
``column_config`` parameter of ``st.dataframe`` or ``st.data_editor``.
|
2091
|
+
|
2092
|
+
Parameters
|
2093
|
+
----------
|
2094
|
+
|
2095
|
+
label: str or None
|
2096
|
+
The label shown at the top of the column. If this is ``None``
|
2097
|
+
(default), the column name is used.
|
2098
|
+
|
2099
|
+
width: "small", "medium", "large", or None
|
2100
|
+
The display width of the column. If this is ``None`` (default), the
|
2101
|
+
column will be sized to fit the cell contents. Otherwise, this can be
|
2102
|
+
one of the following:
|
2103
|
+
|
2104
|
+
- ``"small"``: 75px wide
|
2105
|
+
- ``"medium"``: 200px wide
|
2106
|
+
- ``"large"``: 400px wide
|
2107
|
+
|
2108
|
+
help: str or None
|
2109
|
+
An optional tooltip that gets displayed when hovering over the column
|
2110
|
+
label. If this is ``None`` (default), no tooltip is displayed.
|
2111
|
+
|
2112
|
+
pinned: bool or None
|
2113
|
+
Whether the column is pinned. A pinned column will stay visible on the
|
2114
|
+
left side no matter where the user scrolls. If this is ``None``
|
2115
|
+
(default), Streamlit will decide: index columns are pinned, and data
|
2116
|
+
columns are not pinned.
|
2117
|
+
|
2118
|
+
Examples
|
2119
|
+
--------
|
2120
|
+
|
2121
|
+
>>> import pandas as pd
|
2122
|
+
>>> import streamlit as st
|
2123
|
+
>>>
|
2124
|
+
>>> data_df = pd.DataFrame(
|
2125
|
+
>>> {
|
2126
|
+
>>> "json": [
|
2127
|
+
>>> {"foo": "bar", "bar": "baz"},
|
2128
|
+
>>> {"foo": "baz", "bar": "qux"},
|
2129
|
+
>>> {"foo": "qux", "bar": "foo"},
|
2130
|
+
>>> None,
|
2131
|
+
>>> ],
|
2132
|
+
>>> }
|
2133
|
+
>>> )
|
2134
|
+
>>>
|
2135
|
+
>>> st.dataframe(
|
2136
|
+
>>> data_df,
|
2137
|
+
>>> column_config={
|
2138
|
+
>>> "json": st.column_config.JsonColumn(
|
2139
|
+
>>> "JSON Data",
|
2140
|
+
>>> help="JSON strings or objects",
|
2141
|
+
>>> width="large",
|
2142
|
+
>>> ),
|
2143
|
+
>>> },
|
2144
|
+
>>> hide_index=True,
|
2145
|
+
>>> )
|
2146
|
+
|
2147
|
+
.. output::
|
2148
|
+
https://doc-json-column.streamlit.app/
|
2149
|
+
height: 300px
|
2150
|
+
"""
|
2151
|
+
return ColumnConfig(
|
2152
|
+
label=label,
|
2153
|
+
width=width,
|
2154
|
+
help=help,
|
2155
|
+
pinned=pinned,
|
2156
|
+
type_config=JsonColumnConfig(type="json"),
|
2157
|
+
)
|
@@ -264,7 +264,7 @@ class ButtonMixin:
|
|
264
264
|
mime: str | None = None,
|
265
265
|
key: Key | None = None,
|
266
266
|
help: str | None = None,
|
267
|
-
on_click: WidgetCallback | None =
|
267
|
+
on_click: WidgetCallback | Literal["rerun", "ignore"] | None = "rerun",
|
268
268
|
args: WidgetArgs | None = None,
|
269
269
|
kwargs: WidgetKwargs | None = None,
|
270
270
|
*, # keyword-only arguments:
|
@@ -712,7 +712,7 @@ class ButtonMixin:
|
|
712
712
|
mime: str | None = None,
|
713
713
|
key: Key | None = None,
|
714
714
|
help: str | None = None,
|
715
|
-
on_click: WidgetCallback | None =
|
715
|
+
on_click: WidgetCallback | Literal["rerun", "ignore"] | None = "rerun",
|
716
716
|
args: WidgetArgs | None = None,
|
717
717
|
kwargs: WidgetKwargs | None = None,
|
718
718
|
*, # keyword-only arguments:
|
@@ -724,10 +724,15 @@ class ButtonMixin:
|
|
724
724
|
) -> bool:
|
725
725
|
key = to_key(key)
|
726
726
|
|
727
|
+
if on_click == "ignore" or on_click == "rerun":
|
728
|
+
on_click_callback = None
|
729
|
+
else:
|
730
|
+
on_click_callback = on_click
|
731
|
+
|
727
732
|
check_widget_policies(
|
728
733
|
self.dg,
|
729
734
|
key,
|
730
|
-
|
735
|
+
on_click_callback,
|
731
736
|
default_value=None,
|
732
737
|
writes_allowed=False,
|
733
738
|
)
|
@@ -768,11 +773,16 @@ class ButtonMixin:
|
|
768
773
|
if icon is not None:
|
769
774
|
download_button_proto.icon = validate_icon_or_emoji(icon)
|
770
775
|
|
776
|
+
if on_click == "ignore":
|
777
|
+
download_button_proto.ignore_rerun = True
|
778
|
+
else:
|
779
|
+
download_button_proto.ignore_rerun = False
|
780
|
+
|
771
781
|
serde = ButtonSerde()
|
772
782
|
|
773
783
|
button_state = register_widget(
|
774
784
|
download_button_proto.id,
|
775
|
-
on_change_handler=
|
785
|
+
on_change_handler=on_click_callback,
|
776
786
|
args=args,
|
777
787
|
kwargs=kwargs,
|
778
788
|
deserializer=serde.deserialize,
|
streamlit/navigation/page.py
CHANGED
@@ -34,7 +34,7 @@ def Page(
|
|
34
34
|
icon: str | None = None,
|
35
35
|
url_path: str | None = None,
|
36
36
|
default: bool = False,
|
37
|
-
):
|
37
|
+
) -> StreamlitPage:
|
38
38
|
"""Configure a page for ``st.navigation`` in a multipage app.
|
39
39
|
|
40
40
|
Call ``st.Page`` to initialize a ``StreamlitPage`` object, and pass it to
|
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|
14
14
|
|
15
15
|
|
16
16
|
|
17
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$streamlit/proto/DownloadButton.proto\"\
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$streamlit/proto/DownloadButton.proto\"\xc9\x01\n\x0e\x44ownloadButton\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05label\x18\x02 \x01(\t\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x03 \x01(\x08\x12\x0c\n\x04help\x18\x04 \x01(\t\x12\x0f\n\x07\x66orm_id\x18\x05 \x01(\t\x12\x0b\n\x03url\x18\x06 \x01(\t\x12\x10\n\x08\x64isabled\x18\x07 \x01(\x08\x12\x1b\n\x13use_container_width\x18\x08 \x01(\x08\x12\x0c\n\x04type\x18\t \x01(\t\x12\x0c\n\x04icon\x18\n \x01(\t\x12\x14\n\x0cignore_rerun\x18\x0b \x01(\x08\x42\x33\n\x1c\x63om.snowflake.apps.streamlitB\x13\x44ownloadButtonProtob\x06proto3')
|
18
18
|
|
19
19
|
_globals = globals()
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -23,5 +23,5 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
23
23
|
_globals['DESCRIPTOR']._loaded_options = None
|
24
24
|
_globals['DESCRIPTOR']._serialized_options = b'\n\034com.snowflake.apps.streamlitB\023DownloadButtonProto'
|
25
25
|
_globals['_DOWNLOADBUTTON']._serialized_start=41
|
26
|
-
_globals['_DOWNLOADBUTTON']._serialized_end=
|
26
|
+
_globals['_DOWNLOADBUTTON']._serialized_end=242
|
27
27
|
# @@protoc_insertion_point(module_scope)
|
@@ -38,6 +38,7 @@ class DownloadButton(google.protobuf.message.Message):
|
|
38
38
|
USE_CONTAINER_WIDTH_FIELD_NUMBER: builtins.int
|
39
39
|
TYPE_FIELD_NUMBER: builtins.int
|
40
40
|
ICON_FIELD_NUMBER: builtins.int
|
41
|
+
IGNORE_RERUN_FIELD_NUMBER: builtins.int
|
41
42
|
id: builtins.str
|
42
43
|
label: builtins.str
|
43
44
|
default: builtins.bool
|
@@ -48,6 +49,7 @@ class DownloadButton(google.protobuf.message.Message):
|
|
48
49
|
use_container_width: builtins.bool
|
49
50
|
type: builtins.str
|
50
51
|
icon: builtins.str
|
52
|
+
ignore_rerun: builtins.bool
|
51
53
|
def __init__(
|
52
54
|
self,
|
53
55
|
*,
|
@@ -61,7 +63,8 @@ class DownloadButton(google.protobuf.message.Message):
|
|
61
63
|
use_container_width: builtins.bool = ...,
|
62
64
|
type: builtins.str = ...,
|
63
65
|
icon: builtins.str = ...,
|
66
|
+
ignore_rerun: builtins.bool = ...,
|
64
67
|
) -> None: ...
|
65
|
-
def ClearField(self, field_name: typing.Literal["default", b"default", "disabled", b"disabled", "form_id", b"form_id", "help", b"help", "icon", b"icon", "id", b"id", "label", b"label", "type", b"type", "url", b"url", "use_container_width", b"use_container_width"]) -> None: ...
|
68
|
+
def ClearField(self, field_name: typing.Literal["default", b"default", "disabled", b"disabled", "form_id", b"form_id", "help", b"help", "icon", b"icon", "id", b"id", "ignore_rerun", b"ignore_rerun", "label", b"label", "type", b"type", "url", b"url", "use_container_width", b"use_container_width"]) -> None: ...
|
66
69
|
|
67
70
|
global___DownloadButton = DownloadButton
|
streamlit/runtime/credentials.py
CHANGED
@@ -20,7 +20,6 @@ import json
|
|
20
20
|
import os
|
21
21
|
import sys
|
22
22
|
import textwrap
|
23
|
-
from datetime import datetime, timezone
|
24
23
|
from typing import Final, NamedTuple, NoReturn
|
25
24
|
from uuid import uuid4
|
26
25
|
|
@@ -67,42 +66,42 @@ Collecting usage statistics. To deactivate, set browser.gatherUsageStats to fals
|
|
67
66
|
|
68
67
|
|
69
68
|
def _send_email(email: str) -> None:
|
70
|
-
"""Send the user's email
|
69
|
+
"""Send the user's email for metrics, if submitted"""
|
71
70
|
import requests
|
72
71
|
|
73
72
|
if email is None or "@" not in email:
|
74
73
|
return
|
75
74
|
|
75
|
+
metrics_url = ""
|
76
|
+
try:
|
77
|
+
response_json = requests.get(
|
78
|
+
"https://data.streamlit.io/metrics.json", timeout=2
|
79
|
+
).json()
|
80
|
+
metrics_url = response_json.get("url", "")
|
81
|
+
except Exception:
|
82
|
+
_LOGGER.error("Failed to fetch metrics URL")
|
83
|
+
return
|
84
|
+
|
76
85
|
headers = {
|
77
|
-
"authority": "api.segment.io",
|
78
86
|
"accept": "*/*",
|
79
87
|
"accept-language": "en-US,en;q=0.9",
|
80
|
-
"content-type": "
|
88
|
+
"content-type": "application/json",
|
81
89
|
"origin": "localhost:8501",
|
82
90
|
"referer": "localhost:8501/",
|
83
91
|
}
|
84
92
|
|
85
|
-
dt = f"{datetime.now(timezone.utc).isoformat()}+00:00"
|
86
|
-
|
87
93
|
data = {
|
88
94
|
"anonymous_id": None,
|
89
|
-
"context": {
|
90
|
-
"library": {"name": "analytics-python", "version": "2.2.2"},
|
91
|
-
},
|
92
95
|
"messageId": str(uuid4()),
|
93
|
-
"timestamp": dt,
|
94
96
|
"event": "submittedEmail",
|
95
|
-
"
|
96
|
-
|
97
|
-
"source": "provided_email",
|
98
|
-
},
|
97
|
+
"author_email": email,
|
98
|
+
"source": "provided_email",
|
99
99
|
"type": "track",
|
100
100
|
"userId": email,
|
101
|
-
"writeKey": "iCkMy7ymtJ9qYzQRXkQpnAJEq7D4NyMU",
|
102
101
|
}
|
103
102
|
|
104
103
|
response = requests.post(
|
105
|
-
|
104
|
+
metrics_url,
|
106
105
|
headers=headers,
|
107
106
|
data=json.dumps(data).encode(),
|
108
107
|
)
|
streamlit/static/index.html
CHANGED
@@ -51,7 +51,7 @@
|
|
51
51
|
<script>
|
52
52
|
window.prerenderReady = false
|
53
53
|
</script>
|
54
|
-
<script type="module" crossorigin src="./static/js/index.
|
54
|
+
<script type="module" crossorigin src="./static/js/index.DrBQDoQQ.js"></script>
|
55
55
|
<link rel="stylesheet" crossorigin href="./static/css/index.DpJG_94W.css">
|
56
56
|
</head>
|
57
57
|
<body>
|
@@ -1 +1 @@
|
|
1
|
-
import{r as e,E as n,_ as a}from"./index.
|
1
|
+
import{r as e,E as n,_ as a}from"./index.DrBQDoQQ.js";var o=e.forwardRef(function(t,r){var l={fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"};return e.createElement(n,a({iconAttrs:l,iconVerticalAlign:"middle",iconViewBox:"0 0 24 24"},t,{ref:r}),e.createElement("path",{fill:"none",d:"M0 0h24v24H0V0z"}),e.createElement("path",{d:"M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z"}))});o.displayName="Delete";var i=e.forwardRef(function(t,r){var l={fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"};return e.createElement(n,a({iconAttrs:l,iconVerticalAlign:"middle",iconViewBox:"0 0 24 24"},t,{ref:r}),e.createElement("rect",{width:24,height:24,fill:"none"}),e.createElement("path",{d:"M18 15v3H6v-3H4v3c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-3h-2zm-1-4l-1.41-1.41L13 12.17V4h-2v8.17L8.41 9.59 7 11l5 5 5-5z"}))});i.displayName="FileDownload";export{o as D,i as F};
|