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
@@ -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 contextlib
|
16
18
|
import inspect
|
17
19
|
import os
|
@@ -21,17 +23,14 @@ import time
|
|
21
23
|
import uuid
|
22
24
|
from collections.abc import Sized
|
23
25
|
from functools import wraps
|
24
|
-
from
|
25
|
-
from typing import Any, Callable, List, Optional, Set, TypeVar, Union, cast, overload
|
26
|
-
|
27
|
-
from typing_extensions import Final
|
26
|
+
from typing import Any, Callable, Final, TypeVar, cast, overload
|
28
27
|
|
29
28
|
from streamlit import config, util
|
30
29
|
from streamlit.logger import get_logger
|
31
30
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
32
31
|
from streamlit.proto.PageProfile_pb2 import Argument, Command
|
33
32
|
|
34
|
-
_LOGGER = get_logger(__name__)
|
33
|
+
_LOGGER: Final = get_logger(__name__)
|
35
34
|
|
36
35
|
# Limit the number of commands to keep the page profile message small
|
37
36
|
# since Segment allows only a maximum of 32kb per event.
|
@@ -161,11 +160,11 @@ def _get_machine_id_v3() -> str:
|
|
161
160
|
|
162
161
|
machine_id = str(uuid.getnode())
|
163
162
|
if os.path.isfile(_ETC_MACHINE_ID_PATH):
|
164
|
-
with open(_ETC_MACHINE_ID_PATH
|
163
|
+
with open(_ETC_MACHINE_ID_PATH) as f:
|
165
164
|
machine_id = f.read()
|
166
165
|
|
167
166
|
elif os.path.isfile(_DBUS_MACHINE_ID_PATH):
|
168
|
-
with open(_DBUS_MACHINE_ID_PATH
|
167
|
+
with open(_DBUS_MACHINE_ID_PATH) as f:
|
169
168
|
machine_id = f.read()
|
170
169
|
|
171
170
|
return machine_id
|
@@ -173,10 +172,10 @@ def _get_machine_id_v3() -> str:
|
|
173
172
|
|
174
173
|
class Installation:
|
175
174
|
_instance_lock = threading.Lock()
|
176
|
-
_instance:
|
175
|
+
_instance: Installation | None = None
|
177
176
|
|
178
177
|
@classmethod
|
179
|
-
def instance(cls) ->
|
178
|
+
def instance(cls) -> Installation:
|
180
179
|
"""Returns the singleton Installation"""
|
181
180
|
# We use a double-checked locking optimization to avoid the overhead
|
182
181
|
# of acquiring the lock in the common case:
|
@@ -228,7 +227,7 @@ def _get_top_level_module(func: Callable[..., Any]) -> str:
|
|
228
227
|
return module.__name__.split(".")[0]
|
229
228
|
|
230
229
|
|
231
|
-
def _get_arg_metadata(arg: object) ->
|
230
|
+
def _get_arg_metadata(arg: object) -> str | None:
|
232
231
|
"""Get metadata information related to the value of the given object."""
|
233
232
|
with contextlib.suppress(Exception):
|
234
233
|
if isinstance(arg, (bool)):
|
@@ -245,8 +244,8 @@ def _get_command_telemetry(
|
|
245
244
|
) -> Command:
|
246
245
|
"""Get telemetry information for the given callable and its arguments."""
|
247
246
|
arg_keywords = inspect.getfullargspec(_command_func).args
|
248
|
-
self_arg:
|
249
|
-
arguments:
|
247
|
+
self_arg: Any | None = None
|
248
|
+
arguments: list[Argument] = []
|
250
249
|
is_method = inspect.ismethod(_command_func)
|
251
250
|
name = _command_name
|
252
251
|
|
@@ -315,7 +314,7 @@ def gather_metrics(
|
|
315
314
|
...
|
316
315
|
|
317
316
|
|
318
|
-
def gather_metrics(name: str, func:
|
317
|
+
def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
|
319
318
|
"""Function decorator to add telemetry tracking to commands.
|
320
319
|
|
321
320
|
Parameters
|
@@ -351,11 +350,13 @@ def gather_metrics(name: str, func: Optional[F] = None) -> Union[Callable[[F], F
|
|
351
350
|
|
352
351
|
return wrapper
|
353
352
|
else:
|
354
|
-
# To make mypy type narrow
|
353
|
+
# To make mypy type narrow F | None -> F
|
355
354
|
non_optional_func = func
|
356
355
|
|
357
356
|
@wraps(non_optional_func)
|
358
357
|
def wrapped_func(*args, **kwargs):
|
358
|
+
from timeit import default_timer as timer
|
359
|
+
|
359
360
|
exec_start = timer()
|
360
361
|
# Local imports to prevent circular dependencies
|
361
362
|
from streamlit.runtime.scriptrunner import get_script_run_ctx
|
@@ -371,8 +372,7 @@ def gather_metrics(name: str, func: Optional[F] = None) -> Union[Callable[[F], F
|
|
371
372
|
< _MAX_TRACKED_COMMANDS # Prevent too much memory usage
|
372
373
|
)
|
373
374
|
|
374
|
-
|
375
|
-
command_telemetry: Optional[Command] = None
|
375
|
+
command_telemetry: Command | None = None
|
376
376
|
|
377
377
|
if ctx and tracking_activated:
|
378
378
|
try:
|
@@ -421,10 +421,10 @@ def gather_metrics(name: str, func: Optional[F] = None) -> Union[Callable[[F], F
|
|
421
421
|
|
422
422
|
|
423
423
|
def create_page_profile_message(
|
424
|
-
commands:
|
424
|
+
commands: list[Command],
|
425
425
|
exec_time: int,
|
426
426
|
prep_time: int,
|
427
|
-
uncaught_exception:
|
427
|
+
uncaught_exception: str | None = None,
|
428
428
|
) -> ForwardMsg:
|
429
429
|
"""Create and return the full PageProfile ForwardMsg."""
|
430
430
|
msg = ForwardMsg()
|
@@ -435,7 +435,7 @@ def create_page_profile_message(
|
|
435
435
|
msg.page_profile.headless = config.get_option("server.headless")
|
436
436
|
|
437
437
|
# Collect all config options that have been manually set
|
438
|
-
config_options:
|
438
|
+
config_options: set[str] = set()
|
439
439
|
if config._config_options:
|
440
440
|
for option_name in config._config_options.keys():
|
441
441
|
if not config.is_manually_set(option_name):
|
@@ -450,7 +450,7 @@ def create_page_profile_message(
|
|
450
450
|
msg.page_profile.config.extend(config_options)
|
451
451
|
|
452
452
|
# Check the predefined set of modules for attribution
|
453
|
-
attributions:
|
453
|
+
attributions: set[str] = {
|
454
454
|
attribution
|
455
455
|
for attribution in _ATTRIBUTIONS_TO_CHECK
|
456
456
|
if attribution in sys.modules
|
streamlit/runtime/runtime.py
CHANGED
@@ -19,9 +19,7 @@ import time
|
|
19
19
|
import traceback
|
20
20
|
from dataclasses import dataclass, field
|
21
21
|
from enum import Enum
|
22
|
-
from typing import TYPE_CHECKING, Awaitable,
|
23
|
-
|
24
|
-
from typing_extensions import Final
|
22
|
+
from typing import TYPE_CHECKING, Awaitable, Final, NamedTuple
|
25
23
|
|
26
24
|
from streamlit import config
|
27
25
|
from streamlit.logger import get_logger
|
@@ -69,7 +67,7 @@ if TYPE_CHECKING:
|
|
69
67
|
# Wait for the script run result for 60s and if no result is available give up
|
70
68
|
SCRIPT_RUN_CHECK_TIMEOUT: Final = 60
|
71
69
|
|
72
|
-
|
70
|
+
_LOGGER: Final = get_logger(__name__)
|
73
71
|
|
74
72
|
|
75
73
|
class RuntimeStoppedError(Exception):
|
@@ -85,7 +83,7 @@ class RuntimeConfig:
|
|
85
83
|
|
86
84
|
# DEPRECATED: We need to keep this field around for compatibility reasons, but we no
|
87
85
|
# longer use this anywhere.
|
88
|
-
command_line:
|
86
|
+
command_line: str | None
|
89
87
|
|
90
88
|
# The storage backend for Streamlit's MediaFileManager.
|
91
89
|
media_file_storage: MediaFileStorage
|
@@ -99,7 +97,7 @@ class RuntimeConfig:
|
|
99
97
|
)
|
100
98
|
|
101
99
|
# The SessionManager class to be used.
|
102
|
-
session_manager_class:
|
100
|
+
session_manager_class: type[SessionManager] = WebsocketSessionManager
|
103
101
|
|
104
102
|
# The SessionStorage instance for the SessionManager to use.
|
105
103
|
session_storage: SessionStorage = field(default_factory=MemorySessionStorage)
|
@@ -141,7 +139,7 @@ class AsyncObjects(NamedTuple):
|
|
141
139
|
|
142
140
|
|
143
141
|
class Runtime:
|
144
|
-
_instance:
|
142
|
+
_instance: Runtime | None = None
|
145
143
|
|
146
144
|
@classmethod
|
147
145
|
def instance(cls) -> Runtime:
|
@@ -179,11 +177,11 @@ class Runtime:
|
|
179
177
|
Runtime._instance = self
|
180
178
|
|
181
179
|
# Will be created when we start.
|
182
|
-
self._async_objs:
|
180
|
+
self._async_objs: AsyncObjects | None = None
|
183
181
|
|
184
182
|
# The task that runs our main loop. We need to save a reference
|
185
183
|
# to it so that it doesn't get garbage collected while running.
|
186
|
-
self._loop_coroutine_task:
|
184
|
+
self._loop_coroutine_task: asyncio.Task[None] | None = None
|
187
185
|
|
188
186
|
self._main_script_path = config.script_path
|
189
187
|
self._is_hello = config.is_hello
|
@@ -247,7 +245,7 @@ class Runtime:
|
|
247
245
|
# happen to be threadsafe. This may change with future SessionManager implementations,
|
248
246
|
# at which point we'll need to formalize our thread safety rules for each
|
249
247
|
# SessionManager method.
|
250
|
-
def get_client(self, session_id: str) ->
|
248
|
+
def get_client(self, session_id: str) -> SessionClient | None:
|
251
249
|
"""Get the SessionClient for the given session_id, or None
|
252
250
|
if no such session exists.
|
253
251
|
|
@@ -304,7 +302,7 @@ class Runtime:
|
|
304
302
|
if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
|
305
303
|
return
|
306
304
|
|
307
|
-
|
305
|
+
_LOGGER.debug("Runtime stopping...")
|
308
306
|
self._set_state(RuntimeState.STOPPING)
|
309
307
|
async_objs.must_stop.set()
|
310
308
|
|
@@ -322,9 +320,9 @@ class Runtime:
|
|
322
320
|
def connect_session(
|
323
321
|
self,
|
324
322
|
client: SessionClient,
|
325
|
-
user_info:
|
326
|
-
existing_session_id:
|
327
|
-
session_id_override:
|
323
|
+
user_info: dict[str, str | None],
|
324
|
+
existing_session_id: str | None = None,
|
325
|
+
session_id_override: str | None = None,
|
328
326
|
) -> str:
|
329
327
|
"""Create a new session (or connect to an existing one) and return its unique ID.
|
330
328
|
|
@@ -383,9 +381,9 @@ class Runtime:
|
|
383
381
|
def create_session(
|
384
382
|
self,
|
385
383
|
client: SessionClient,
|
386
|
-
user_info:
|
387
|
-
existing_session_id:
|
388
|
-
session_id_override:
|
384
|
+
user_info: dict[str, str | None],
|
385
|
+
existing_session_id: str | None = None,
|
386
|
+
session_id_override: str | None = None,
|
389
387
|
) -> str:
|
390
388
|
"""Create a new session (or connect to an existing one) and return its unique ID.
|
391
389
|
|
@@ -394,7 +392,7 @@ class Runtime:
|
|
394
392
|
This method is simply an alias for connect_session added for backwards
|
395
393
|
compatibility.
|
396
394
|
"""
|
397
|
-
|
395
|
+
_LOGGER.warning("create_session is deprecated! Use connect_session instead.")
|
398
396
|
return self.connect_session(
|
399
397
|
client=client,
|
400
398
|
user_info=user_info,
|
@@ -478,7 +476,7 @@ class Runtime:
|
|
478
476
|
|
479
477
|
session_info = self._session_mgr.get_active_session_info(session_id)
|
480
478
|
if session_info is None:
|
481
|
-
|
479
|
+
_LOGGER.debug(
|
482
480
|
"Discarding BackMsg for disconnected session (id=%s)", session_id
|
483
481
|
)
|
484
482
|
return
|
@@ -508,7 +506,7 @@ class Runtime:
|
|
508
506
|
|
509
507
|
session_info = self._session_mgr.get_active_session_info(session_id)
|
510
508
|
if session_info is None:
|
511
|
-
|
509
|
+
_LOGGER.debug(
|
512
510
|
"Discarding BackMsg Exception for disconnected session (id=%s)",
|
513
511
|
session_id,
|
514
512
|
)
|
@@ -517,7 +515,7 @@ class Runtime:
|
|
517
515
|
session_info.session.handle_backmsg_exception(exc)
|
518
516
|
|
519
517
|
@property
|
520
|
-
async def is_ready_for_browser_connection(self) ->
|
518
|
+
async def is_ready_for_browser_connection(self) -> tuple[bool, str]:
|
521
519
|
if self._state not in (
|
522
520
|
RuntimeState.INITIAL,
|
523
521
|
RuntimeState.STOPPING,
|
@@ -527,7 +525,7 @@ class Runtime:
|
|
527
525
|
|
528
526
|
return False, "unavailable"
|
529
527
|
|
530
|
-
async def does_script_run_without_error(self) ->
|
528
|
+
async def does_script_run_without_error(self) -> tuple[bool, str]:
|
531
529
|
"""Load and execute the app's script to verify it runs without an error.
|
532
530
|
|
533
531
|
Returns
|
@@ -572,7 +570,7 @@ class Runtime:
|
|
572
570
|
session.shutdown()
|
573
571
|
|
574
572
|
def _set_state(self, new_state: RuntimeState) -> None:
|
575
|
-
|
573
|
+
_LOGGER.debug("Runtime state: %s -> %s", self._state, new_state)
|
576
574
|
self._state = new_state
|
577
575
|
|
578
576
|
async def _loop_coroutine(self) -> None:
|
@@ -655,7 +653,7 @@ class Runtime:
|
|
655
653
|
except Exception as e:
|
656
654
|
async_objs.stopped.set_exception(e)
|
657
655
|
traceback.print_exc()
|
658
|
-
|
656
|
+
_LOGGER.info(
|
659
657
|
"""
|
660
658
|
Please report this bug at https://github.com/streamlit/streamlit/issues.
|
661
659
|
"""
|
@@ -689,13 +687,13 @@ Please report this bug at https://github.com/streamlit/streamlit/issues.
|
|
689
687
|
):
|
690
688
|
# This session has probably cached this message. Send
|
691
689
|
# a reference instead.
|
692
|
-
|
690
|
+
_LOGGER.debug("Sending cached message ref (hash=%s)", msg.hash)
|
693
691
|
msg_to_send = create_reference_msg(msg)
|
694
692
|
|
695
693
|
# Cache the message so it can be referenced in the future.
|
696
694
|
# If the message is already cached, this will reset its
|
697
695
|
# age.
|
698
|
-
|
696
|
+
_LOGGER.debug("Caching message (hash=%s)", msg.hash)
|
699
697
|
self._message_cache.add_message(
|
700
698
|
msg, session_info.session, session_info.script_run_count
|
701
699
|
)
|
@@ -706,7 +704,7 @@ Please report this bug at https://github.com/streamlit/streamlit/issues.
|
|
706
704
|
msg.WhichOneof("type") == "script_finished"
|
707
705
|
and msg.script_finished == ForwardMsg.FINISHED_SUCCESSFULLY
|
708
706
|
):
|
709
|
-
|
707
|
+
_LOGGER.debug(
|
710
708
|
"Script run finished successfully; "
|
711
709
|
"removing expired entries from MessageCache "
|
712
710
|
"(max_age=%s)",
|
@@ -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.
|