streamlit-nightly 1.31.2.dev20240212__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 +21 -29
- 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/hashing.py +29 -21
- 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/legacy_caching/hashing.py +29 -25
- 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/stats.py +13 -15
- streamlit/runtime/uploaded_file_manager.py +6 -5
- streamlit/runtime/websocket_session_manager.py +14 -14
- streamlit/source_util.py +13 -11
- streamlit/static/asset-manifest.json +13 -13
- streamlit/static/index.html +1 -1
- streamlit/static/static/css/2411.8b8f33d6.chunk.css +1 -0
- streamlit/static/static/css/43.e3b876c5.chunk.css +1 -0
- streamlit/static/static/css/6692.65519639.chunk.css +1 -0
- streamlit/static/static/js/{3075.76725a14.chunk.js → 2411.714d213e.chunk.js} +2 -2
- streamlit/static/static/js/4185.21ca0590.chunk.js +1 -0
- streamlit/static/static/js/43.36939bb1.chunk.js +1 -0
- streamlit/static/static/js/{5117.6a701db1.chunk.js → 5117.04bfe5d3.chunk.js} +1 -1
- streamlit/static/static/js/{5791.30b01ee8.chunk.js → 5791.c5138157.chunk.js} +1 -1
- streamlit/static/static/js/656.8c998bc8.chunk.js +2 -0
- streamlit/static/static/js/{6692.6ac4ea6f.chunk.js → 6692.6496cbc2.chunk.js} +1 -1
- streamlit/static/static/js/7142.400eefdd.chunk.js +1 -0
- streamlit/static/static/js/main.2737c0f9.js +2 -0
- streamlit/static/static/js/{main.043d802e.js.LICENSE.txt → main.2737c0f9.js.LICENSE.txt} +23 -25
- streamlit/string_util.py +13 -9
- streamlit/temporary_directory.py +3 -1
- streamlit/testing/v1/element_tree.py +1 -2
- streamlit/testing/v1/util.py +7 -3
- streamlit/type_util.py +30 -25
- streamlit/url_util.py +6 -4
- streamlit/user_info.py +8 -6
- streamlit/util.py +23 -37
- streamlit/version.py +16 -9
- 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 +41 -34
- streamlit/web/server/server_util.py +8 -3
- streamlit/web/server/stats_request_handler.py +14 -5
- streamlit/web/server/upload_file_request_handler.py +7 -8
- streamlit/web/server/websocket_headers.py +2 -2
- {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/RECORD +176 -176
- streamlit/static/static/css/3075.81b3d18f.chunk.css +0 -1
- streamlit/static/static/css/43.c24b25fa.chunk.css +0 -1
- streamlit/static/static/css/6692.bb444a79.chunk.css +0 -1
- streamlit/static/static/js/1215.baf3721f.chunk.js +0 -2
- streamlit/static/static/js/4185.90e929dc.chunk.js +0 -1
- streamlit/static/static/js/43.8ca4bc8a.chunk.js +0 -1
- streamlit/static/static/js/7142.a359ed63.chunk.js +0 -1
- streamlit/static/static/js/main.043d802e.js +0 -2
- /streamlit/static/static/js/{3075.76725a14.chunk.js.LICENSE.txt → 2411.714d213e.chunk.js.LICENSE.txt} +0 -0
- /streamlit/static/static/js/{1215.baf3721f.chunk.js.LICENSE.txt → 656.8c998bc8.chunk.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.31.2.dev20240212.data → streamlit_nightly-1.31.2.dev20240214.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,9 @@
|
|
14
14
|
|
15
15
|
"""Runtime-related utility functions"""
|
16
16
|
|
17
|
-
from
|
17
|
+
from __future__ import annotations
|
18
|
+
|
19
|
+
from typing import Any
|
18
20
|
|
19
21
|
from streamlit import config
|
20
22
|
from streamlit.errors import MarkdownFormattedException
|
@@ -27,7 +29,7 @@ class MessageSizeError(MarkdownFormattedException):
|
|
27
29
|
|
28
30
|
def __init__(self, failed_msg_str: Any):
|
29
31
|
msg = self._get_message(failed_msg_str)
|
30
|
-
super(
|
32
|
+
super().__init__(msg)
|
31
33
|
|
32
34
|
def _get_message(self, failed_msg_str: Any) -> str:
|
33
35
|
# This needs to have zero indentation otherwise the markdown will render incorrectly.
|
@@ -82,7 +84,7 @@ def serialize_forward_msg(msg: ForwardMsg) -> bytes:
|
|
82
84
|
|
83
85
|
# This needs to be initialized lazily to avoid calling config.get_option() and
|
84
86
|
# thus initializing config options when this file is first imported.
|
85
|
-
_max_message_size_bytes:
|
87
|
+
_max_message_size_bytes: int | None = None
|
86
88
|
|
87
89
|
|
88
90
|
def get_max_message_size_bytes() -> int:
|
streamlit/runtime/script_data.py
CHANGED
@@ -12,9 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
import
|
15
|
+
from __future__ import annotations
|
16
16
|
|
17
|
-
|
17
|
+
import ast
|
18
|
+
from typing import Any, Final
|
18
19
|
|
19
20
|
from streamlit import config
|
20
21
|
|
@@ -24,7 +25,7 @@ from streamlit import config
|
|
24
25
|
MAGIC_MODULE_NAME: Final = "__streamlitmagic__"
|
25
26
|
|
26
27
|
|
27
|
-
def add_magic(code, script_path):
|
28
|
+
def add_magic(code: str, script_path: str) -> Any:
|
28
29
|
"""Modifies the code to support magic Streamlit commands.
|
29
30
|
|
30
31
|
Parameters
|
@@ -51,7 +52,10 @@ def add_magic(code, script_path):
|
|
51
52
|
|
52
53
|
|
53
54
|
def _modify_ast_subtree(
|
54
|
-
tree
|
55
|
+
tree: Any,
|
56
|
+
body_attr: str = "body",
|
57
|
+
is_root: bool = False,
|
58
|
+
file_ends_in_semicolon: bool = False,
|
55
59
|
):
|
56
60
|
"""Parses magic commands and modifies the given AST (sub)tree."""
|
57
61
|
|
@@ -118,7 +122,7 @@ def _modify_ast_subtree(
|
|
118
122
|
return tree
|
119
123
|
|
120
124
|
|
121
|
-
def _insert_import_statement(tree):
|
125
|
+
def _insert_import_statement(tree: Any) -> None:
|
122
126
|
"""Insert Streamlit import statement at the top(ish) of the tree."""
|
123
127
|
|
124
128
|
st_import = _build_st_import_statement()
|
@@ -226,11 +230,11 @@ def _get_st_write_from_expr(
|
|
226
230
|
return st_write
|
227
231
|
|
228
232
|
|
229
|
-
def _is_string_constant_node(node):
|
233
|
+
def _is_string_constant_node(node) -> bool:
|
230
234
|
return type(node) is ast.Constant and type(node.value) is str
|
231
235
|
|
232
236
|
|
233
|
-
def _is_docstring_node(node, node_index, parent_type):
|
237
|
+
def _is_docstring_node(node, node_index, parent_type) -> bool:
|
234
238
|
return (
|
235
239
|
node_index == 0
|
236
240
|
and _is_string_constant_node(node)
|
@@ -238,7 +242,7 @@ def _is_docstring_node(node, node_index, parent_type):
|
|
238
242
|
)
|
239
243
|
|
240
244
|
|
241
|
-
def _does_file_end_in_semicolon(tree, code):
|
245
|
+
def _does_file_end_in_semicolon(tree, code: str) -> bool:
|
242
246
|
file_ends_in_semicolon = False
|
243
247
|
|
244
248
|
# Avoid spending time with this operation if magic.displayLastExprIfNoSemicolon is
|
@@ -247,13 +251,15 @@ def _does_file_end_in_semicolon(tree, code):
|
|
247
251
|
last_line_num = getattr(tree.body[-1], "end_lineno", None)
|
248
252
|
|
249
253
|
if last_line_num is not None:
|
250
|
-
last_line_str = code.split("\n")[last_line_num - 1]
|
254
|
+
last_line_str: str = code.split("\n")[last_line_num - 1]
|
251
255
|
file_ends_in_semicolon = last_line_str.strip(" ").endswith(";")
|
252
256
|
|
253
257
|
return file_ends_in_semicolon
|
254
258
|
|
255
259
|
|
256
|
-
def _is_displayable_last_expr(
|
260
|
+
def _is_displayable_last_expr(
|
261
|
+
is_root: bool, is_last_expr: bool, file_ends_in_semicolon: bool
|
262
|
+
) -> bool:
|
257
263
|
return (
|
258
264
|
# This is a "displayable last expression" if...
|
259
265
|
# ...it's actually the last expression...
|
@@ -267,5 +273,5 @@ def _is_displayable_last_expr(is_root, is_last_expr, file_ends_in_semicolon):
|
|
267
273
|
)
|
268
274
|
|
269
275
|
|
270
|
-
def _should_display_docstring_like_node_anyway(is_root):
|
276
|
+
def _should_display_docstring_like_node_anyway(is_root: bool) -> bool:
|
271
277
|
return config.get_option("magic.displayRootDocString") and is_root
|
@@ -12,10 +12,12 @@
|
|
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 dataclasses import dataclass
|
17
19
|
from enum import Enum
|
18
|
-
from typing import
|
20
|
+
from typing import cast
|
19
21
|
|
20
22
|
from streamlit import util
|
21
23
|
from streamlit.proto.WidgetStates_pb2 import WidgetStates
|
@@ -41,7 +43,7 @@ class RerunData:
|
|
41
43
|
"""Data attached to RERUN requests. Immutable."""
|
42
44
|
|
43
45
|
query_string: str = ""
|
44
|
-
widget_states:
|
46
|
+
widget_states: WidgetStates | None = None
|
45
47
|
page_script_hash: str = ""
|
46
48
|
page_name: str = ""
|
47
49
|
|
@@ -54,7 +56,7 @@ class ScriptRequest:
|
|
54
56
|
"""A STOP or RERUN request and associated data."""
|
55
57
|
|
56
58
|
type: ScriptRequestType
|
57
|
-
_rerun_data:
|
59
|
+
_rerun_data: RerunData | None = None
|
58
60
|
|
59
61
|
@property
|
60
62
|
def rerun_data(self) -> RerunData:
|
@@ -141,7 +143,7 @@ class ScriptRequests:
|
|
141
143
|
# We'll never get here
|
142
144
|
raise RuntimeError(f"Unrecognized ScriptRunnerState: {self._state}")
|
143
145
|
|
144
|
-
def on_scriptrunner_yield(self) ->
|
146
|
+
def on_scriptrunner_yield(self) -> ScriptRequest | None:
|
145
147
|
"""Called by the ScriptRunner when it's at a yield point.
|
146
148
|
|
147
149
|
If we have no request, return None.
|
@@ -12,14 +12,16 @@
|
|
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 collections
|
16
18
|
import contextvars
|
17
19
|
import threading
|
18
20
|
from dataclasses import dataclass, field
|
19
|
-
from typing import Callable, Counter, Dict,
|
21
|
+
from typing import Callable, Counter, Dict, Final, Union
|
20
22
|
from urllib import parse
|
21
23
|
|
22
|
-
from typing_extensions import
|
24
|
+
from typing_extensions import TypeAlias
|
23
25
|
|
24
26
|
from streamlit import runtime
|
25
27
|
from streamlit.errors import StreamlitAPIException
|
@@ -30,16 +32,16 @@ from streamlit.runtime.scriptrunner.script_requests import ScriptRequests
|
|
30
32
|
from streamlit.runtime.state import SafeSessionState
|
31
33
|
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
32
34
|
|
33
|
-
|
35
|
+
_LOGGER: Final = get_logger(__name__)
|
34
36
|
|
35
|
-
UserInfo: TypeAlias = Dict[str,
|
37
|
+
UserInfo: TypeAlias = Dict[str, Union[str, None]]
|
36
38
|
|
37
39
|
|
38
40
|
# The dg_stack tracks the currently active DeltaGenerator, and is pushed to when
|
39
41
|
# a DeltaGenerator is entered via a `with` block. This is implemented as a ContextVar
|
40
42
|
# so that different threads or async tasks can have their own stacks.
|
41
43
|
dg_stack: contextvars.ContextVar[
|
42
|
-
|
44
|
+
tuple["streamlit.delta_generator.DeltaGenerator", ...]
|
43
45
|
] = contextvars.ContextVar("dg_stack", default=tuple())
|
44
46
|
|
45
47
|
|
@@ -69,15 +71,15 @@ class ScriptRunContext:
|
|
69
71
|
|
70
72
|
gather_usage_stats: bool = False
|
71
73
|
command_tracking_deactivated: bool = False
|
72
|
-
tracked_commands:
|
74
|
+
tracked_commands: list[Command] = field(default_factory=list)
|
73
75
|
tracked_commands_counter: Counter[str] = field(default_factory=collections.Counter)
|
74
76
|
_set_page_config_allowed: bool = True
|
75
77
|
_has_script_started: bool = False
|
76
|
-
widget_ids_this_run:
|
77
|
-
widget_user_keys_this_run:
|
78
|
-
form_ids_this_run:
|
79
|
-
cursors:
|
80
|
-
script_requests:
|
78
|
+
widget_ids_this_run: set[str] = field(default_factory=set)
|
79
|
+
widget_user_keys_this_run: set[str] = field(default_factory=set)
|
80
|
+
form_ids_this_run: set[str] = field(default_factory=set)
|
81
|
+
cursors: dict[int, "streamlit.cursor.RunningCursor"] = field(default_factory=dict)
|
82
|
+
script_requests: ScriptRequests | None = None
|
81
83
|
|
82
84
|
# TODO(willhuang1997): Remove this variable when experimental query params are removed
|
83
85
|
_experimental_query_params_used = False
|
@@ -153,7 +155,7 @@ SCRIPT_RUN_CONTEXT_ATTR_NAME: Final = "streamlit_script_run_ctx"
|
|
153
155
|
|
154
156
|
|
155
157
|
def add_script_run_ctx(
|
156
|
-
thread:
|
158
|
+
thread: threading.Thread | None = None, ctx: ScriptRunContext | None = None
|
157
159
|
):
|
158
160
|
"""Adds the current ScriptRunContext to a newly-created thread.
|
159
161
|
|
@@ -183,7 +185,7 @@ def add_script_run_ctx(
|
|
183
185
|
return thread
|
184
186
|
|
185
187
|
|
186
|
-
def get_script_run_ctx(suppress_warning: bool = False) ->
|
188
|
+
def get_script_run_ctx(suppress_warning: bool = False) -> ScriptRunContext | None:
|
187
189
|
"""
|
188
190
|
Parameters
|
189
191
|
----------
|
@@ -196,15 +198,13 @@ def get_script_run_ctx(suppress_warning: bool = False) -> Optional[ScriptRunCont
|
|
196
198
|
|
197
199
|
"""
|
198
200
|
thread = threading.current_thread()
|
199
|
-
ctx:
|
200
|
-
thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None
|
201
|
-
)
|
201
|
+
ctx: ScriptRunContext | None = getattr(thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None)
|
202
202
|
if ctx is None and runtime.exists() and not suppress_warning:
|
203
203
|
# Only warn about a missing ScriptRunContext if suppress_warning is False, and
|
204
204
|
# we were started via `streamlit run`. Otherwise, the user is likely running a
|
205
205
|
# script "bare", and doesn't need to be warned about streamlit
|
206
206
|
# bits that are irrelevant when not connected to a session.
|
207
|
-
|
207
|
+
_LOGGER.warning("Thread '%s': missing ScriptRunContext", thread.name)
|
208
208
|
|
209
209
|
return ctx
|
210
210
|
|
@@ -12,6 +12,8 @@
|
|
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 gc
|
16
18
|
import sys
|
17
19
|
import threading
|
@@ -19,7 +21,7 @@ import types
|
|
19
21
|
from contextlib import contextmanager
|
20
22
|
from enum import Enum
|
21
23
|
from timeit import default_timer as timer
|
22
|
-
from typing import Callable,
|
24
|
+
from typing import Callable, Final
|
23
25
|
|
24
26
|
from blinker import Signal
|
25
27
|
|
@@ -47,7 +49,7 @@ from streamlit.runtime.state import (
|
|
47
49
|
from streamlit.runtime.uploaded_file_manager import UploadedFileManager
|
48
50
|
from streamlit.vendor.ipython.modified_sys_path import modified_sys_path
|
49
51
|
|
50
|
-
_LOGGER = get_logger(__name__)
|
52
|
+
_LOGGER: Final = get_logger(__name__)
|
51
53
|
|
52
54
|
|
53
55
|
class ScriptRunnerEvent(Enum):
|
@@ -103,7 +105,7 @@ class ScriptRunner:
|
|
103
105
|
uploaded_file_mgr: UploadedFileManager,
|
104
106
|
script_cache: ScriptCache,
|
105
107
|
initial_rerun_data: RerunData,
|
106
|
-
user_info:
|
108
|
+
user_info: dict[str, str | None],
|
107
109
|
):
|
108
110
|
"""Initialize the ScriptRunner.
|
109
111
|
|
@@ -181,7 +183,7 @@ class ScriptRunner:
|
|
181
183
|
self._execing = False
|
182
184
|
|
183
185
|
# This is initialized in start()
|
184
|
-
self._script_thread:
|
186
|
+
self._script_thread: threading.Thread | None = None
|
185
187
|
|
186
188
|
def __repr__(self) -> str:
|
187
189
|
return util.repr_(self)
|
@@ -493,7 +495,7 @@ class ScriptRunner:
|
|
493
495
|
|
494
496
|
# This will be set to a RerunData instance if our execution
|
495
497
|
# is interrupted by a RerunException.
|
496
|
-
rerun_exception_data:
|
498
|
+
rerun_exception_data: RerunData | None = None
|
497
499
|
|
498
500
|
# If the script stops early, we don't want to remove unseen widgets,
|
499
501
|
# so we track this to potentially skip session state cleanup later.
|
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
|