streamlit-nightly 1.35.1.dev20240530__py2.py3-none-any.whl → 1.35.1.dev20240601__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/__init__.py +2 -0
- streamlit/commands/execution_control.py +23 -13
- streamlit/commands/navigation.py +191 -0
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/elements/media.py +2 -2
- streamlit/elements/plotly_chart.py +1 -1
- streamlit/elements/widgets/button.py +49 -40
- streamlit/elements/widgets/camera_input.py +1 -1
- streamlit/elements/widgets/chat.py +1 -1
- streamlit/elements/widgets/checkbox.py +1 -1
- streamlit/elements/widgets/color_picker.py +1 -1
- streamlit/elements/widgets/data_editor.py +1 -1
- streamlit/elements/widgets/file_uploader.py +1 -1
- streamlit/elements/widgets/multiselect.py +1 -1
- streamlit/elements/widgets/number_input.py +1 -1
- streamlit/elements/widgets/radio.py +1 -1
- streamlit/elements/widgets/select_slider.py +1 -1
- streamlit/elements/widgets/selectbox.py +1 -1
- streamlit/elements/widgets/slider.py +1 -1
- streamlit/elements/widgets/text_widgets.py +2 -2
- streamlit/elements/widgets/time_widgets.py +2 -2
- streamlit/navigation/__init__.py +13 -0
- streamlit/navigation/page.py +197 -0
- streamlit/proto/AppPage_pb2.py +3 -3
- streamlit/proto/AppPage_pb2.pyi +11 -1
- streamlit/proto/ForwardMsg_pb2.py +10 -9
- streamlit/proto/ForwardMsg_pb2.pyi +17 -5
- streamlit/proto/Navigation_pb2.py +29 -0
- streamlit/proto/Navigation_pb2.pyi +79 -0
- streamlit/proto/NewSession_pb2.py +24 -24
- streamlit/proto/NewSession_pb2.pyi +5 -1
- streamlit/runtime/app_session.py +35 -21
- streamlit/runtime/fragment.py +18 -2
- streamlit/runtime/pages_manager.py +354 -0
- streamlit/runtime/scriptrunner/script_run_context.py +13 -2
- streamlit/runtime/scriptrunner/script_runner.py +23 -37
- streamlit/source_util.py +25 -11
- streamlit/static/asset-manifest.json +4 -4
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/8571.cfc22b99.chunk.js +1 -0
- streamlit/static/static/js/9945.47d54f35.chunk.js +2 -0
- streamlit/static/static/js/{main.9978e612.js → main.707da454.js} +2 -2
- streamlit/testing/v1/app_test.py +7 -1
- streamlit/testing/v1/local_script_runner.py +6 -1
- streamlit/watcher/local_sources_watcher.py +20 -10
- streamlit/web/bootstrap.py +1 -19
- streamlit/web/server/routes.py +23 -25
- streamlit/web/server/server.py +9 -8
- {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/RECORD +56 -50
- streamlit/static/static/js/5117.04bfe5d3.chunk.js +0 -1
- streamlit/static/static/js/6950.70fe55c2.chunk.js +0 -2
- /streamlit/static/static/js/{6950.70fe55c2.chunk.js.LICENSE.txt → 9945.47d54f35.chunk.js.LICENSE.txt} +0 -0
- /streamlit/static/static/js/{main.9978e612.js.LICENSE.txt → main.707da454.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.35.1.dev20240530.data → streamlit_nightly-1.35.1.dev20240601.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/top_level.txt +0 -0
streamlit/__init__.py
CHANGED
@@ -106,6 +106,8 @@ import streamlit.column_config as _column_config
|
|
106
106
|
|
107
107
|
from streamlit.echo import echo as echo
|
108
108
|
from streamlit.commands.logo import logo as logo
|
109
|
+
from streamlit.commands.navigation import navigation as navigation
|
110
|
+
from streamlit.navigation.page import Page as Page
|
109
111
|
from streamlit.elements.spinner import spinner as spinner
|
110
112
|
|
111
113
|
from streamlit.commands.page_config import set_page_config as set_page_config
|
@@ -18,11 +18,11 @@ import os
|
|
18
18
|
from typing import Final, NoReturn
|
19
19
|
|
20
20
|
import streamlit as st
|
21
|
-
from streamlit import source_util
|
22
21
|
from streamlit.deprecation_util import make_deprecated_name_warning
|
23
22
|
from streamlit.errors import NoSessionContext, StreamlitAPIException
|
24
23
|
from streamlit.file_util import get_main_script_directory, normalize_path_join
|
25
24
|
from streamlit.logger import get_logger
|
25
|
+
from streamlit.navigation.page import StreamlitPage
|
26
26
|
from streamlit.runtime.metrics_util import gather_metrics
|
27
27
|
from streamlit.runtime.scriptrunner import RerunData, get_script_run_ctx
|
28
28
|
|
@@ -96,7 +96,7 @@ def experimental_rerun() -> NoReturn:
|
|
96
96
|
|
97
97
|
|
98
98
|
@gather_metrics("switch_page")
|
99
|
-
def switch_page(page: str) -> NoReturn: # type: ignore[misc]
|
99
|
+
def switch_page(page: str | StreamlitPage) -> NoReturn: # type: ignore[misc]
|
100
100
|
"""Programmatically switch the current page in a multipage app.
|
101
101
|
|
102
102
|
When ``st.switch_page`` is called, the current page execution stops and
|
@@ -107,8 +107,10 @@ def switch_page(page: str) -> NoReturn: # type: ignore[misc]
|
|
107
107
|
|
108
108
|
Parameters
|
109
109
|
----------
|
110
|
-
page: str
|
111
|
-
The file path (relative to the main script)
|
110
|
+
page: str or st.Page
|
111
|
+
The file path (relative to the main script) or an st.Page indicating
|
112
|
+
the page to switch to.
|
113
|
+
|
112
114
|
|
113
115
|
Example
|
114
116
|
-------
|
@@ -141,21 +143,29 @@ def switch_page(page: str) -> NoReturn: # type: ignore[misc]
|
|
141
143
|
# This should never be the case
|
142
144
|
raise NoSessionContext()
|
143
145
|
|
144
|
-
|
145
|
-
|
146
|
-
|
146
|
+
page_script_hash = ""
|
147
|
+
if isinstance(page, StreamlitPage):
|
148
|
+
page_script_hash = page._script_hash
|
149
|
+
else:
|
150
|
+
main_script_directory = get_main_script_directory(ctx.main_script_path)
|
151
|
+
requested_page = os.path.realpath(
|
152
|
+
normalize_path_join(main_script_directory, page)
|
153
|
+
)
|
154
|
+
all_app_pages = ctx.pages_manager.get_pages().values()
|
147
155
|
|
148
|
-
|
156
|
+
matched_pages = [p for p in all_app_pages if p["script_path"] == requested_page]
|
149
157
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
158
|
+
if len(matched_pages) == 0:
|
159
|
+
raise StreamlitAPIException(
|
160
|
+
f"Could not find page: `{page}`. Must be the file path relative to the main script, from the directory: `{os.path.basename(main_script_directory)}`. Only the main app file and files in the `pages/` directory are supported."
|
161
|
+
)
|
162
|
+
|
163
|
+
page_script_hash = matched_pages[0]["page_script_hash"]
|
154
164
|
|
155
165
|
ctx.script_requests.request_rerun(
|
156
166
|
RerunData(
|
157
167
|
query_string=ctx.query_string,
|
158
|
-
page_script_hash=
|
168
|
+
page_script_hash=page_script_hash,
|
159
169
|
)
|
160
170
|
)
|
161
171
|
# Force a yield point so the runner can do the rerun
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
from pathlib import Path
|
18
|
+
from typing import Literal
|
19
|
+
|
20
|
+
from typing_extensions import TypeAlias
|
21
|
+
|
22
|
+
from streamlit.errors import StreamlitAPIException
|
23
|
+
from streamlit.navigation.page import StreamlitPage
|
24
|
+
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
25
|
+
from streamlit.proto.Navigation_pb2 import Navigation as NavigationProto
|
26
|
+
from streamlit.runtime.metrics_util import gather_metrics
|
27
|
+
from streamlit.runtime.scriptrunner.script_run_context import (
|
28
|
+
ScriptRunContext,
|
29
|
+
get_script_run_ctx,
|
30
|
+
)
|
31
|
+
from streamlit.source_util import PageHash, PageInfo
|
32
|
+
|
33
|
+
SectionHeader: TypeAlias = str
|
34
|
+
|
35
|
+
|
36
|
+
def pages_from_nav_sections(
|
37
|
+
nav_sections: dict[SectionHeader, list[StreamlitPage]]
|
38
|
+
) -> list[StreamlitPage]:
|
39
|
+
page_list = []
|
40
|
+
for pages in nav_sections.values():
|
41
|
+
for page in pages:
|
42
|
+
page_list.append(page)
|
43
|
+
|
44
|
+
return page_list
|
45
|
+
|
46
|
+
|
47
|
+
def send_page_not_found(ctx: ScriptRunContext):
|
48
|
+
msg = ForwardMsg()
|
49
|
+
msg.page_not_found.page_name = ""
|
50
|
+
ctx.enqueue(msg)
|
51
|
+
|
52
|
+
|
53
|
+
@gather_metrics("navigation")
|
54
|
+
def navigation(
|
55
|
+
pages: list[StreamlitPage] | dict[SectionHeader, list[StreamlitPage]],
|
56
|
+
*,
|
57
|
+
position: Literal["sidebar", "hidden"] = "sidebar",
|
58
|
+
) -> StreamlitPage | None:
|
59
|
+
"""
|
60
|
+
Configure the available pages in a multipage app.
|
61
|
+
|
62
|
+
Call `st.navigation` in your main script with one or more pages defined by
|
63
|
+
`st.Page`. `st.navigation` returns the current page which can be executed
|
64
|
+
using `Page.run()`.
|
65
|
+
|
66
|
+
When using `st.navigation`, the main script is executed on every app rerun,
|
67
|
+
with the current page executed in-line using `Page.run()`. The set of
|
68
|
+
available pages can be updated with each rerun for dynamic navigation. In
|
69
|
+
this mode, the `pages/` folder is ignored.
|
70
|
+
|
71
|
+
By default, `st.navigation` draws the available pages in the side
|
72
|
+
navigation. This behavior can be changed using the `position=` keyword
|
73
|
+
argument.
|
74
|
+
|
75
|
+
Parameters
|
76
|
+
----------
|
77
|
+
pages: list[st.Page] or dict[str, list[st.Page]]
|
78
|
+
A list of `st.Page` objects or a dictionary where the keys are section
|
79
|
+
headers and the values are lists of `st.Page` objects.
|
80
|
+
|
81
|
+
position: "sidebar" or "hidden"
|
82
|
+
The position of the navigation menu. Can be "sidebar" or "hidden".
|
83
|
+
|
84
|
+
Example
|
85
|
+
-------
|
86
|
+
>>> import streamlit as st
|
87
|
+
>>> from pages import page1, page2
|
88
|
+
>>>
|
89
|
+
>>> pg = st.navigation([st.Page(page1), st.Page(page2)])
|
90
|
+
>>>
|
91
|
+
>>> st.title("My Awesome App")
|
92
|
+
>>> pg.run()
|
93
|
+
"""
|
94
|
+
ctx = get_script_run_ctx()
|
95
|
+
if not ctx:
|
96
|
+
return None
|
97
|
+
|
98
|
+
nav_sections = {"": pages} if isinstance(pages, list) else pages
|
99
|
+
page_list = pages_from_nav_sections(nav_sections)
|
100
|
+
|
101
|
+
if not page_list:
|
102
|
+
raise StreamlitAPIException(
|
103
|
+
"`st.navigation` must be called with at least one `st.Page`."
|
104
|
+
)
|
105
|
+
|
106
|
+
default_page = None
|
107
|
+
pagehash_to_pageinfo: dict[PageHash, PageInfo] = {}
|
108
|
+
|
109
|
+
# This nested loop keeps track of two things:
|
110
|
+
# 1. the default page
|
111
|
+
# 2. the pagehash to pageinfo mapping
|
112
|
+
for section_header in nav_sections:
|
113
|
+
for page in nav_sections[section_header]:
|
114
|
+
if page._default:
|
115
|
+
if default_page is not None:
|
116
|
+
raise StreamlitAPIException(
|
117
|
+
"Multiple Pages specified with `default=True`. "
|
118
|
+
"At most one Page can be set to default."
|
119
|
+
)
|
120
|
+
default_page = page
|
121
|
+
|
122
|
+
if isinstance(page._page, Path):
|
123
|
+
script_path = str(page._page)
|
124
|
+
else:
|
125
|
+
script_path = ""
|
126
|
+
|
127
|
+
script_hash = page._script_hash
|
128
|
+
if script_hash in pagehash_to_pageinfo:
|
129
|
+
# The page script hash is soley based on the url path
|
130
|
+
# So duplicate page script hashes are due to duplicate url paths
|
131
|
+
raise StreamlitAPIException(
|
132
|
+
f"Multiple Pages specified with URL pathname {page.url_path}. "
|
133
|
+
"URL pathnames must be unique. The url pathname may be "
|
134
|
+
"inferred from the filename, callable name, or title."
|
135
|
+
)
|
136
|
+
|
137
|
+
pagehash_to_pageinfo[script_hash] = {
|
138
|
+
"page_script_hash": script_hash,
|
139
|
+
"page_name": page.title,
|
140
|
+
"icon": page.icon,
|
141
|
+
"script_path": script_path,
|
142
|
+
"url_pathname": page.url_path,
|
143
|
+
}
|
144
|
+
|
145
|
+
if default_page is None:
|
146
|
+
default_page = page_list[0]
|
147
|
+
default_page._default = True
|
148
|
+
|
149
|
+
msg = ForwardMsg()
|
150
|
+
if position == "hidden":
|
151
|
+
msg.navigation.position = NavigationProto.Position.HIDDEN
|
152
|
+
else:
|
153
|
+
msg.navigation.position = NavigationProto.Position.SIDEBAR
|
154
|
+
msg.navigation.sections[:] = nav_sections.keys()
|
155
|
+
for section_header in nav_sections:
|
156
|
+
for page in nav_sections[section_header]:
|
157
|
+
p = msg.navigation.app_pages.add()
|
158
|
+
p.page_script_hash = page._script_hash
|
159
|
+
p.page_name = page.title
|
160
|
+
p.icon = page.icon
|
161
|
+
p.is_default = page._default
|
162
|
+
p.section_header = section_header
|
163
|
+
p.url_pathname = page.url_path
|
164
|
+
|
165
|
+
# Inform our page manager about the set of pages we have
|
166
|
+
ctx.pages_manager.set_pages(pagehash_to_pageinfo)
|
167
|
+
found_page = ctx.pages_manager.get_page_script(
|
168
|
+
fallback_page_hash=default_page._script_hash
|
169
|
+
)
|
170
|
+
|
171
|
+
page_to_return = None
|
172
|
+
if found_page:
|
173
|
+
found_page_script_hash = found_page["page_script_hash"]
|
174
|
+
matching_pages = [
|
175
|
+
p for p in page_list if p._script_hash == found_page_script_hash
|
176
|
+
]
|
177
|
+
if len(matching_pages) > 0:
|
178
|
+
page_to_return = matching_pages[0]
|
179
|
+
|
180
|
+
if not page_to_return:
|
181
|
+
send_page_not_found(ctx)
|
182
|
+
page_to_return = default_page
|
183
|
+
|
184
|
+
# Ordain the page that can be called
|
185
|
+
page_to_return._can_be_called = True
|
186
|
+
msg.navigation.page_script_hash = page_to_return._script_hash
|
187
|
+
|
188
|
+
# This will either navigation or yield if the page is not found
|
189
|
+
ctx.enqueue(msg)
|
190
|
+
|
191
|
+
return page_to_return
|
@@ -180,7 +180,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
180
180
|
key=key,
|
181
181
|
json_args=serialized_json_args,
|
182
182
|
special_args=special_args,
|
183
|
-
page=ctx.
|
183
|
+
page=ctx.active_script_hash if ctx else None,
|
184
184
|
)
|
185
185
|
else:
|
186
186
|
computed_id = compute_widget_id(
|
@@ -190,7 +190,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
190
190
|
form_id=current_form_id(dg),
|
191
191
|
url=self.url,
|
192
192
|
key=key,
|
193
|
-
page=ctx.
|
193
|
+
page=ctx.active_script_hash if ctx else None,
|
194
194
|
)
|
195
195
|
element.component_instance.id = computed_id
|
196
196
|
|
streamlit/elements/media.py
CHANGED
@@ -576,7 +576,7 @@ def marshall_video(
|
|
576
576
|
loop=loop,
|
577
577
|
autoplay=autoplay,
|
578
578
|
muted=muted,
|
579
|
-
page=ctx.
|
579
|
+
page=ctx.active_script_hash if ctx else None,
|
580
580
|
)
|
581
581
|
|
582
582
|
proto.id = id
|
@@ -752,6 +752,6 @@ def marshall_audio(
|
|
752
752
|
end_time=end_time,
|
753
753
|
loop=loop,
|
754
754
|
autoplay=autoplay,
|
755
|
-
page=ctx.
|
755
|
+
page=ctx.active_script_hash if ctx else None,
|
756
756
|
)
|
757
757
|
proto.id = id
|
@@ -509,7 +509,7 @@ class PlotlyMixin:
|
|
509
509
|
theme=theme,
|
510
510
|
form_id=plotly_chart_proto.form_id,
|
511
511
|
use_container_width=use_container_width,
|
512
|
-
page=ctx.
|
512
|
+
page=ctx.active_script_hash if ctx else None,
|
513
513
|
)
|
514
514
|
|
515
515
|
if is_selection_activated:
|
@@ -22,7 +22,7 @@ from typing import TYPE_CHECKING, BinaryIO, Final, Literal, TextIO, Union, cast
|
|
22
22
|
|
23
23
|
from typing_extensions import TypeAlias
|
24
24
|
|
25
|
-
from streamlit import runtime
|
25
|
+
from streamlit import runtime
|
26
26
|
from streamlit.elements.form import current_form_id, is_in_form
|
27
27
|
from streamlit.elements.lib.policies import (
|
28
28
|
check_cache_replay_rules,
|
@@ -31,6 +31,7 @@ from streamlit.elements.lib.policies import (
|
|
31
31
|
)
|
32
32
|
from streamlit.errors import StreamlitAPIException
|
33
33
|
from streamlit.file_util import get_main_script_directory, normalize_path_join
|
34
|
+
from streamlit.navigation.page import StreamlitPage
|
34
35
|
from streamlit.proto.Button_pb2 import Button as ButtonProto
|
35
36
|
from streamlit.proto.DownloadButton_pb2 import DownloadButton as DownloadButtonProto
|
36
37
|
from streamlit.proto.LinkButton_pb2 import LinkButton as LinkButtonProto
|
@@ -46,6 +47,7 @@ from streamlit.runtime.state import (
|
|
46
47
|
from streamlit.runtime.state.common import compute_widget_id, save_for_app_testing
|
47
48
|
from streamlit.string_util import validate_icon_or_emoji
|
48
49
|
from streamlit.type_util import Key, to_key
|
50
|
+
from streamlit.url_util import is_url
|
49
51
|
|
50
52
|
if TYPE_CHECKING:
|
51
53
|
from streamlit.delta_generator import DeltaGenerator
|
@@ -443,7 +445,7 @@ class ButtonMixin:
|
|
443
445
|
@gather_metrics("page_link")
|
444
446
|
def page_link(
|
445
447
|
self,
|
446
|
-
page: str,
|
448
|
+
page: str | StreamlitPage,
|
447
449
|
*,
|
448
450
|
label: str | None = None,
|
449
451
|
icon: str | None = None,
|
@@ -463,10 +465,10 @@ class ButtonMixin:
|
|
463
465
|
|
464
466
|
Parameters
|
465
467
|
----------
|
466
|
-
page : str
|
467
|
-
The file path (relative to the main script)
|
468
|
-
Alternatively, this can be the URL to an
|
469
|
-
with "http://" or "https://").
|
468
|
+
page : str or st.Page
|
469
|
+
The file path (relative to the main script) or an st.Page indicating
|
470
|
+
the page to switch to. Alternatively, this can be the URL to an
|
471
|
+
external page (must start with "http://" or "https://").
|
470
472
|
label : str
|
471
473
|
The label for the page link. Labels are required for external pages.
|
472
474
|
Labels can optionally contain Markdown and supports the following
|
@@ -593,7 +595,7 @@ class ButtonMixin:
|
|
593
595
|
help=help,
|
594
596
|
type=type,
|
595
597
|
use_container_width=use_container_width,
|
596
|
-
page=ctx.
|
598
|
+
page=ctx.active_script_hash if ctx else None,
|
597
599
|
)
|
598
600
|
|
599
601
|
if is_in_form(self.dg):
|
@@ -656,7 +658,7 @@ class ButtonMixin:
|
|
656
658
|
|
657
659
|
def _page_link(
|
658
660
|
self,
|
659
|
-
page: str,
|
661
|
+
page: str | StreamlitPage,
|
660
662
|
*, # keyword-only arguments:
|
661
663
|
label: str | None = None,
|
662
664
|
icon: str | None = None,
|
@@ -679,38 +681,45 @@ class ButtonMixin:
|
|
679
681
|
if use_container_width is not None:
|
680
682
|
page_link_proto.use_container_width = use_container_width
|
681
683
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
684
|
+
if isinstance(page, StreamlitPage):
|
685
|
+
page_link_proto.page_script_hash = page._script_hash
|
686
|
+
page_link_proto.page = page.url_path
|
687
|
+
if label is None:
|
688
|
+
page_link_proto.label = page.title
|
689
|
+
else:
|
690
|
+
# Handle external links:
|
691
|
+
if is_url(page):
|
692
|
+
if label is None or label == "":
|
693
|
+
raise StreamlitAPIException(
|
694
|
+
"The label param is required for external links used with st.page_link - please provide a label."
|
695
|
+
)
|
696
|
+
else:
|
697
|
+
page_link_proto.page = page
|
698
|
+
page_link_proto.external = True
|
699
|
+
return self.dg._enqueue("page_link", page_link_proto)
|
700
|
+
|
701
|
+
ctx = get_script_run_ctx()
|
702
|
+
ctx_main_script = ""
|
703
|
+
all_app_pages = {}
|
704
|
+
if ctx:
|
705
|
+
ctx_main_script = ctx.main_script_path
|
706
|
+
all_app_pages = ctx.pages_manager.get_pages()
|
707
|
+
|
708
|
+
main_script_directory = get_main_script_directory(ctx_main_script)
|
709
|
+
requested_page = os.path.realpath(
|
710
|
+
normalize_path_join(main_script_directory, page)
|
711
|
+
)
|
697
712
|
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
if requested_page == full_path:
|
709
|
-
if label is None:
|
710
|
-
page_link_proto.label = page_name.replace("_", " ")
|
711
|
-
page_link_proto.page_script_hash = page_data["page_script_hash"]
|
712
|
-
page_link_proto.page = page_name
|
713
|
-
break
|
713
|
+
# Handle retrieving the page_script_hash & page
|
714
|
+
for page_data in all_app_pages.values():
|
715
|
+
full_path = page_data["script_path"]
|
716
|
+
page_name = page_data["page_name"]
|
717
|
+
if requested_page == full_path:
|
718
|
+
if label is None:
|
719
|
+
page_link_proto.label = page_name.replace("_", " ")
|
720
|
+
page_link_proto.page_script_hash = page_data["page_script_hash"]
|
721
|
+
page_link_proto.page = page_name
|
722
|
+
break
|
714
723
|
|
715
724
|
if page_link_proto.page_script_hash == "":
|
716
725
|
raise StreamlitAPIException(
|
@@ -750,7 +759,7 @@ class ButtonMixin:
|
|
750
759
|
is_form_submitter=is_form_submitter,
|
751
760
|
type=type,
|
752
761
|
use_container_width=use_container_width,
|
753
|
-
page=ctx.
|
762
|
+
page=ctx.active_script_hash if ctx else None,
|
754
763
|
)
|
755
764
|
|
756
765
|
# It doesn't make sense to create a button inside a form (except
|
@@ -328,7 +328,7 @@ class ChatMixin:
|
|
328
328
|
key=key,
|
329
329
|
placeholder=placeholder,
|
330
330
|
max_chars=max_chars,
|
331
|
-
page=ctx.
|
331
|
+
page=ctx.active_script_hash if ctx else None,
|
332
332
|
)
|
333
333
|
|
334
334
|
# It doesn't make sense to create a chat input inside a form.
|
@@ -314,7 +314,7 @@ class MultiSelectMixin:
|
|
314
314
|
max_selections=max_selections,
|
315
315
|
placeholder=placeholder,
|
316
316
|
form_id=current_form_id(self.dg),
|
317
|
-
page=ctx.
|
317
|
+
page=ctx.active_script_hash if ctx else None,
|
318
318
|
)
|
319
319
|
|
320
320
|
default_value: list[int] = [] if indices is None else indices
|
@@ -303,7 +303,7 @@ class NumberInputMixin:
|
|
303
303
|
help=help,
|
304
304
|
placeholder=None if placeholder is None else str(placeholder),
|
305
305
|
form_id=current_form_id(self.dg),
|
306
|
-
page=ctx.
|
306
|
+
page=ctx.active_script_hash if ctx else None,
|
307
307
|
)
|
308
308
|
|
309
309
|
# Ensure that all arguments are of the same type.
|
@@ -276,7 +276,7 @@ class RadioMixin:
|
|
276
276
|
horizontal=horizontal,
|
277
277
|
captions=captions,
|
278
278
|
form_id=current_form_id(self.dg),
|
279
|
-
page=ctx.
|
279
|
+
page=ctx.active_script_hash if ctx else None,
|
280
280
|
)
|
281
281
|
|
282
282
|
if not isinstance(index, int) and index is not None:
|
@@ -255,7 +255,7 @@ class SelectboxMixin:
|
|
255
255
|
help=help,
|
256
256
|
placeholder=placeholder,
|
257
257
|
form_id=current_form_id(self.dg),
|
258
|
-
page=ctx.
|
258
|
+
page=ctx.active_script_hash if ctx else None,
|
259
259
|
)
|
260
260
|
|
261
261
|
if not isinstance(index, int) and index is not None:
|
@@ -279,7 +279,7 @@ class TextWidgetsMixin:
|
|
279
279
|
autocomplete=autocomplete,
|
280
280
|
placeholder=str(placeholder),
|
281
281
|
form_id=current_form_id(self.dg),
|
282
|
-
page=ctx.
|
282
|
+
page=ctx.active_script_hash if ctx else None,
|
283
283
|
)
|
284
284
|
|
285
285
|
session_state = get_session_state().filtered_state
|
@@ -546,7 +546,7 @@ class TextWidgetsMixin:
|
|
546
546
|
help=help,
|
547
547
|
placeholder=str(placeholder),
|
548
548
|
form_id=current_form_id(self.dg),
|
549
|
-
page=ctx.
|
549
|
+
page=ctx.active_script_hash if ctx else None,
|
550
550
|
)
|
551
551
|
|
552
552
|
session_state = get_session_state().filtered_state
|
@@ -458,7 +458,7 @@ class TimeWidgetsMixin:
|
|
458
458
|
help=help,
|
459
459
|
step=step,
|
460
460
|
form_id=current_form_id(self.dg),
|
461
|
-
page=ctx.
|
461
|
+
page=ctx.active_script_hash if ctx else None,
|
462
462
|
)
|
463
463
|
del value
|
464
464
|
|
@@ -731,7 +731,7 @@ class TimeWidgetsMixin:
|
|
731
731
|
help=help,
|
732
732
|
format=format,
|
733
733
|
form_id=current_form_id(self.dg),
|
734
|
-
page=ctx.
|
734
|
+
page=ctx.active_script_hash if ctx else None,
|
735
735
|
)
|
736
736
|
if not bool(ALLOWED_DATE_FORMATS.match(format)):
|
737
737
|
raise StreamlitAPIException(
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
|
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.
|