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.
Files changed (58) hide show
  1. streamlit/__init__.py +2 -0
  2. streamlit/commands/execution_control.py +23 -13
  3. streamlit/commands/navigation.py +191 -0
  4. streamlit/components/v1/custom_component.py +2 -2
  5. streamlit/elements/media.py +2 -2
  6. streamlit/elements/plotly_chart.py +1 -1
  7. streamlit/elements/widgets/button.py +49 -40
  8. streamlit/elements/widgets/camera_input.py +1 -1
  9. streamlit/elements/widgets/chat.py +1 -1
  10. streamlit/elements/widgets/checkbox.py +1 -1
  11. streamlit/elements/widgets/color_picker.py +1 -1
  12. streamlit/elements/widgets/data_editor.py +1 -1
  13. streamlit/elements/widgets/file_uploader.py +1 -1
  14. streamlit/elements/widgets/multiselect.py +1 -1
  15. streamlit/elements/widgets/number_input.py +1 -1
  16. streamlit/elements/widgets/radio.py +1 -1
  17. streamlit/elements/widgets/select_slider.py +1 -1
  18. streamlit/elements/widgets/selectbox.py +1 -1
  19. streamlit/elements/widgets/slider.py +1 -1
  20. streamlit/elements/widgets/text_widgets.py +2 -2
  21. streamlit/elements/widgets/time_widgets.py +2 -2
  22. streamlit/navigation/__init__.py +13 -0
  23. streamlit/navigation/page.py +197 -0
  24. streamlit/proto/AppPage_pb2.py +3 -3
  25. streamlit/proto/AppPage_pb2.pyi +11 -1
  26. streamlit/proto/ForwardMsg_pb2.py +10 -9
  27. streamlit/proto/ForwardMsg_pb2.pyi +17 -5
  28. streamlit/proto/Navigation_pb2.py +29 -0
  29. streamlit/proto/Navigation_pb2.pyi +79 -0
  30. streamlit/proto/NewSession_pb2.py +24 -24
  31. streamlit/proto/NewSession_pb2.pyi +5 -1
  32. streamlit/runtime/app_session.py +35 -21
  33. streamlit/runtime/fragment.py +18 -2
  34. streamlit/runtime/pages_manager.py +354 -0
  35. streamlit/runtime/scriptrunner/script_run_context.py +13 -2
  36. streamlit/runtime/scriptrunner/script_runner.py +23 -37
  37. streamlit/source_util.py +25 -11
  38. streamlit/static/asset-manifest.json +4 -4
  39. streamlit/static/index.html +1 -1
  40. streamlit/static/static/js/8571.cfc22b99.chunk.js +1 -0
  41. streamlit/static/static/js/9945.47d54f35.chunk.js +2 -0
  42. streamlit/static/static/js/{main.9978e612.js → main.707da454.js} +2 -2
  43. streamlit/testing/v1/app_test.py +7 -1
  44. streamlit/testing/v1/local_script_runner.py +6 -1
  45. streamlit/watcher/local_sources_watcher.py +20 -10
  46. streamlit/web/bootstrap.py +1 -19
  47. streamlit/web/server/routes.py +23 -25
  48. streamlit/web/server/server.py +9 -8
  49. {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/METADATA +1 -1
  50. {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/RECORD +56 -50
  51. streamlit/static/static/js/5117.04bfe5d3.chunk.js +0 -1
  52. streamlit/static/static/js/6950.70fe55c2.chunk.js +0 -2
  53. /streamlit/static/static/js/{6950.70fe55c2.chunk.js.LICENSE.txt → 9945.47d54f35.chunk.js.LICENSE.txt} +0 -0
  54. /streamlit/static/static/js/{main.9978e612.js.LICENSE.txt → main.707da454.js.LICENSE.txt} +0 -0
  55. {streamlit_nightly-1.35.1.dev20240530.data → streamlit_nightly-1.35.1.dev20240601.data}/scripts/streamlit.cmd +0 -0
  56. {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/WHEEL +0 -0
  57. {streamlit_nightly-1.35.1.dev20240530.dist-info → streamlit_nightly-1.35.1.dev20240601.dist-info}/entry_points.txt +0 -0
  58. {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) of the page to switch to.
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
- main_script_directory = get_main_script_directory(ctx.main_script_path)
145
- requested_page = os.path.realpath(normalize_path_join(main_script_directory, page))
146
- all_app_pages = source_util.get_pages(ctx.main_script_path).values()
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
- matched_pages = [p for p in all_app_pages if p["script_path"] == requested_page]
156
+ matched_pages = [p for p in all_app_pages if p["script_path"] == requested_page]
149
157
 
150
- if len(matched_pages) == 0:
151
- raise StreamlitAPIException(
152
- 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."
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=matched_pages[0]["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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
193
+ page=ctx.active_script_hash if ctx else None,
194
194
  )
195
195
  element.component_instance.id = computed_id
196
196
 
@@ -576,7 +576,7 @@ def marshall_video(
576
576
  loop=loop,
577
577
  autoplay=autoplay,
578
578
  muted=muted,
579
- page=ctx.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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, source_util
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) of the page to switch to.
468
- Alternatively, this can be the URL to an external page (must start
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.page_script_hash if ctx else None,
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
- # Handle external links:
683
- if page.startswith("http://") or page.startswith("https://"):
684
- if label is None or label == "":
685
- raise StreamlitAPIException(
686
- f"The label param is required for external links used with st.page_link - please provide a label."
687
- )
688
- else:
689
- page_link_proto.page = page
690
- page_link_proto.external = True
691
- return self.dg._enqueue("page_link", page_link_proto)
692
-
693
- ctx = get_script_run_ctx()
694
- ctx_main_script = ""
695
- if ctx:
696
- ctx_main_script = ctx.main_script_path
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
- main_script_directory = get_main_script_directory(ctx_main_script)
699
- requested_page = os.path.realpath(
700
- normalize_path_join(main_script_directory, page)
701
- )
702
- all_app_pages = source_util.get_pages(ctx_main_script).values()
703
-
704
- # Handle retrieving the page_script_hash & page
705
- for page_data in all_app_pages:
706
- full_path = page_data["script_path"]
707
- page_name = page_data["page_name"]
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.page_script_hash if ctx else None,
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
@@ -212,7 +212,7 @@ class CameraInputMixin:
212
212
  key=key,
213
213
  help=help,
214
214
  form_id=current_form_id(self.dg),
215
- page=ctx.page_script_hash if ctx else None,
215
+ page=ctx.active_script_hash if ctx else None,
216
216
  )
217
217
 
218
218
  camera_input_proto = CameraInputProto()
@@ -328,7 +328,7 @@ class ChatMixin:
328
328
  key=key,
329
329
  placeholder=placeholder,
330
330
  max_chars=max_chars,
331
- page=ctx.page_script_hash if ctx else None,
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.
@@ -297,7 +297,7 @@ class CheckboxMixin:
297
297
  key=key,
298
298
  help=help,
299
299
  form_id=current_form_id(self.dg),
300
- page=ctx.page_script_hash if ctx else None,
300
+ page=ctx.active_script_hash if ctx else None,
301
301
  )
302
302
 
303
303
  checkbox_proto = CheckboxProto()
@@ -187,7 +187,7 @@ class ColorPickerMixin:
187
187
  key=key,
188
188
  help=help,
189
189
  form_id=current_form_id(self.dg),
190
- page=ctx.page_script_hash if ctx else None,
190
+ page=ctx.active_script_hash if ctx else None,
191
191
  )
192
192
 
193
193
  # set value default
@@ -883,7 +883,7 @@ class DataEditorMixin:
883
883
  num_rows=num_rows,
884
884
  key=key,
885
885
  form_id=current_form_id(self.dg),
886
- page=ctx.page_script_hash if ctx else None,
886
+ page=ctx.active_script_hash if ctx else None,
887
887
  )
888
888
 
889
889
  proto = ArrowProto()
@@ -417,7 +417,7 @@ class FileUploaderMixin:
417
417
  key=key,
418
418
  help=help,
419
419
  form_id=current_form_id(self.dg),
420
- page=ctx.page_script_hash if ctx else None,
420
+ page=ctx.active_script_hash if ctx else None,
421
421
  )
422
422
 
423
423
  if type:
@@ -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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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:
@@ -303,7 +303,7 @@ class SelectSliderMixin:
303
303
  key=key,
304
304
  help=help,
305
305
  form_id=current_form_id(self.dg),
306
- page=ctx.page_script_hash if ctx else None,
306
+ page=ctx.active_script_hash if ctx else None,
307
307
  )
308
308
 
309
309
  slider_proto = SliderProto()
@@ -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.page_script_hash if ctx else None,
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:
@@ -386,7 +386,7 @@ class SliderMixin:
386
386
  key=key,
387
387
  help=help,
388
388
  form_id=current_form_id(self.dg),
389
- page=ctx.page_script_hash if ctx else None,
389
+ page=ctx.active_script_hash if ctx else None,
390
390
  )
391
391
 
392
392
  SUPPORTED_TYPES = {
@@ -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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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.page_script_hash if ctx else None,
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.