streamlit-nightly 1.31.2.dev20240213__py2.py3-none-any.whl → 1.31.2.dev20240214__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/case_converters.py +9 -4
- streamlit/cli_util.py +2 -0
- streamlit/code_util.py +5 -2
- streamlit/color_util.py +2 -0
- streamlit/column_config.py +2 -0
- streamlit/commands/execution_control.py +4 -2
- streamlit/commands/experimental_query_params.py +7 -4
- streamlit/commands/page_config.py +11 -9
- streamlit/components/v1/components.py +23 -16
- streamlit/config.py +3 -5
- streamlit/config_option.py +12 -11
- streamlit/connections/base_connection.py +4 -2
- streamlit/connections/snowflake_connection.py +4 -4
- streamlit/connections/snowpark_connection.py +3 -3
- streamlit/connections/sql_connection.py +6 -6
- streamlit/connections/util.py +8 -5
- streamlit/constants.py +2 -0
- streamlit/cursor.py +16 -14
- streamlit/delta_generator.py +10 -13
- streamlit/deprecation_util.py +4 -3
- streamlit/echo.py +5 -3
- streamlit/elements/alert.py +16 -14
- streamlit/elements/altair_utils.py +8 -6
- streamlit/elements/arrow.py +4 -4
- streamlit/elements/arrow_altair.py +24 -34
- streamlit/elements/arrow_vega_lite.py +9 -14
- streamlit/elements/balloons.py +4 -2
- streamlit/elements/bokeh_chart.py +7 -7
- streamlit/elements/code.py +6 -4
- streamlit/elements/deck_gl_json_chart.py +8 -8
- streamlit/elements/doc_string.py +5 -9
- streamlit/elements/empty.py +4 -2
- streamlit/elements/exception.py +10 -10
- streamlit/elements/form.py +1 -3
- streamlit/elements/graphviz_chart.py +5 -6
- streamlit/elements/heading.py +16 -14
- streamlit/elements/iframe.py +14 -12
- streamlit/elements/image.py +8 -8
- streamlit/elements/json.py +6 -4
- streamlit/elements/layouts.py +12 -10
- streamlit/elements/lib/column_config_utils.py +2 -2
- streamlit/elements/lib/column_types.py +23 -23
- streamlit/elements/lib/dicttools.py +10 -6
- streamlit/elements/lib/mutable_status_container.py +7 -7
- streamlit/elements/lib/pandas_styler_utils.py +6 -6
- streamlit/elements/lib/streamlit_plotly_theme.py +2 -0
- streamlit/elements/map.py +11 -22
- streamlit/elements/markdown.py +16 -14
- streamlit/elements/media.py +16 -16
- streamlit/elements/metric.py +9 -7
- streamlit/elements/plotly_chart.py +5 -5
- streamlit/elements/progress.py +6 -6
- streamlit/elements/pyplot.py +10 -13
- streamlit/elements/snow.py +4 -2
- streamlit/elements/spinner.py +2 -0
- streamlit/elements/text.py +7 -5
- streamlit/elements/toast.py +6 -4
- streamlit/elements/utils.py +15 -28
- streamlit/elements/widgets/button.py +39 -39
- streamlit/elements/widgets/camera_input.py +21 -17
- streamlit/elements/widgets/chat.py +6 -7
- streamlit/elements/widgets/checkbox.py +21 -19
- streamlit/elements/widgets/color_picker.py +18 -16
- streamlit/elements/widgets/data_editor.py +7 -7
- streamlit/elements/widgets/file_uploader.py +59 -55
- streamlit/elements/widgets/multiselect.py +33 -42
- streamlit/elements/widgets/number_input.py +10 -5
- streamlit/elements/widgets/radio.py +1 -1
- streamlit/elements/widgets/select_slider.py +25 -34
- streamlit/elements/widgets/selectbox.py +1 -1
- streamlit/elements/widgets/slider.py +28 -36
- streamlit/elements/widgets/text_widgets.py +6 -6
- streamlit/elements/widgets/time_widgets.py +13 -13
- streamlit/elements/write.py +8 -19
- streamlit/env_util.py +5 -3
- streamlit/error_util.py +7 -3
- streamlit/errors.py +3 -1
- streamlit/external/langchain/streamlit_callback_handler.py +26 -24
- streamlit/file_util.py +18 -14
- streamlit/folder_black_list.py +3 -1
- streamlit/git_util.py +5 -3
- streamlit/js_number.py +10 -13
- streamlit/logger.py +5 -5
- streamlit/net_util.py +14 -11
- streamlit/platform.py +2 -0
- streamlit/runtime/__init__.py +2 -0
- streamlit/runtime/app_session.py +42 -42
- streamlit/runtime/caching/__init__.py +4 -4
- streamlit/runtime/caching/cache_data_api.py +3 -3
- streamlit/runtime/caching/cache_errors.py +5 -3
- streamlit/runtime/caching/cache_type.py +2 -0
- streamlit/runtime/caching/cache_utils.py +2 -4
- streamlit/runtime/caching/cached_message_replay.py +12 -5
- streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -2
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -5
- streamlit/runtime/connection_factory.py +8 -8
- streamlit/runtime/forward_msg_cache.py +20 -18
- streamlit/runtime/forward_msg_queue.py +8 -9
- streamlit/runtime/legacy_caching/caching.py +32 -42
- streamlit/runtime/media_file_manager.py +16 -14
- streamlit/runtime/media_file_storage.py +8 -8
- streamlit/runtime/memory_media_file_storage.py +12 -14
- streamlit/runtime/memory_session_storage.py +4 -3
- streamlit/runtime/memory_uploaded_file_manager.py +9 -10
- streamlit/runtime/metrics_util.py +20 -20
- streamlit/runtime/runtime.py +25 -27
- streamlit/runtime/runtime_util.py +5 -3
- streamlit/runtime/script_data.py +2 -0
- streamlit/runtime/scriptrunner/magic.py +17 -11
- streamlit/runtime/scriptrunner/magic_funcs.py +2 -0
- streamlit/runtime/scriptrunner/script_requests.py +6 -4
- streamlit/runtime/scriptrunner/script_run_context.py +17 -17
- streamlit/runtime/scriptrunner/script_runner.py +7 -5
- streamlit/runtime/secrets.py +4 -6
- streamlit/runtime/session_manager.py +14 -14
- streamlit/runtime/state/common.py +5 -4
- streamlit/runtime/state/query_params.py +8 -6
- streamlit/runtime/state/query_params_proxy.py +7 -5
- streamlit/runtime/state/safe_session_state.py +7 -5
- streamlit/runtime/state/session_state.py +3 -4
- streamlit/runtime/state/session_state_proxy.py +5 -5
- streamlit/runtime/state/widgets.py +20 -18
- streamlit/runtime/uploaded_file_manager.py +6 -5
- streamlit/runtime/websocket_session_manager.py +14 -14
- streamlit/source_util.py +13 -11
- streamlit/string_util.py +13 -9
- streamlit/temporary_directory.py +3 -1
- streamlit/testing/v1/element_tree.py +1 -2
- streamlit/type_util.py +21 -25
- streamlit/url_util.py +6 -4
- streamlit/user_info.py +8 -6
- streamlit/util.py +23 -37
- streamlit/watcher/event_based_path_watcher.py +10 -10
- streamlit/watcher/local_sources_watcher.py +15 -13
- streamlit/watcher/path_watcher.py +0 -3
- streamlit/watcher/polling_path_watcher.py +9 -8
- streamlit/watcher/util.py +3 -2
- streamlit/web/cache_storage_manager_config.py +2 -0
- streamlit/web/server/app_static_file_handler.py +6 -5
- streamlit/web/server/browser_websocket_handler.py +10 -8
- streamlit/web/server/component_request_handler.py +7 -4
- streamlit/web/server/media_file_handler.py +5 -4
- streamlit/web/server/routes.py +6 -3
- streamlit/web/server/server.py +31 -31
- streamlit/web/server/server_util.py +4 -2
- streamlit/web/server/upload_file_request_handler.py +7 -8
- streamlit/web/server/websocket_headers.py +2 -2
- {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/RECORD +153 -153
- {streamlit_nightly-1.31.2.dev20240213.data → streamlit_nightly-1.31.2.dev20240214.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/top_level.txt +0 -0
streamlit/runtime/secrets.py
CHANGED
@@ -19,12 +19,10 @@ import threading
|
|
19
19
|
from copy import deepcopy
|
20
20
|
from typing import (
|
21
21
|
Any,
|
22
|
-
Dict,
|
23
22
|
Final,
|
24
23
|
ItemsView,
|
25
24
|
Iterator,
|
26
25
|
KeysView,
|
27
|
-
List,
|
28
26
|
Mapping,
|
29
27
|
NoReturn,
|
30
28
|
ValuesView,
|
@@ -37,8 +35,8 @@ import streamlit.watcher.path_watcher
|
|
37
35
|
from streamlit import file_util, runtime
|
38
36
|
from streamlit.logger import get_logger
|
39
37
|
|
40
|
-
_LOGGER = get_logger(__name__)
|
41
|
-
SECRETS_FILE_LOCS: Final[
|
38
|
+
_LOGGER: Final = get_logger(__name__)
|
39
|
+
SECRETS_FILE_LOCS: Final[list[str]] = [
|
42
40
|
file_util.get_streamlit_file_path("secrets.toml"),
|
43
41
|
# NOTE: The order here is important! Project-level secrets should overwrite global
|
44
42
|
# secrets.
|
@@ -107,7 +105,7 @@ class AttrDict(Mapping[str, Any]):
|
|
107
105
|
def __setattr__(self, key, value) -> NoReturn:
|
108
106
|
raise TypeError("Secrets does not support attribute assignment.")
|
109
107
|
|
110
|
-
def to_dict(self) ->
|
108
|
+
def to_dict(self) -> dict[str, Any]:
|
111
109
|
return deepcopy(self.__nested_secrets__)
|
112
110
|
|
113
111
|
|
@@ -118,7 +116,7 @@ class Secrets(Mapping[str, Any]):
|
|
118
116
|
Safe to use from multiple threads.
|
119
117
|
"""
|
120
118
|
|
121
|
-
def __init__(self, file_paths:
|
119
|
+
def __init__(self, file_paths: list[str]):
|
122
120
|
# Our secrets dict.
|
123
121
|
self._secrets: Mapping[str, Any] | None = None
|
124
122
|
self._lock = threading.RLock()
|
@@ -12,11 +12,11 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
from __future__ import annotations
|
16
|
+
|
15
17
|
from abc import abstractmethod
|
16
18
|
from dataclasses import dataclass
|
17
|
-
from typing import Callable,
|
18
|
-
|
19
|
-
from typing_extensions import Protocol
|
19
|
+
from typing import Callable, Protocol, cast
|
20
20
|
|
21
21
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
22
22
|
from streamlit.runtime.app_session import AppSession
|
@@ -64,7 +64,7 @@ class SessionInfo:
|
|
64
64
|
the ForwardMsgCache.
|
65
65
|
"""
|
66
66
|
|
67
|
-
client:
|
67
|
+
client: SessionClient | None
|
68
68
|
session: AppSession
|
69
69
|
script_run_count: int = 0
|
70
70
|
|
@@ -90,7 +90,7 @@ class SessionStorageError(Exception):
|
|
90
90
|
|
91
91
|
class SessionStorage(Protocol):
|
92
92
|
@abstractmethod
|
93
|
-
def get(self, session_id: str) ->
|
93
|
+
def get(self, session_id: str) -> SessionInfo | None:
|
94
94
|
"""Return the SessionInfo corresponding to session_id, or None if one does not
|
95
95
|
exist.
|
96
96
|
|
@@ -152,7 +152,7 @@ class SessionStorage(Protocol):
|
|
152
152
|
raise NotImplementedError
|
153
153
|
|
154
154
|
@abstractmethod
|
155
|
-
def list(self) ->
|
155
|
+
def list(self) -> list[SessionInfo]:
|
156
156
|
"""List all sessions tracked by this SessionStorage.
|
157
157
|
|
158
158
|
Returns
|
@@ -210,7 +210,7 @@ class SessionManager(Protocol):
|
|
210
210
|
session_storage: SessionStorage,
|
211
211
|
uploaded_file_manager: UploadedFileManager,
|
212
212
|
script_cache: ScriptCache,
|
213
|
-
message_enqueued_callback:
|
213
|
+
message_enqueued_callback: Callable[[], None] | None,
|
214
214
|
) -> None:
|
215
215
|
"""Initialize a SessionManager with the given SessionStorage.
|
216
216
|
|
@@ -235,9 +235,9 @@ class SessionManager(Protocol):
|
|
235
235
|
self,
|
236
236
|
client: SessionClient,
|
237
237
|
script_data: ScriptData,
|
238
|
-
user_info:
|
239
|
-
existing_session_id:
|
240
|
-
session_id_override:
|
238
|
+
user_info: dict[str, str | None],
|
239
|
+
existing_session_id: str | None = None,
|
240
|
+
session_id_override: str | None = None,
|
241
241
|
) -> str:
|
242
242
|
"""Create a new session or connect to an existing one.
|
243
243
|
|
@@ -290,7 +290,7 @@ class SessionManager(Protocol):
|
|
290
290
|
raise NotImplementedError
|
291
291
|
|
292
292
|
@abstractmethod
|
293
|
-
def get_session_info(self, session_id: str) ->
|
293
|
+
def get_session_info(self, session_id: str) -> SessionInfo | None:
|
294
294
|
"""Return the SessionInfo for the given id, or None if no such session
|
295
295
|
exists.
|
296
296
|
|
@@ -306,7 +306,7 @@ class SessionManager(Protocol):
|
|
306
306
|
raise NotImplementedError
|
307
307
|
|
308
308
|
@abstractmethod
|
309
|
-
def list_sessions(self) ->
|
309
|
+
def list_sessions(self) -> list[SessionInfo]:
|
310
310
|
"""Return the SessionInfo for all sessions managed by this SessionManager.
|
311
311
|
|
312
312
|
Returns
|
@@ -344,7 +344,7 @@ class SessionManager(Protocol):
|
|
344
344
|
"""
|
345
345
|
self.close_session(session_id)
|
346
346
|
|
347
|
-
def get_active_session_info(self, session_id: str) ->
|
347
|
+
def get_active_session_info(self, session_id: str) -> ActiveSessionInfo | None:
|
348
348
|
"""Return the ActiveSessionInfo for the given id, or None if either no such
|
349
349
|
session exists or the session is not active.
|
350
350
|
|
@@ -371,7 +371,7 @@ class SessionManager(Protocol):
|
|
371
371
|
"""
|
372
372
|
return self.get_active_session_info(session_id) is not None
|
373
373
|
|
374
|
-
def list_active_sessions(self) ->
|
374
|
+
def list_active_sessions(self) -> list[ActiveSessionInfo]:
|
375
375
|
"""Return the session info for all active sessions tracked by this SessionManager.
|
376
376
|
|
377
377
|
Returns
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
"""Functions and data structures shared by session_state.py and widgets.py"""
|
16
|
+
|
16
17
|
from __future__ import annotations
|
17
18
|
|
18
19
|
import hashlib
|
@@ -23,8 +24,8 @@ from typing import (
|
|
23
24
|
Any,
|
24
25
|
Callable,
|
25
26
|
Dict,
|
27
|
+
Final,
|
26
28
|
Generic,
|
27
|
-
Optional,
|
28
29
|
Sequence,
|
29
30
|
Tuple,
|
30
31
|
TypeVar,
|
@@ -32,7 +33,7 @@ from typing import (
|
|
32
33
|
)
|
33
34
|
|
34
35
|
from google.protobuf.message import Message
|
35
|
-
from typing_extensions import
|
36
|
+
from typing_extensions import TypeAlias
|
36
37
|
|
37
38
|
from streamlit import util
|
38
39
|
from streamlit.errors import StreamlitAPIException
|
@@ -151,7 +152,7 @@ class RegisterWidgetResult(Generic[T_co]):
|
|
151
152
|
@classmethod
|
152
153
|
def failure(
|
153
154
|
cls, deserializer: WidgetDeserializer[T_co]
|
154
|
-
) ->
|
155
|
+
) -> RegisterWidgetResult[T_co]:
|
155
156
|
"""The canonical way to construct a RegisterWidgetResult in cases
|
156
157
|
where the true widget value could not be determined.
|
157
158
|
"""
|
@@ -200,7 +201,7 @@ def compute_widget_id(
|
|
200
201
|
return f"{GENERATED_WIDGET_ID_PREFIX}-{h.hexdigest()}-{user_key}"
|
201
202
|
|
202
203
|
|
203
|
-
def user_key_from_widget_id(widget_id: str) ->
|
204
|
+
def user_key_from_widget_id(widget_id: str) -> str | None:
|
204
205
|
"""Return the user key portion of a widget id, or None if the id does not
|
205
206
|
have a user key.
|
206
207
|
|
@@ -12,8 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
from __future__ import annotations
|
16
|
+
|
15
17
|
from dataclasses import dataclass, field
|
16
|
-
from typing import
|
18
|
+
from typing import Iterable, Iterator, MutableMapping
|
17
19
|
from urllib import parse
|
18
20
|
|
19
21
|
from streamlit.constants import EMBED_QUERY_PARAMS_KEYS
|
@@ -27,7 +29,7 @@ class QueryParams(MutableMapping[str, str]):
|
|
27
29
|
It stores str keys with str and List[str] values.
|
28
30
|
"""
|
29
31
|
|
30
|
-
_query_params:
|
32
|
+
_query_params: dict[str, list[str] | str] = field(default_factory=dict)
|
31
33
|
|
32
34
|
def __iter__(self) -> Iterator[str]:
|
33
35
|
self._ensure_single_query_api_used()
|
@@ -59,7 +61,7 @@ class QueryParams(MutableMapping[str, str]):
|
|
59
61
|
except KeyError:
|
60
62
|
raise KeyError(missing_key_error_message(key))
|
61
63
|
|
62
|
-
def __setitem__(self, key: str, value:
|
64
|
+
def __setitem__(self, key: str, value: str | Iterable[str]) -> None:
|
63
65
|
if isinstance(value, dict):
|
64
66
|
raise StreamlitAPIException(
|
65
67
|
f"You cannot set a query params key `{key}` to a dictionary."
|
@@ -86,7 +88,7 @@ class QueryParams(MutableMapping[str, str]):
|
|
86
88
|
except KeyError:
|
87
89
|
raise KeyError(missing_key_error_message(key))
|
88
90
|
|
89
|
-
def get_all(self, key: str) ->
|
91
|
+
def get_all(self, key: str) -> list[str]:
|
90
92
|
self._ensure_single_query_api_used()
|
91
93
|
if key not in self._query_params or key in EMBED_QUERY_PARAMS_KEYS:
|
92
94
|
return []
|
@@ -128,7 +130,7 @@ class QueryParams(MutableMapping[str, str]):
|
|
128
130
|
|
129
131
|
self._send_query_param_msg()
|
130
132
|
|
131
|
-
def to_dict(self) ->
|
133
|
+
def to_dict(self) -> dict[str, str]:
|
132
134
|
self._ensure_single_query_api_used()
|
133
135
|
# return the last query param if multiple values are set
|
134
136
|
return {
|
@@ -137,7 +139,7 @@ class QueryParams(MutableMapping[str, str]):
|
|
137
139
|
if key not in EMBED_QUERY_PARAMS_KEYS
|
138
140
|
}
|
139
141
|
|
140
|
-
def set_with_no_forward_msg(self, key: str, val:
|
142
|
+
def set_with_no_forward_msg(self, key: str, val: list[str] | str) -> None:
|
141
143
|
self._query_params[key] = val
|
142
144
|
|
143
145
|
def clear_with_no_forward_msg(self) -> None:
|
@@ -12,7 +12,9 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
from typing import Iterable, Iterator, MutableMapping
|
16
18
|
|
17
19
|
from streamlit.runtime.metrics_util import gather_metrics
|
18
20
|
from streamlit.runtime.state.query_params import missing_key_error_message
|
@@ -47,7 +49,7 @@ class QueryParamsProxy(MutableMapping[str, str]):
|
|
47
49
|
del qp[key]
|
48
50
|
|
49
51
|
@gather_metrics("query_params.set_item")
|
50
|
-
def __setitem__(self, key: str, value:
|
52
|
+
def __setitem__(self, key: str, value: str | Iterable[str]) -> None:
|
51
53
|
with get_session_state().query_params() as qp:
|
52
54
|
qp[key] = value
|
53
55
|
|
@@ -67,12 +69,12 @@ class QueryParamsProxy(MutableMapping[str, str]):
|
|
67
69
|
raise AttributeError(missing_key_error_message(key))
|
68
70
|
|
69
71
|
@gather_metrics("query_params.set_attr")
|
70
|
-
def __setattr__(self, key: str, value:
|
72
|
+
def __setattr__(self, key: str, value: str | Iterable[str]) -> None:
|
71
73
|
with get_session_state().query_params() as qp:
|
72
74
|
qp[key] = value
|
73
75
|
|
74
76
|
@gather_metrics("query_params.get_all")
|
75
|
-
def get_all(self, key: str) ->
|
77
|
+
def get_all(self, key: str) -> list[str]:
|
76
78
|
"""
|
77
79
|
Get a list of all query parameter values associated to a given key.
|
78
80
|
|
@@ -107,7 +109,7 @@ class QueryParamsProxy(MutableMapping[str, str]):
|
|
107
109
|
qp.clear()
|
108
110
|
|
109
111
|
@gather_metrics("query_params.to_dict")
|
110
|
-
def to_dict(self) ->
|
112
|
+
def to_dict(self) -> dict[str, str]:
|
111
113
|
"""
|
112
114
|
Get all query parameters as a dictionary.
|
113
115
|
|
@@ -12,9 +12,11 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
from __future__ import annotations
|
16
|
+
|
15
17
|
import threading
|
16
18
|
from contextlib import contextmanager
|
17
|
-
from typing import Any, Callable,
|
19
|
+
from typing import Any, Callable, Iterator
|
18
20
|
|
19
21
|
from streamlit.proto.WidgetStates_pb2 import WidgetState as WidgetStateProto
|
20
22
|
from streamlit.proto.WidgetStates_pb2 import WidgetStates as WidgetStatesProto
|
@@ -47,7 +49,7 @@ class SafeSessionState:
|
|
47
49
|
object.__setattr__(self, "_yield_callback", yield_callback)
|
48
50
|
|
49
51
|
def register_widget(
|
50
|
-
self, metadata: WidgetMetadata[T], user_key:
|
52
|
+
self, metadata: WidgetMetadata[T], user_key: str | None
|
51
53
|
) -> RegisterWidgetResult[T]:
|
52
54
|
self._yield_callback()
|
53
55
|
with self._lock:
|
@@ -62,7 +64,7 @@ class SafeSessionState:
|
|
62
64
|
# to a Lock.)
|
63
65
|
self._state.on_script_will_rerun(latest_widget_states)
|
64
66
|
|
65
|
-
def on_script_finished(self, widget_ids_this_run:
|
67
|
+
def on_script_finished(self, widget_ids_this_run: set[str]) -> None:
|
66
68
|
with self._lock:
|
67
69
|
self._state.on_script_finished(widget_ids_this_run)
|
68
70
|
|
@@ -70,7 +72,7 @@ class SafeSessionState:
|
|
70
72
|
with self._lock:
|
71
73
|
self._state.maybe_check_serializable()
|
72
74
|
|
73
|
-
def get_widget_states(self) ->
|
75
|
+
def get_widget_states(self) -> list[WidgetStateProto]:
|
74
76
|
"""Return a list of serialized widget values for each widget with a value."""
|
75
77
|
with self._lock:
|
76
78
|
return self._state.get_widget_states()
|
@@ -80,7 +82,7 @@ class SafeSessionState:
|
|
80
82
|
return self._state.is_new_state_value(user_key)
|
81
83
|
|
82
84
|
@property
|
83
|
-
def filtered_state(self) ->
|
85
|
+
def filtered_state(self) -> dict[str, Any]:
|
84
86
|
"""The combined session and widget state, excluding keyless widgets."""
|
85
87
|
with self._lock:
|
86
88
|
return self._state.filtered_state
|
@@ -152,8 +152,7 @@ class WStates(MutableMapping[str, Any]):
|
|
152
152
|
# For this and many other methods, we can't simply delegate to the
|
153
153
|
# states field, because we need to invoke `__getitem__` for any
|
154
154
|
# values, to handle deserialization and unwrapping of values.
|
155
|
-
|
156
|
-
yield key
|
155
|
+
yield from self.states
|
157
156
|
|
158
157
|
def keys(self) -> KeysView[str]:
|
159
158
|
return KeysView(self.states)
|
@@ -164,7 +163,7 @@ class WStates(MutableMapping[str, Any]):
|
|
164
163
|
def values(self) -> set[Any]: # type: ignore[override]
|
165
164
|
return {self[wid] for wid in self}
|
166
165
|
|
167
|
-
def update(self, other:
|
166
|
+
def update(self, other: WStates) -> None: # type: ignore[override]
|
168
167
|
"""Copy all widget values and metadata from 'other' into this mapping,
|
169
168
|
overwriting any data in this mapping that's also present in 'other'.
|
170
169
|
"""
|
@@ -674,7 +673,7 @@ def _is_internal_key(key: str) -> bool:
|
|
674
673
|
|
675
674
|
@dataclass
|
676
675
|
class SessionStateStatProvider(CacheStatsProvider):
|
677
|
-
_session_mgr:
|
676
|
+
_session_mgr: SessionManager
|
678
677
|
|
679
678
|
def get_stats(self) -> list[CacheStat]:
|
680
679
|
stats: list[CacheStat] = []
|
@@ -12,9 +12,9 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from
|
15
|
+
from __future__ import annotations
|
16
16
|
|
17
|
-
from
|
17
|
+
from typing import Any, Final, Iterator, MutableMapping
|
18
18
|
|
19
19
|
from streamlit import logger as _logger
|
20
20
|
from streamlit import runtime
|
@@ -24,7 +24,7 @@ from streamlit.runtime.state.safe_session_state import SafeSessionState
|
|
24
24
|
from streamlit.runtime.state.session_state import SessionState
|
25
25
|
from streamlit.type_util import Key
|
26
26
|
|
27
|
-
|
27
|
+
_LOGGER: Final = _logger.get_logger(__name__)
|
28
28
|
|
29
29
|
|
30
30
|
_state_use_warning_already_displayed: bool = False
|
@@ -48,7 +48,7 @@ def get_session_state() -> SafeSessionState:
|
|
48
48
|
if not _state_use_warning_already_displayed:
|
49
49
|
_state_use_warning_already_displayed = True
|
50
50
|
if not runtime.exists():
|
51
|
-
|
51
|
+
_LOGGER.warning(
|
52
52
|
"Session state does not function when running a script without `streamlit run`"
|
53
53
|
)
|
54
54
|
return SafeSessionState(SessionState(), lambda: None)
|
@@ -130,7 +130,7 @@ class SessionStateProxy(MutableMapping[Key, Any]):
|
|
130
130
|
except KeyError:
|
131
131
|
raise AttributeError(_missing_attr_error_message(key))
|
132
132
|
|
133
|
-
def to_dict(self) ->
|
133
|
+
def to_dict(self) -> dict[str, Any]:
|
134
134
|
"""Return a dict containing all session_state and keyed widget values."""
|
135
135
|
return get_session_state().filtered_state
|
136
136
|
|
@@ -12,11 +12,13 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
from __future__ import annotations
|
16
|
+
|
15
17
|
import textwrap
|
16
18
|
from types import MappingProxyType
|
17
|
-
from typing import TYPE_CHECKING,
|
19
|
+
from typing import TYPE_CHECKING, Final, Mapping
|
18
20
|
|
19
|
-
from typing_extensions import
|
21
|
+
from typing_extensions import TypeAlias
|
20
22
|
|
21
23
|
from streamlit.errors import DuplicateWidgetID
|
22
24
|
from streamlit.proto.WidgetStates_pb2 import WidgetState, WidgetStates
|
@@ -86,12 +88,12 @@ def register_widget(
|
|
86
88
|
element_proto: WidgetProto,
|
87
89
|
deserializer: WidgetDeserializer[T],
|
88
90
|
serializer: WidgetSerializer[T],
|
89
|
-
ctx:
|
90
|
-
user_key:
|
91
|
-
widget_func_name:
|
92
|
-
on_change_handler:
|
93
|
-
args:
|
94
|
-
kwargs:
|
91
|
+
ctx: ScriptRunContext | None,
|
92
|
+
user_key: str | None = None,
|
93
|
+
widget_func_name: str | None = None,
|
94
|
+
on_change_handler: WidgetCallback | None = None,
|
95
|
+
args: WidgetArgs | None = None,
|
96
|
+
kwargs: WidgetKwargs | None = None,
|
95
97
|
) -> RegisterWidgetResult[T]:
|
96
98
|
"""Register a widget with Streamlit, and return its current value.
|
97
99
|
NOTE: This function should be called after the proto has been filled.
|
@@ -107,21 +109,21 @@ def register_widget(
|
|
107
109
|
its st.<widget_name> function.
|
108
110
|
serializer : WidgetSerializer[T]
|
109
111
|
Called to convert a widget's value to its protobuf representation.
|
110
|
-
ctx :
|
112
|
+
ctx : ScriptRunContext or None
|
111
113
|
Used to ensure uniqueness of widget IDs, and to look up widget values.
|
112
|
-
user_key :
|
114
|
+
user_key : str or None
|
113
115
|
Optional user-specified string to use as the widget ID.
|
114
116
|
If this is None, we'll generate an ID by hashing the element.
|
115
|
-
widget_func_name :
|
117
|
+
widget_func_name : str or None
|
116
118
|
The widget's DeltaGenerator function name, if it's different from
|
117
119
|
its element_type. Custom components are a special case: they all have
|
118
120
|
the element_type "component_instance", but are instantiated with
|
119
121
|
dynamically-named functions.
|
120
|
-
on_change_handler :
|
122
|
+
on_change_handler : WidgetCallback or None
|
121
123
|
An optional callback invoked when the widget's value changes.
|
122
|
-
args :
|
124
|
+
args : WidgetArgs or None
|
123
125
|
args to pass to on_change_handler when invoked
|
124
|
-
kwargs :
|
126
|
+
kwargs : WidgetKwargs or None
|
125
127
|
kwargs to pass to on_change_handler when invoked
|
126
128
|
|
127
129
|
Returns
|
@@ -163,8 +165,8 @@ def register_widget(
|
|
163
165
|
|
164
166
|
def register_widget_from_metadata(
|
165
167
|
metadata: WidgetMetadata[T],
|
166
|
-
ctx:
|
167
|
-
widget_func_name:
|
168
|
+
ctx: ScriptRunContext | None,
|
169
|
+
widget_func_name: str | None,
|
168
170
|
element_type: ElementType,
|
169
171
|
) -> RegisterWidgetResult[T]:
|
170
172
|
"""Register a widget and return its value, using an already constructed
|
@@ -226,7 +228,7 @@ def coalesce_widget_states(
|
|
226
228
|
`old_states` will be set to True in the coalesced result, so that button
|
227
229
|
presses don't go missing.
|
228
230
|
"""
|
229
|
-
states_by_id:
|
231
|
+
states_by_id: dict[str, WidgetState] = {
|
230
232
|
wstate.id: wstate for wstate in new_states.widgets
|
231
233
|
}
|
232
234
|
|
@@ -254,7 +256,7 @@ def coalesce_widget_states(
|
|
254
256
|
|
255
257
|
|
256
258
|
def _build_duplicate_widget_message(
|
257
|
-
widget_func_name: str, user_key:
|
259
|
+
widget_func_name: str, user_key: str | None = None
|
258
260
|
) -> str:
|
259
261
|
if user_key is not None:
|
260
262
|
message = textwrap.dedent(
|
@@ -11,11 +11,12 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
|
14
17
|
import io
|
15
18
|
from abc import abstractmethod
|
16
|
-
from typing import
|
17
|
-
|
18
|
-
from typing_extensions import Protocol
|
19
|
+
from typing import NamedTuple, Protocol, Sequence
|
19
20
|
|
20
21
|
from streamlit import util
|
21
22
|
from streamlit.proto.Common_pb2 import FileURLs as FileURLsProto
|
@@ -98,7 +99,7 @@ class UploadedFileManager(CacheStatsProvider, Protocol):
|
|
98
99
|
@abstractmethod
|
99
100
|
def get_files(
|
100
101
|
self, session_id: str, file_ids: Sequence[str]
|
101
|
-
) ->
|
102
|
+
) -> list[UploadedFileRec]:
|
102
103
|
"""Return a list of UploadedFileRec for a given sequence of file_ids.
|
103
104
|
|
104
105
|
Parameters
|
@@ -123,7 +124,7 @@ class UploadedFileManager(CacheStatsProvider, Protocol):
|
|
123
124
|
|
124
125
|
def get_upload_urls(
|
125
126
|
self, session_id: str, file_names: Sequence[str]
|
126
|
-
) ->
|
127
|
+
) -> list[UploadFileUrlInfo]:
|
127
128
|
"""Return a list of UploadFileUrlInfo for a given sequence of file_names.
|
128
129
|
Optional to implement, issuing of URLs could be done by other service.
|
129
130
|
|
@@ -12,9 +12,9 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from
|
15
|
+
from __future__ import annotations
|
16
16
|
|
17
|
-
from
|
17
|
+
from typing import Callable, Final, List, cast
|
18
18
|
|
19
19
|
from streamlit.logger import get_logger
|
20
20
|
from streamlit.runtime.app_session import AppSession
|
@@ -30,7 +30,7 @@ from streamlit.runtime.session_manager import (
|
|
30
30
|
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
31
31
|
from streamlit.watcher import LocalSourcesWatcher
|
32
32
|
|
33
|
-
|
33
|
+
_LOGGER: Final = get_logger(__name__)
|
34
34
|
|
35
35
|
|
36
36
|
class WebsocketSessionManager(SessionManager):
|
@@ -48,7 +48,7 @@ class WebsocketSessionManager(SessionManager):
|
|
48
48
|
session_storage: SessionStorage,
|
49
49
|
uploaded_file_manager: UploadedFileManager,
|
50
50
|
script_cache: ScriptCache,
|
51
|
-
message_enqueued_callback:
|
51
|
+
message_enqueued_callback: Callable[[], None] | None,
|
52
52
|
) -> None:
|
53
53
|
self._session_storage = session_storage
|
54
54
|
self._uploaded_file_mgr = uploaded_file_manager
|
@@ -56,22 +56,22 @@ class WebsocketSessionManager(SessionManager):
|
|
56
56
|
self._message_enqueued_callback = message_enqueued_callback
|
57
57
|
|
58
58
|
# Mapping of AppSession.id -> ActiveSessionInfo.
|
59
|
-
self._active_session_info_by_id:
|
59
|
+
self._active_session_info_by_id: dict[str, ActiveSessionInfo] = {}
|
60
60
|
|
61
61
|
def connect_session(
|
62
62
|
self,
|
63
63
|
client: SessionClient,
|
64
64
|
script_data: ScriptData,
|
65
|
-
user_info:
|
66
|
-
existing_session_id:
|
67
|
-
session_id_override:
|
65
|
+
user_info: dict[str, str | None],
|
66
|
+
existing_session_id: str | None = None,
|
67
|
+
session_id_override: str | None = None,
|
68
68
|
) -> str:
|
69
69
|
assert not (
|
70
70
|
existing_session_id and session_id_override
|
71
71
|
), "Only one of existing_session_id and session_id_override should be truthy"
|
72
72
|
|
73
73
|
if existing_session_id in self._active_session_info_by_id:
|
74
|
-
|
74
|
+
_LOGGER.warning(
|
75
75
|
"Session with id %s is already connected! Connecting to a new session.",
|
76
76
|
existing_session_id,
|
77
77
|
)
|
@@ -105,7 +105,7 @@ class WebsocketSessionManager(SessionManager):
|
|
105
105
|
session_id_override=session_id_override,
|
106
106
|
)
|
107
107
|
|
108
|
-
|
108
|
+
_LOGGER.debug(
|
109
109
|
"Created new session for client %s. Session ID: %s", id(client), session.id
|
110
110
|
)
|
111
111
|
|
@@ -133,13 +133,13 @@ class WebsocketSessionManager(SessionManager):
|
|
133
133
|
)
|
134
134
|
del self._active_session_info_by_id[session_id]
|
135
135
|
|
136
|
-
def get_active_session_info(self, session_id: str) ->
|
136
|
+
def get_active_session_info(self, session_id: str) -> ActiveSessionInfo | None:
|
137
137
|
return self._active_session_info_by_id.get(session_id)
|
138
138
|
|
139
139
|
def is_active_session(self, session_id: str) -> bool:
|
140
140
|
return session_id in self._active_session_info_by_id
|
141
141
|
|
142
|
-
def list_active_sessions(self) ->
|
142
|
+
def list_active_sessions(self) -> list[ActiveSessionInfo]:
|
143
143
|
return list(self._active_session_info_by_id.values())
|
144
144
|
|
145
145
|
def close_session(self, session_id: str) -> None:
|
@@ -154,13 +154,13 @@ class WebsocketSessionManager(SessionManager):
|
|
154
154
|
self._session_storage.delete(session_id)
|
155
155
|
session_info.session.shutdown()
|
156
156
|
|
157
|
-
def get_session_info(self, session_id: str) ->
|
157
|
+
def get_session_info(self, session_id: str) -> SessionInfo | None:
|
158
158
|
session_info = self.get_active_session_info(session_id)
|
159
159
|
if session_info:
|
160
160
|
return cast(SessionInfo, session_info)
|
161
161
|
return self._session_storage.get(session_id)
|
162
162
|
|
163
|
-
def list_sessions(self) ->
|
163
|
+
def list_sessions(self) -> list[SessionInfo]:
|
164
164
|
return (
|
165
165
|
cast(List[SessionInfo], self.list_active_sessions())
|
166
166
|
+ self._session_storage.list()
|