streamlit-nightly 1.35.1.dev20240610__py2.py3-none-any.whl → 1.35.1.dev20240611__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 +5 -1
- streamlit/case_converters.py +2 -2
- streamlit/cli_util.py +2 -2
- streamlit/color_util.py +2 -2
- streamlit/commands/experimental_query_params.py +6 -8
- streamlit/commands/logo.py +4 -9
- streamlit/commands/navigation.py +6 -4
- streamlit/components/lib/local_component_registry.py +4 -2
- streamlit/components/types/base_component_registry.py +3 -2
- streamlit/components/v1/component_arrow.py +2 -1
- streamlit/components/v1/component_registry.py +6 -2
- streamlit/components/v1/components.py +4 -2
- streamlit/components/v1/custom_component.py +6 -6
- streamlit/config.py +15 -12
- streamlit/connections/snowflake_connection.py +2 -1
- streamlit/connections/snowpark_connection.py +2 -4
- streamlit/connections/sql_connection.py +2 -1
- streamlit/delta_generator.py +3 -4
- streamlit/elements/arrow.py +3 -6
- streamlit/elements/code.py +1 -1
- streamlit/elements/dialog_decorator.py +10 -8
- streamlit/elements/doc_string.py +1 -1
- streamlit/elements/exception.py +1 -1
- streamlit/elements/form.py +1 -1
- streamlit/elements/heading.py +1 -1
- streamlit/elements/html.py +1 -1
- streamlit/elements/image.py +5 -3
- streamlit/elements/layouts.py +7 -7
- streamlit/elements/lib/built_in_chart_utils.py +24 -12
- streamlit/elements/lib/column_config_utils.py +2 -1
- streamlit/elements/lib/dialog.py +8 -5
- streamlit/elements/lib/dicttools.py +3 -3
- streamlit/elements/lib/mutable_status_container.py +8 -5
- streamlit/elements/lib/pandas_styler_utils.py +2 -1
- streamlit/elements/lib/subtitle_utils.py +0 -1
- streamlit/elements/lib/utils.py +8 -10
- streamlit/elements/plotly_chart.py +5 -10
- streamlit/elements/pyplot.py +0 -1
- streamlit/elements/toast.py +2 -2
- streamlit/elements/vega_charts.py +46 -10
- streamlit/elements/widgets/color_picker.py +6 -4
- streamlit/elements/widgets/file_uploader.py +4 -8
- streamlit/elements/widgets/multiselect.py +2 -4
- streamlit/elements/widgets/number_input.py +4 -8
- streamlit/elements/widgets/select_slider.py +1 -1
- streamlit/elements/widgets/slider.py +2 -5
- streamlit/elements/widgets/time_widgets.py +5 -5
- streamlit/errors.py +1 -6
- streamlit/git_util.py +2 -2
- streamlit/hello/Animation_Demo.py +0 -1
- streamlit/logger.py +1 -1
- streamlit/navigation/page.py +6 -1
- streamlit/net_util.py +2 -5
- streamlit/proto/AutoRerun_pb2.py +3 -2
- streamlit/runtime/app_session.py +7 -7
- streamlit/runtime/caching/__init__.py +9 -13
- streamlit/runtime/caching/cache_data_api.py +18 -7
- streamlit/runtime/caching/cache_errors.py +8 -6
- streamlit/runtime/caching/cache_resource_api.py +10 -9
- streamlit/runtime/caching/cache_utils.py +10 -7
- streamlit/runtime/caching/cached_message_replay.py +10 -9
- streamlit/runtime/caching/hashing.py +3 -3
- streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
- streamlit/runtime/connection_factory.py +4 -2
- streamlit/runtime/credentials.py +11 -20
- streamlit/runtime/forward_msg_cache.py +10 -11
- streamlit/runtime/forward_msg_queue.py +6 -4
- streamlit/runtime/fragment.py +7 -9
- streamlit/runtime/media_file_manager.py +4 -4
- streamlit/runtime/memory_media_file_storage.py +7 -8
- streamlit/runtime/metrics_util.py +2 -4
- streamlit/runtime/pages_manager.py +41 -41
- streamlit/runtime/runtime.py +4 -4
- streamlit/runtime/runtime_util.py +7 -12
- streamlit/runtime/scriptrunner/magic.py +1 -1
- streamlit/runtime/scriptrunner/script_requests.py +4 -2
- streamlit/runtime/scriptrunner/script_run_context.py +15 -15
- streamlit/runtime/scriptrunner/script_runner.py +8 -8
- streamlit/runtime/secrets.py +3 -5
- streamlit/runtime/session_manager.py +8 -7
- streamlit/runtime/state/common.py +1 -1
- streamlit/runtime/state/query_params_proxy.py +5 -10
- streamlit/runtime/state/safe_session_state.py +8 -7
- streamlit/runtime/state/widgets.py +27 -27
- streamlit/runtime/stats.py +1 -1
- streamlit/runtime/uploaded_file_manager.py +4 -2
- streamlit/runtime/websocket_session_manager.py +6 -4
- streamlit/string_util.py +1 -1
- streamlit/testing/v1/app_test.py +4 -2
- streamlit/testing/v1/element_tree.py +33 -37
- streamlit/testing/v1/local_script_runner.py +7 -7
- streamlit/time_util.py +2 -4
- streamlit/type_util.py +16 -29
- streamlit/user_info.py +4 -2
- streamlit/util.py +1 -1
- streamlit/watcher/event_based_path_watcher.py +6 -3
- streamlit/watcher/local_sources_watcher.py +11 -7
- streamlit/web/bootstrap.py +1 -1
- streamlit/web/cache_storage_manager_config.py +5 -1
- streamlit/web/cli.py +9 -4
- streamlit/web/server/browser_websocket_handler.py +7 -8
- streamlit/web/server/component_request_handler.py +4 -2
- streamlit/web/server/routes.py +3 -3
- streamlit/web/server/server.py +12 -12
- streamlit/web/server/server_util.py +5 -6
- streamlit/web/server/stats_request_handler.py +1 -1
- streamlit/web/server/upload_file_request_handler.py +5 -3
- {streamlit_nightly-1.35.1.dev20240610.dist-info → streamlit_nightly-1.35.1.dev20240611.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.35.1.dev20240610.dist-info → streamlit_nightly-1.35.1.dev20240611.dist-info}/RECORD +113 -113
- {streamlit_nightly-1.35.1.dev20240610.data → streamlit_nightly-1.35.1.dev20240611.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.35.1.dev20240610.dist-info → streamlit_nightly-1.35.1.dev20240611.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.35.1.dev20240610.dist-info → streamlit_nightly-1.35.1.dev20240611.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.35.1.dev20240610.dist-info → streamlit_nightly-1.35.1.dev20240611.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
"""
|
15
|
+
"""Declares the CacheStorageContext dataclass, which contains parameter information for
|
16
16
|
each function decorated by `@st.cache_data` (for example: ttl, max_entries etc.)
|
17
17
|
|
18
18
|
Declares the CacheStorageManager protocol, which implementations are used
|
@@ -16,8 +16,7 @@ from __future__ import annotations
|
|
16
16
|
|
17
17
|
import os
|
18
18
|
import re
|
19
|
-
from
|
20
|
-
from typing import Any, Final, Literal, TypeVar, overload
|
19
|
+
from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar, overload
|
21
20
|
|
22
21
|
from streamlit.connections import (
|
23
22
|
BaseConnection,
|
@@ -31,6 +30,9 @@ from streamlit.runtime.caching import cache_resource
|
|
31
30
|
from streamlit.runtime.metrics_util import gather_metrics
|
32
31
|
from streamlit.runtime.secrets import secrets_singleton
|
33
32
|
|
33
|
+
if TYPE_CHECKING:
|
34
|
+
from datetime import timedelta
|
35
|
+
|
34
36
|
# NOTE: Adding support for a new first party connection requires:
|
35
37
|
# 1. Adding the new connection name and class to this dict.
|
36
38
|
# 2. Writing two new @overloads for connection_factory (one for the case where the
|
streamlit/runtime/credentials.py
CHANGED
@@ -20,9 +20,8 @@ import json
|
|
20
20
|
import os
|
21
21
|
import sys
|
22
22
|
import textwrap
|
23
|
-
from collections import namedtuple
|
24
23
|
from datetime import datetime
|
25
|
-
from typing import Final, NoReturn
|
24
|
+
from typing import Final, NamedTuple, NoReturn
|
26
25
|
from uuid import uuid4
|
27
26
|
|
28
27
|
from streamlit import cli_util, env_util, file_util, util
|
@@ -36,13 +35,10 @@ if env_util.IS_WINDOWS:
|
|
36
35
|
else:
|
37
36
|
_CONFIG_FILE_PATH = "~/.streamlit/config.toml"
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
"is_valid", # boolean : whether the email is valid.
|
44
|
-
],
|
45
|
-
)
|
38
|
+
|
39
|
+
class _Activation(NamedTuple):
|
40
|
+
email: str | None # the user's email.
|
41
|
+
is_valid: bool # whether the email is valid.
|
46
42
|
|
47
43
|
|
48
44
|
def email_prompt() -> str:
|
@@ -55,19 +51,14 @@ def email_prompt() -> str:
|
|
55
51
|
)
|
56
52
|
|
57
53
|
# IMPORTANT: Break the text below at 80 chars.
|
58
|
-
return """
|
59
|
-
{
|
54
|
+
return f"""
|
55
|
+
{"👋 " if show_emoji else ""}{cli_util.style_for_cli("Welcome to Streamlit!", bold=True)}
|
60
56
|
|
61
57
|
If you’d like to receive helpful onboarding emails, news, offers, promotions,
|
62
58
|
and the occasional swag, please enter your email address below. Otherwise,
|
63
59
|
leave this field blank.
|
64
60
|
|
65
|
-
|
66
|
-
"👋 " if show_emoji else ""
|
67
|
-
) % {
|
68
|
-
"welcome": cli_util.style_for_cli("Welcome to Streamlit!", bold=True),
|
69
|
-
"email": cli_util.style_for_cli("Email: ", fg="blue"),
|
70
|
-
}
|
61
|
+
{cli_util.style_for_cli("Email: ", fg="blue")}"""
|
71
62
|
|
72
63
|
|
73
64
|
_TELEMETRY_HEADLESS_TEXT = """
|
@@ -119,10 +110,10 @@ def _send_email(email: str) -> None:
|
|
119
110
|
response.raise_for_status()
|
120
111
|
|
121
112
|
|
122
|
-
class Credentials
|
113
|
+
class Credentials:
|
123
114
|
"""Credentials class."""
|
124
115
|
|
125
|
-
_singleton:
|
116
|
+
_singleton: Credentials | None = None
|
126
117
|
|
127
118
|
@classmethod
|
128
119
|
def get_current(cls):
|
@@ -156,7 +147,7 @@ class Credentials(object):
|
|
156
147
|
import toml
|
157
148
|
|
158
149
|
try:
|
159
|
-
with open(self._conf_file
|
150
|
+
with open(self._conf_file) as f:
|
160
151
|
data = toml.load(f).get("general")
|
161
152
|
if data is None:
|
162
153
|
raise Exception
|
@@ -111,9 +111,9 @@ class ForwardMsgCache(CacheStatsProvider):
|
|
111
111
|
|
112
112
|
def __init__(self, msg: ForwardMsg | None):
|
113
113
|
self.msg = msg
|
114
|
-
self._session_script_run_counts: MutableMapping[
|
115
|
-
|
116
|
-
|
114
|
+
self._session_script_run_counts: MutableMapping[AppSession, int] = (
|
115
|
+
WeakKeyDictionary()
|
116
|
+
)
|
117
117
|
|
118
118
|
def __repr__(self) -> str:
|
119
119
|
return util.repr_(self)
|
@@ -285,13 +285,12 @@ class ForwardMsgCache(CacheStatsProvider):
|
|
285
285
|
self._entries.clear()
|
286
286
|
|
287
287
|
def get_stats(self) -> list[CacheStat]:
|
288
|
-
stats: list[CacheStat] = [
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
cache_name="",
|
294
|
-
byte_length=entry.msg.ByteSize() if entry.msg is not None else 0,
|
295
|
-
)
|
288
|
+
stats: list[CacheStat] = [
|
289
|
+
CacheStat(
|
290
|
+
category_name="ForwardMessageCache",
|
291
|
+
cache_name="",
|
292
|
+
byte_length=entry.msg.ByteSize() if entry.msg is not None else 0,
|
296
293
|
)
|
294
|
+
for _, entry in self._entries.items()
|
295
|
+
]
|
297
296
|
return group_stats(stats)
|
@@ -14,11 +14,13 @@
|
|
14
14
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
-
from typing import Any
|
17
|
+
from typing import TYPE_CHECKING, Any
|
18
18
|
|
19
|
-
from streamlit.proto.Delta_pb2 import Delta
|
20
19
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
21
20
|
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
from streamlit.proto.Delta_pb2 import Delta
|
23
|
+
|
22
24
|
|
23
25
|
class ForwardMsgQueue:
|
24
26
|
"""Accumulates a session's outgoing ForwardMsgs.
|
@@ -38,7 +40,7 @@ class ForwardMsgQueue:
|
|
38
40
|
# redundant outgoing Deltas (where a newer Delta supersedes
|
39
41
|
# an older Delta, with the same delta_path, that's still in the
|
40
42
|
# queue).
|
41
|
-
self._delta_index_map: dict[tuple[int, ...], int] =
|
43
|
+
self._delta_index_map: dict[tuple[int, ...], int] = {}
|
42
44
|
|
43
45
|
def get_debug(self) -> dict[str, Any]:
|
44
46
|
from google.protobuf.json_format import MessageToDict
|
@@ -102,7 +104,7 @@ class ForwardMsgQueue:
|
|
102
104
|
}
|
103
105
|
]
|
104
106
|
|
105
|
-
self._delta_index_map =
|
107
|
+
self._delta_index_map = {}
|
106
108
|
|
107
109
|
def flush(self) -> list[ForwardMsg]:
|
108
110
|
"""Clear the queue and return a list of the messages it contained
|
streamlit/runtime/fragment.py
CHANGED
@@ -19,15 +19,17 @@ import hashlib
|
|
19
19
|
import inspect
|
20
20
|
from abc import abstractmethod
|
21
21
|
from copy import deepcopy
|
22
|
-
from datetime import timedelta
|
23
22
|
from functools import wraps
|
24
|
-
from typing import Any, Callable, Protocol, TypeVar, overload
|
23
|
+
from typing import TYPE_CHECKING, Any, Callable, Protocol, TypeVar, overload
|
25
24
|
|
26
25
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
27
26
|
from streamlit.runtime.metrics_util import gather_metrics
|
28
27
|
from streamlit.runtime.scriptrunner import get_script_run_ctx
|
29
28
|
from streamlit.time_util import time_to_seconds
|
30
29
|
|
30
|
+
if TYPE_CHECKING:
|
31
|
+
from datetime import timedelta
|
32
|
+
|
31
33
|
F = TypeVar("F", bound=Callable[..., Any])
|
32
34
|
Fragment = Callable[[], Any]
|
33
35
|
|
@@ -127,9 +129,7 @@ def _fragment(
|
|
127
129
|
active_dg = dg_stack_snapshot[-1]
|
128
130
|
h = hashlib.new("md5")
|
129
131
|
h.update(
|
130
|
-
f"{non_optional_func.__module__}.{non_optional_func.__qualname__}{active_dg._get_delta_path_str()}".encode(
|
131
|
-
"utf-8"
|
132
|
-
)
|
132
|
+
f"{non_optional_func.__module__}.{non_optional_func.__qualname__}{active_dg._get_delta_path_str()}".encode()
|
133
133
|
)
|
134
134
|
fragment_id = h.hexdigest()
|
135
135
|
|
@@ -207,8 +207,7 @@ def fragment(
|
|
207
207
|
func: F,
|
208
208
|
*,
|
209
209
|
run_every: int | float | timedelta | str | None = None,
|
210
|
-
) -> F:
|
211
|
-
...
|
210
|
+
) -> F: ...
|
212
211
|
|
213
212
|
|
214
213
|
# Support being able to pass parameters to this decorator (that is, being able to write
|
@@ -218,8 +217,7 @@ def fragment(
|
|
218
217
|
func: None = None,
|
219
218
|
*,
|
220
219
|
run_every: int | float | timedelta | str | None = None,
|
221
|
-
) -> Callable[[F], F]:
|
222
|
-
...
|
220
|
+
) -> Callable[[F], F]: ...
|
223
221
|
|
224
222
|
|
225
223
|
@gather_metrics("experimental_fragment")
|
@@ -82,12 +82,12 @@ class MediaFileManager:
|
|
82
82
|
self._storage = storage
|
83
83
|
|
84
84
|
# Dict of [file_id -> MediaFileMetadata]
|
85
|
-
self._file_metadata: dict[str, MediaFileMetadata] =
|
85
|
+
self._file_metadata: dict[str, MediaFileMetadata] = {}
|
86
86
|
|
87
87
|
# Dict[session ID][coordinates] -> file_id.
|
88
|
-
self._files_by_session_and_coord: dict[
|
89
|
-
|
90
|
-
|
88
|
+
self._files_by_session_and_coord: dict[str, dict[str, str]] = (
|
89
|
+
collections.defaultdict(dict)
|
90
|
+
)
|
91
91
|
|
92
92
|
# MediaFileManager is used from multiple threads, so all operations
|
93
93
|
# need to be protected with a Lock. (This is not an RLock, which
|
@@ -171,13 +171,12 @@ class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
|
|
171
171
|
# with other threads that may be manipulating the cache.
|
172
172
|
files_by_id = self._files_by_id.copy()
|
173
173
|
|
174
|
-
stats: list[CacheStat] = [
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
cache_name="",
|
180
|
-
byte_length=len(file.content),
|
181
|
-
)
|
174
|
+
stats: list[CacheStat] = [
|
175
|
+
CacheStat(
|
176
|
+
category_name="st_memory_media_file_storage",
|
177
|
+
cache_name="",
|
178
|
+
byte_length=len(file.content),
|
182
179
|
)
|
180
|
+
for _, file in files_by_id.items()
|
181
|
+
]
|
183
182
|
return group_stats(stats)
|
@@ -306,16 +306,14 @@ F = TypeVar("F", bound=Callable[..., Any])
|
|
306
306
|
def gather_metrics(
|
307
307
|
name: str,
|
308
308
|
func: F,
|
309
|
-
) -> F:
|
310
|
-
...
|
309
|
+
) -> F: ...
|
311
310
|
|
312
311
|
|
313
312
|
@overload
|
314
313
|
def gather_metrics(
|
315
314
|
name: str,
|
316
315
|
func: None = None,
|
317
|
-
) -> Callable[[F], F]:
|
318
|
-
...
|
316
|
+
) -> Callable[[F], F]: ...
|
319
317
|
|
320
318
|
|
321
319
|
def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
|
@@ -18,15 +18,15 @@ import contextlib
|
|
18
18
|
import os
|
19
19
|
import threading
|
20
20
|
from pathlib import Path
|
21
|
-
from typing import TYPE_CHECKING, Any, Callable, Final
|
21
|
+
from typing import TYPE_CHECKING, Any, Callable, Final
|
22
22
|
|
23
23
|
from streamlit import source_util
|
24
24
|
from streamlit.logger import get_logger
|
25
|
-
from streamlit.runtime.scriptrunner.script_cache import ScriptCache
|
26
25
|
from streamlit.util import calc_md5
|
27
26
|
from streamlit.watcher import watch_dir
|
28
27
|
|
29
28
|
if TYPE_CHECKING:
|
29
|
+
from streamlit.runtime.scriptrunner.script_cache import ScriptCache
|
30
30
|
from streamlit.source_util import PageHash, PageInfo, PageName, ScriptPath
|
31
31
|
|
32
32
|
_LOGGER: Final = get_logger(__name__)
|
@@ -76,17 +76,17 @@ class PagesStrategyV1:
|
|
76
76
|
|
77
77
|
# In MPA v1, there's no difference between the active hash
|
78
78
|
# and the page script hash.
|
79
|
-
def get_active_script_hash(self) ->
|
79
|
+
def get_active_script_hash(self) -> PageHash:
|
80
80
|
return self.pages_manager.current_page_hash
|
81
81
|
|
82
|
-
def set_active_script_hash(self, _page_hash:
|
82
|
+
def set_active_script_hash(self, _page_hash: PageHash):
|
83
83
|
# Intentionally do nothing as MPA v1 active_script_hash does not
|
84
84
|
# differentiate the active_script_hash and the page_script_hash
|
85
85
|
pass
|
86
86
|
|
87
87
|
def get_initial_active_script(
|
88
|
-
self, page_script_hash:
|
89
|
-
) ->
|
88
|
+
self, page_script_hash: PageHash, page_name: PageName
|
89
|
+
) -> PageInfo | None:
|
90
90
|
pages = self.get_pages()
|
91
91
|
|
92
92
|
if page_script_hash:
|
@@ -114,7 +114,7 @@ class PagesStrategyV1:
|
|
114
114
|
main_page_info = list(pages.values())[0]
|
115
115
|
return main_page_info
|
116
116
|
|
117
|
-
def get_pages(self) -> dict[
|
117
|
+
def get_pages(self) -> dict[PageHash, PageInfo]:
|
118
118
|
return source_util.get_pages(self.pages_manager.main_script_path)
|
119
119
|
|
120
120
|
def register_pages_changed_callback(
|
@@ -123,10 +123,10 @@ class PagesStrategyV1:
|
|
123
123
|
) -> Callable[[], None]:
|
124
124
|
return source_util.register_pages_changed_callback(callback)
|
125
125
|
|
126
|
-
def set_pages(self, _pages: dict[
|
126
|
+
def set_pages(self, _pages: dict[PageHash, PageInfo]) -> None:
|
127
127
|
raise NotImplementedError("Unable to set pages in this V1 strategy")
|
128
128
|
|
129
|
-
def get_page_script(self, _fallback_page_hash:
|
129
|
+
def get_page_script(self, _fallback_page_hash: PageHash) -> PageInfo | None:
|
130
130
|
raise NotImplementedError("Unable to get page script in this V1 strategy")
|
131
131
|
|
132
132
|
|
@@ -147,18 +147,18 @@ class PagesStrategyV2:
|
|
147
147
|
|
148
148
|
def __init__(self, pages_manager: PagesManager, **kwargs):
|
149
149
|
self.pages_manager = pages_manager
|
150
|
-
self._active_script_hash:
|
151
|
-
self._pages: dict[
|
150
|
+
self._active_script_hash: PageHash = self.pages_manager.main_script_hash
|
151
|
+
self._pages: dict[PageHash, PageInfo] | None = None
|
152
152
|
|
153
|
-
def get_active_script_hash(self) ->
|
153
|
+
def get_active_script_hash(self) -> PageHash:
|
154
154
|
return self._active_script_hash
|
155
155
|
|
156
|
-
def set_active_script_hash(self, page_hash:
|
156
|
+
def set_active_script_hash(self, page_hash: PageHash):
|
157
157
|
self._active_script_hash = page_hash
|
158
158
|
|
159
159
|
def get_initial_active_script(
|
160
|
-
self, page_script_hash:
|
161
|
-
) ->
|
160
|
+
self, page_script_hash: PageHash, page_name: PageName
|
161
|
+
) -> PageInfo:
|
162
162
|
return {
|
163
163
|
# We always run the main script in V2 as it's the common code
|
164
164
|
"script_path": self.pages_manager.main_script_path,
|
@@ -166,7 +166,7 @@ class PagesStrategyV2:
|
|
166
166
|
or self.pages_manager.main_script_hash, # Default Hash
|
167
167
|
}
|
168
168
|
|
169
|
-
def get_page_script(self, fallback_page_hash:
|
169
|
+
def get_page_script(self, fallback_page_hash: PageHash) -> PageInfo | None:
|
170
170
|
if self._pages is None:
|
171
171
|
return None
|
172
172
|
|
@@ -196,7 +196,7 @@ class PagesStrategyV2:
|
|
196
196
|
|
197
197
|
return self._pages.get(fallback_page_hash, None)
|
198
198
|
|
199
|
-
def get_pages(self) -> dict[
|
199
|
+
def get_pages(self) -> dict[PageHash, PageInfo]:
|
200
200
|
# If pages are not set, provide the common page info where
|
201
201
|
# - the main script path is the executing script to start
|
202
202
|
# - the page script hash and name reflects the intended page requested
|
@@ -209,7 +209,7 @@ class PagesStrategyV2:
|
|
209
209
|
}
|
210
210
|
}
|
211
211
|
|
212
|
-
def set_pages(self, pages: dict[
|
212
|
+
def set_pages(self, pages: dict[PageHash, PageInfo]) -> None:
|
213
213
|
self._pages = pages
|
214
214
|
|
215
215
|
def register_pages_changed_callback(
|
@@ -233,60 +233,60 @@ class PagesManager:
|
|
233
233
|
NOTE: Each strategy handles its own thread safety when accessing the pages
|
234
234
|
"""
|
235
235
|
|
236
|
-
DefaultStrategy:
|
236
|
+
DefaultStrategy: type[PagesStrategyV1 | PagesStrategyV2] = PagesStrategyV1
|
237
237
|
|
238
238
|
def __init__(
|
239
239
|
self,
|
240
|
-
main_script_path:
|
240
|
+
main_script_path: ScriptPath,
|
241
241
|
script_cache: ScriptCache | None = None,
|
242
242
|
**kwargs,
|
243
243
|
):
|
244
244
|
self._main_script_path = main_script_path
|
245
|
-
self._main_script_hash:
|
246
|
-
self._current_page_hash:
|
245
|
+
self._main_script_hash: PageHash = calc_md5(main_script_path)
|
246
|
+
self._current_page_hash: PageHash = self._main_script_hash
|
247
247
|
self.pages_strategy = PagesManager.DefaultStrategy(self, **kwargs)
|
248
248
|
self._script_cache = script_cache
|
249
|
-
self._intended_page_script_hash:
|
250
|
-
self._intended_page_name:
|
249
|
+
self._intended_page_script_hash: PageHash | None = None
|
250
|
+
self._intended_page_name: PageName | None = None
|
251
251
|
|
252
252
|
@property
|
253
|
-
def current_page_hash(self) ->
|
253
|
+
def current_page_hash(self) -> PageHash:
|
254
254
|
return self._current_page_hash
|
255
255
|
|
256
256
|
@property
|
257
|
-
def main_script_path(self) ->
|
257
|
+
def main_script_path(self) -> ScriptPath:
|
258
258
|
return self._main_script_path
|
259
259
|
|
260
260
|
@property
|
261
|
-
def main_script_hash(self) ->
|
261
|
+
def main_script_hash(self) -> PageHash:
|
262
262
|
return self._main_script_hash
|
263
263
|
|
264
264
|
@property
|
265
|
-
def intended_page_name(self) ->
|
265
|
+
def intended_page_name(self) -> PageName | None:
|
266
266
|
return self._intended_page_name
|
267
267
|
|
268
268
|
@property
|
269
|
-
def intended_page_script_hash(self) ->
|
269
|
+
def intended_page_script_hash(self) -> PageHash | None:
|
270
270
|
return self._intended_page_script_hash
|
271
271
|
|
272
|
-
def get_main_page(self) ->
|
272
|
+
def get_main_page(self) -> PageInfo:
|
273
273
|
return {
|
274
274
|
"script_path": self._main_script_path,
|
275
275
|
"page_script_hash": self._main_script_hash,
|
276
276
|
}
|
277
277
|
|
278
|
-
def get_current_page_script_hash(self) ->
|
278
|
+
def get_current_page_script_hash(self) -> PageHash:
|
279
279
|
"""Gets the script hash of the associated page of a script."""
|
280
280
|
return self._current_page_hash
|
281
281
|
|
282
|
-
def set_current_page_script_hash(self, page_hash:
|
282
|
+
def set_current_page_script_hash(self, page_hash: PageHash) -> None:
|
283
283
|
self._current_page_hash = page_hash
|
284
284
|
|
285
|
-
def get_active_script_hash(self) ->
|
285
|
+
def get_active_script_hash(self) -> PageHash:
|
286
286
|
"""Gets the script hash of the currently executing script."""
|
287
287
|
return self.pages_strategy.get_active_script_hash()
|
288
288
|
|
289
|
-
def set_active_script_hash(self, page_hash:
|
289
|
+
def set_active_script_hash(self, page_hash: PageHash):
|
290
290
|
return self.pages_strategy.set_active_script_hash(page_hash)
|
291
291
|
|
292
292
|
def reset_active_script_hash(self):
|
@@ -294,20 +294,20 @@ class PagesManager:
|
|
294
294
|
self.set_active_script_hash(self.main_script_hash)
|
295
295
|
|
296
296
|
def set_script_intent(
|
297
|
-
self, page_script_hash:
|
297
|
+
self, page_script_hash: PageHash, page_name: PageName
|
298
298
|
) -> None:
|
299
299
|
self._intended_page_script_hash = page_script_hash
|
300
300
|
self._intended_page_name = page_name
|
301
301
|
|
302
302
|
def get_initial_active_script(
|
303
|
-
self, page_script_hash:
|
304
|
-
) ->
|
303
|
+
self, page_script_hash: PageHash, page_name: PageName
|
304
|
+
) -> PageInfo | None:
|
305
305
|
return self.pages_strategy.get_initial_active_script(
|
306
306
|
page_script_hash, page_name
|
307
307
|
)
|
308
308
|
|
309
309
|
@contextlib.contextmanager
|
310
|
-
def run_with_active_hash(self, page_hash:
|
310
|
+
def run_with_active_hash(self, page_hash: PageHash):
|
311
311
|
original_page_hash = self.get_active_script_hash()
|
312
312
|
self.set_active_script_hash(page_hash)
|
313
313
|
try:
|
@@ -316,10 +316,10 @@ class PagesManager:
|
|
316
316
|
# in the event of any exception, ensure we set the active hash back
|
317
317
|
self.set_active_script_hash(original_page_hash)
|
318
318
|
|
319
|
-
def get_pages(self) -> dict[
|
319
|
+
def get_pages(self) -> dict[PageHash, PageInfo]:
|
320
320
|
return self.pages_strategy.get_pages()
|
321
321
|
|
322
|
-
def set_pages(self, pages: dict[
|
322
|
+
def set_pages(self, pages: dict[PageHash, PageInfo]) -> None:
|
323
323
|
# Manually setting the pages indicates we are using MPA v2.
|
324
324
|
if isinstance(self.pages_strategy, PagesStrategyV1):
|
325
325
|
if os.path.exists(Path(self.main_script_path).parent / "pages"):
|
@@ -331,7 +331,7 @@ class PagesManager:
|
|
331
331
|
|
332
332
|
self.pages_strategy.set_pages(pages)
|
333
333
|
|
334
|
-
def get_page_script(self, fallback_page_hash:
|
334
|
+
def get_page_script(self, fallback_page_hash: PageHash = "") -> PageInfo | None:
|
335
335
|
# We assume the pages strategy is V2 cause this is used
|
336
336
|
# in the st.navigation call, but we just swallow the error
|
337
337
|
try:
|
streamlit/runtime/runtime.py
CHANGED
@@ -23,9 +23,7 @@ from typing import TYPE_CHECKING, Awaitable, Final, NamedTuple
|
|
23
23
|
|
24
24
|
from streamlit import config
|
25
25
|
from streamlit.components.lib.local_component_registry import LocalComponentRegistry
|
26
|
-
from streamlit.components.types.base_component_registry import BaseComponentRegistry
|
27
26
|
from streamlit.logger import get_logger
|
28
|
-
from streamlit.proto.BackMsg_pb2 import BackMsg
|
29
27
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
30
28
|
from streamlit.runtime.app_session import AppSession
|
31
29
|
from streamlit.runtime.caching import (
|
@@ -41,7 +39,6 @@ from streamlit.runtime.forward_msg_cache import (
|
|
41
39
|
populate_hash_if_needed,
|
42
40
|
)
|
43
41
|
from streamlit.runtime.media_file_manager import MediaFileManager
|
44
|
-
from streamlit.runtime.media_file_storage import MediaFileStorage
|
45
42
|
from streamlit.runtime.memory_session_storage import MemorySessionStorage
|
46
43
|
from streamlit.runtime.runtime_util import is_cacheable_msg
|
47
44
|
from streamlit.runtime.script_data import ScriptData
|
@@ -58,11 +55,14 @@ from streamlit.runtime.state import (
|
|
58
55
|
SessionStateStatProvider,
|
59
56
|
)
|
60
57
|
from streamlit.runtime.stats import StatsManager
|
61
|
-
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
62
58
|
from streamlit.runtime.websocket_session_manager import WebsocketSessionManager
|
63
59
|
|
64
60
|
if TYPE_CHECKING:
|
61
|
+
from streamlit.components.types.base_component_registry import BaseComponentRegistry
|
62
|
+
from streamlit.proto.BackMsg_pb2 import BackMsg
|
65
63
|
from streamlit.runtime.caching.storage import CacheStorageManager
|
64
|
+
from streamlit.runtime.media_file_storage import MediaFileStorage
|
65
|
+
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
66
66
|
|
67
67
|
# Wait for the script run result for 60s and if no result is available give up
|
68
68
|
SCRIPT_RUN_CHECK_TIMEOUT: Final = 60
|
@@ -16,13 +16,15 @@
|
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
from typing import Any
|
19
|
+
from typing import TYPE_CHECKING, Any
|
20
20
|
|
21
21
|
from streamlit import config
|
22
22
|
from streamlit.errors import MarkdownFormattedException, StreamlitAPIException
|
23
|
-
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
24
23
|
from streamlit.runtime.forward_msg_cache import populate_hash_if_needed
|
25
24
|
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
27
|
+
|
26
28
|
|
27
29
|
class MessageSizeError(MarkdownFormattedException):
|
28
30
|
"""Exception raised when a websocket message is larger than the configured limit."""
|
@@ -34,9 +36,8 @@ class MessageSizeError(MarkdownFormattedException):
|
|
34
36
|
def _get_message(self, failed_msg_str: Any) -> str:
|
35
37
|
# This needs to have zero indentation otherwise the markdown will render incorrectly.
|
36
38
|
return (
|
37
|
-
|
38
|
-
|
39
|
-
**Data of size {message_size_mb:.1f} MB exceeds the message size limit of {message_size_limit_mb} MB.**
|
39
|
+
f"""
|
40
|
+
**Data of size {len(failed_msg_str) / 1e6:.1f} MB exceeds the message size limit of {get_max_message_size_bytes() / 1e6} MB.**
|
40
41
|
|
41
42
|
This is often caused by a large chart or dataframe. Please decrease the amount of data sent
|
42
43
|
to the browser, or increase the limit by setting the config option `server.maxMessageSize`.
|
@@ -45,13 +46,7 @@ to the browser, or increase the limit by setting the config option `server.maxMe
|
|
45
46
|
_Note that increasing the limit may lead to long loading times and large memory consumption
|
46
47
|
of the client's browser and the Streamlit server._
|
47
48
|
"""
|
48
|
-
|
49
|
-
.format(
|
50
|
-
message_size_mb=len(failed_msg_str) / 1e6,
|
51
|
-
message_size_limit_mb=(get_max_message_size_bytes() / 1e6),
|
52
|
-
)
|
53
|
-
.strip("\n")
|
54
|
-
)
|
49
|
+
).strip("\n")
|
55
50
|
|
56
51
|
|
57
52
|
class BadDurationStringError(StreamlitAPIException):
|
@@ -229,7 +229,7 @@ def _get_st_write_from_expr(
|
|
229
229
|
|
230
230
|
|
231
231
|
def _is_string_constant_node(node) -> bool:
|
232
|
-
return
|
232
|
+
return isinstance(node, ast.Constant) and isinstance(node.value, str)
|
233
233
|
|
234
234
|
|
235
235
|
def _is_docstring_node(node, node_index, parent_type) -> bool:
|
@@ -17,12 +17,14 @@ from __future__ import annotations
|
|
17
17
|
import threading
|
18
18
|
from dataclasses import dataclass, field
|
19
19
|
from enum import Enum
|
20
|
-
from typing import cast
|
20
|
+
from typing import TYPE_CHECKING, cast
|
21
21
|
|
22
22
|
from streamlit import util
|
23
|
-
from streamlit.proto.WidgetStates_pb2 import WidgetStates
|
24
23
|
from streamlit.runtime.state import coalesce_widget_states
|
25
24
|
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from streamlit.proto.WidgetStates_pb2 import WidgetStates
|
27
|
+
|
26
28
|
|
27
29
|
class ScriptRequestType(Enum):
|
28
30
|
# The ScriptRunner should continue running its script.
|