streamlit-nightly 1.33.1.dev20240416__py2.py3-none-any.whl → 1.33.1.dev20240418__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/components/v1/custom_component.py +2 -0
- streamlit/delta_generator.py +0 -5
- streamlit/elements/__init__.py +0 -57
- streamlit/elements/arrow_vega_lite.py +8 -1
- streamlit/elements/form.py +5 -1
- streamlit/elements/spinner.py +16 -30
- streamlit/elements/utils.py +36 -1
- streamlit/elements/widgets/button.py +20 -1
- streamlit/elements/widgets/camera_input.py +3 -0
- streamlit/elements/widgets/chat.py +8 -1
- streamlit/elements/widgets/checkbox.py +3 -1
- streamlit/elements/widgets/color_picker.py +3 -0
- streamlit/elements/widgets/data_editor.py +10 -1
- streamlit/elements/widgets/file_uploader.py +3 -0
- streamlit/elements/widgets/multiselect.py +13 -6
- streamlit/elements/widgets/number_input.py +8 -0
- streamlit/elements/widgets/radio.py +9 -0
- streamlit/elements/widgets/select_slider.py +4 -0
- streamlit/elements/widgets/selectbox.py +8 -1
- streamlit/elements/widgets/slider.py +3 -1
- streamlit/elements/widgets/text_widgets.py +13 -2
- streamlit/elements/widgets/time_widgets.py +27 -10
- streamlit/runtime/caching/__init__.py +1 -19
- streamlit/runtime/caching/cache_data_api.py +8 -2
- streamlit/runtime/caching/cache_errors.py +0 -38
- streamlit/runtime/caching/cache_resource_api.py +8 -2
- streamlit/runtime/caching/cache_utils.py +26 -9
- streamlit/runtime/caching/cached_message_replay.py +25 -67
- streamlit/runtime/fragment.py +1 -1
- streamlit/runtime/legacy_caching/__init__.py +2 -12
- streamlit/runtime/legacy_caching/caching.py +1 -80
- streamlit/runtime/scriptrunner/script_run_context.py +4 -0
- streamlit/static/asset-manifest.json +3 -3
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/43.b0aa5759.chunk.js +1 -0
- streamlit/static/static/js/{main.713dd29d.js → main.81ad100d.js} +2 -2
- {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/METADATA +3 -3
- {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/RECORD +43 -43
- streamlit/static/static/js/43.9ae03282.chunk.js +0 -1
- /streamlit/static/static/js/{main.713dd29d.js.LICENSE.txt → main.81ad100d.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.33.1.dev20240416.data → streamlit_nightly-1.33.1.dev20240418.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/top_level.txt +0 -0
@@ -20,6 +20,7 @@ from typing import TYPE_CHECKING, Literal, cast, overload
|
|
20
20
|
|
21
21
|
from streamlit.elements.form import current_form_id
|
22
22
|
from streamlit.elements.utils import (
|
23
|
+
check_cache_replay_rules,
|
23
24
|
check_callback_rules,
|
24
25
|
check_session_state_rules,
|
25
26
|
get_label_visibility_proto_value,
|
@@ -33,6 +34,7 @@ from streamlit.runtime.state import (
|
|
33
34
|
WidgetArgs,
|
34
35
|
WidgetCallback,
|
35
36
|
WidgetKwargs,
|
37
|
+
get_session_state,
|
36
38
|
register_widget,
|
37
39
|
)
|
38
40
|
from streamlit.runtime.state.common import compute_widget_id
|
@@ -254,9 +256,9 @@ class TextWidgetsMixin:
|
|
254
256
|
ctx: ScriptRunContext | None = None,
|
255
257
|
) -> str | None:
|
256
258
|
key = to_key(key)
|
259
|
+
check_cache_replay_rules()
|
257
260
|
check_callback_rules(self.dg, on_change)
|
258
261
|
check_session_state_rules(default_value=None if value == "" else value, key=key)
|
259
|
-
|
260
262
|
maybe_raise_label_warnings(label, label_visibility)
|
261
263
|
|
262
264
|
# Make sure value is always string or None:
|
@@ -277,6 +279,10 @@ class TextWidgetsMixin:
|
|
277
279
|
page=ctx.page_script_hash if ctx else None,
|
278
280
|
)
|
279
281
|
|
282
|
+
session_state = get_session_state().filtered_state
|
283
|
+
if key is not None and key in session_state and session_state[key] is None:
|
284
|
+
value = None
|
285
|
+
|
280
286
|
text_input_proto = TextInputProto()
|
281
287
|
text_input_proto.id = id
|
282
288
|
text_input_proto.label = label
|
@@ -515,9 +521,10 @@ class TextWidgetsMixin:
|
|
515
521
|
ctx: ScriptRunContext | None = None,
|
516
522
|
) -> str | None:
|
517
523
|
key = to_key(key)
|
524
|
+
|
525
|
+
check_cache_replay_rules()
|
518
526
|
check_callback_rules(self.dg, on_change)
|
519
527
|
check_session_state_rules(default_value=None if value == "" else value, key=key)
|
520
|
-
|
521
528
|
maybe_raise_label_warnings(label, label_visibility)
|
522
529
|
|
523
530
|
value = str(value) if value is not None else None
|
@@ -536,6 +543,10 @@ class TextWidgetsMixin:
|
|
536
543
|
page=ctx.page_script_hash if ctx else None,
|
537
544
|
)
|
538
545
|
|
546
|
+
session_state = get_session_state().filtered_state
|
547
|
+
if key is not None and key in session_state and session_state[key] is None:
|
548
|
+
value = None
|
549
|
+
|
539
550
|
text_area_proto = TextAreaProto()
|
540
551
|
text_area_proto.id = id
|
541
552
|
text_area_proto.label = label
|
@@ -21,6 +21,7 @@ from typing import (
|
|
21
21
|
TYPE_CHECKING,
|
22
22
|
Any,
|
23
23
|
Final,
|
24
|
+
List,
|
24
25
|
Literal,
|
25
26
|
Sequence,
|
26
27
|
Tuple,
|
@@ -33,6 +34,7 @@ from typing_extensions import TypeAlias
|
|
33
34
|
|
34
35
|
from streamlit.elements.form import current_form_id
|
35
36
|
from streamlit.elements.utils import (
|
37
|
+
check_cache_replay_rules,
|
36
38
|
check_callback_rules,
|
37
39
|
check_session_state_rules,
|
38
40
|
get_label_visibility_proto_value,
|
@@ -78,7 +80,6 @@ def _parse_date_value(
|
|
78
80
|
if value == "today":
|
79
81
|
parsed_dates = [datetime.now().date()]
|
80
82
|
elif value == "default_value_today":
|
81
|
-
# Set value default.
|
82
83
|
parsed_dates = [datetime.now().date()]
|
83
84
|
elif isinstance(value, datetime):
|
84
85
|
parsed_dates = [value.date()]
|
@@ -158,17 +159,27 @@ class _DateInputValues:
|
|
158
159
|
max_value: SingleDateValue,
|
159
160
|
) -> _DateInputValues:
|
160
161
|
parsed_value, is_range = _parse_date_value(value=value)
|
162
|
+
parsed_min = _parse_min_date(
|
163
|
+
min_value=min_value,
|
164
|
+
parsed_dates=parsed_value,
|
165
|
+
)
|
166
|
+
parsed_max = _parse_max_date(
|
167
|
+
max_value=max_value,
|
168
|
+
parsed_dates=parsed_value,
|
169
|
+
)
|
170
|
+
|
171
|
+
if value == "default_value_today":
|
172
|
+
v = cast(List[date], parsed_value)[0]
|
173
|
+
if v < parsed_min:
|
174
|
+
parsed_value = [parsed_min]
|
175
|
+
if v > parsed_max:
|
176
|
+
parsed_value = [parsed_max]
|
177
|
+
|
161
178
|
return cls(
|
162
179
|
value=parsed_value,
|
163
180
|
is_range=is_range,
|
164
|
-
min=
|
165
|
-
|
166
|
-
parsed_dates=parsed_value,
|
167
|
-
),
|
168
|
-
max=_parse_max_date(
|
169
|
-
max_value=max_value,
|
170
|
-
parsed_dates=parsed_value,
|
171
|
-
),
|
181
|
+
min=parsed_min,
|
182
|
+
max=parsed_max,
|
172
183
|
)
|
173
184
|
|
174
185
|
def __post_init__(self) -> None:
|
@@ -413,6 +424,7 @@ class TimeWidgetsMixin:
|
|
413
424
|
ctx: ScriptRunContext | None = None,
|
414
425
|
) -> time | None:
|
415
426
|
key = to_key(key)
|
427
|
+
check_cache_replay_rules()
|
416
428
|
check_callback_rules(self.dg, on_change)
|
417
429
|
check_session_state_rules(
|
418
430
|
default_value=value if value != "now" else None, key=key
|
@@ -447,6 +459,10 @@ class TimeWidgetsMixin:
|
|
447
459
|
)
|
448
460
|
del value
|
449
461
|
|
462
|
+
session_state = get_session_state().filtered_state
|
463
|
+
if key is not None and key in session_state and session_state[key] is None:
|
464
|
+
parsed_time = None
|
465
|
+
|
450
466
|
time_input_proto = TimeInputProto()
|
451
467
|
time_input_proto.id = id
|
452
468
|
time_input_proto.label = label
|
@@ -668,11 +684,12 @@ class TimeWidgetsMixin:
|
|
668
684
|
ctx: ScriptRunContext | None = None,
|
669
685
|
) -> DateWidgetReturn:
|
670
686
|
key = to_key(key)
|
687
|
+
|
688
|
+
check_cache_replay_rules()
|
671
689
|
check_callback_rules(self.dg, on_change)
|
672
690
|
check_session_state_rules(
|
673
691
|
default_value=value if value != "default_value_today" else None, key=key
|
674
692
|
)
|
675
|
-
|
676
693
|
maybe_raise_label_warnings(label, label_visibility)
|
677
694
|
|
678
695
|
def parse_date_deterministic(
|
@@ -14,8 +14,7 @@
|
|
14
14
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
-
import
|
18
|
-
from typing import Any, Iterator
|
17
|
+
from typing import Any
|
19
18
|
|
20
19
|
from google.protobuf.message import Message
|
21
20
|
|
@@ -84,21 +83,6 @@ def save_media_data(image_data: bytes | str, mimetype: str, image_id: str) -> No
|
|
84
83
|
CACHE_RESOURCE_MESSAGE_REPLAY_CTX.save_image_data(image_data, mimetype, image_id)
|
85
84
|
|
86
85
|
|
87
|
-
def maybe_show_cached_st_function_warning(dg, st_func_name: str) -> None:
|
88
|
-
CACHE_DATA_MESSAGE_REPLAY_CTX.maybe_show_cached_st_function_warning(
|
89
|
-
dg, st_func_name
|
90
|
-
)
|
91
|
-
CACHE_RESOURCE_MESSAGE_REPLAY_CTX.maybe_show_cached_st_function_warning(
|
92
|
-
dg, st_func_name
|
93
|
-
)
|
94
|
-
|
95
|
-
|
96
|
-
@contextlib.contextmanager
|
97
|
-
def suppress_cached_st_function_warning() -> Iterator[None]:
|
98
|
-
with CACHE_DATA_MESSAGE_REPLAY_CTX.suppress_cached_st_function_warning(), CACHE_RESOURCE_MESSAGE_REPLAY_CTX.suppress_cached_st_function_warning():
|
99
|
-
yield
|
100
|
-
|
101
|
-
|
102
86
|
# Explicitly export public symbols
|
103
87
|
from streamlit.runtime.caching.cache_data_api import get_data_cache_stats_provider
|
104
88
|
from streamlit.runtime.caching.cache_resource_api import (
|
@@ -136,8 +120,6 @@ __all__ = [
|
|
136
120
|
"save_block_message",
|
137
121
|
"save_widget_metadata",
|
138
122
|
"save_media_data",
|
139
|
-
"maybe_show_cached_st_function_warning",
|
140
|
-
"suppress_cached_st_function_warning",
|
141
123
|
"get_data_cache_stats_provider",
|
142
124
|
"get_resource_cache_stats_provider",
|
143
125
|
"cache_data",
|
@@ -513,6 +513,9 @@ class CacheDataAPI:
|
|
513
513
|
... # Fetch data from _db_connection here, and then clean it up.
|
514
514
|
... return data
|
515
515
|
...
|
516
|
+
>>> fetch_and_clean_data.clear(_db_connection, 50)
|
517
|
+
>>> # Clear the cached entry for the arguments provided.
|
518
|
+
>>>
|
516
519
|
>>> fetch_and_clean_data.clear()
|
517
520
|
>>> # Clear all cached entries for this function.
|
518
521
|
|
@@ -701,8 +704,11 @@ class DataCache(Cache):
|
|
701
704
|
|
702
705
|
self.storage.set(key, pickled_entry)
|
703
706
|
|
704
|
-
def _clear(self) -> None:
|
705
|
-
|
707
|
+
def _clear(self, key: str | None = None) -> None:
|
708
|
+
if not key:
|
709
|
+
self.storage.clear()
|
710
|
+
else:
|
711
|
+
self.storage.delete(key)
|
706
712
|
|
707
713
|
def _read_multi_results_from_storage(self, key: str) -> MultiCacheResults:
|
708
714
|
"""Look up the results from storage and ensure it has the right type.
|
@@ -96,44 +96,6 @@ class CacheError(Exception):
|
|
96
96
|
pass
|
97
97
|
|
98
98
|
|
99
|
-
class CachedStFunctionWarning(StreamlitAPIWarning):
|
100
|
-
def __init__(
|
101
|
-
self,
|
102
|
-
cache_type: CacheType,
|
103
|
-
st_func_name: str,
|
104
|
-
cached_func: types.FunctionType,
|
105
|
-
):
|
106
|
-
args = {
|
107
|
-
"st_func_name": f"`st.{st_func_name}()`",
|
108
|
-
"func_name": self._get_cached_func_name_md(cached_func),
|
109
|
-
"decorator_name": get_decorator_api_name(cache_type),
|
110
|
-
}
|
111
|
-
|
112
|
-
msg = (
|
113
|
-
"""
|
114
|
-
Your script uses %(st_func_name)s to write to your Streamlit app from within
|
115
|
-
some cached code at %(func_name)s. This code will only be called when we detect
|
116
|
-
a cache "miss", which can lead to unexpected results.
|
117
|
-
|
118
|
-
How to fix this:
|
119
|
-
* Move the %(st_func_name)s call outside %(func_name)s.
|
120
|
-
* Or, if you know what you're doing, use `@st.%(decorator_name)s(experimental_allow_widgets=True)`
|
121
|
-
to enable widget replay and suppress this warning.
|
122
|
-
"""
|
123
|
-
% args
|
124
|
-
).strip("\n")
|
125
|
-
|
126
|
-
super().__init__(msg)
|
127
|
-
|
128
|
-
@staticmethod
|
129
|
-
def _get_cached_func_name_md(func: types.FunctionType) -> str:
|
130
|
-
"""Get markdown representation of the function name."""
|
131
|
-
if hasattr(func, "__name__"):
|
132
|
-
return "`%s()`" % func.__name__
|
133
|
-
else:
|
134
|
-
return "a cached function"
|
135
|
-
|
136
|
-
|
137
99
|
class CacheReplayClosureError(StreamlitAPIException):
|
138
100
|
def __init__(
|
139
101
|
self,
|
@@ -384,6 +384,9 @@ class CacheResourceAPI:
|
|
384
384
|
... # Create a database connection object that points to the URL.
|
385
385
|
... return connection
|
386
386
|
...
|
387
|
+
>>> fetch_and_clean_data.clear(_sessionmaker, "https://streamlit.io/")
|
388
|
+
>>> # Clear the cached entry for the arguments provided.
|
389
|
+
>>>
|
387
390
|
>>> get_database_session.clear()
|
388
391
|
>>> # Clear all cached entries for this function.
|
389
392
|
|
@@ -549,9 +552,12 @@ class ResourceCache(Cache):
|
|
549
552
|
multi_results.results[widget_key] = result
|
550
553
|
self._mem_cache[key] = multi_results
|
551
554
|
|
552
|
-
def _clear(self) -> None:
|
555
|
+
def _clear(self, key: str | None = None) -> None:
|
553
556
|
with self._mem_cache_lock:
|
554
|
-
|
557
|
+
if key is None:
|
558
|
+
self._mem_cache.clear()
|
559
|
+
elif key in self._mem_cache:
|
560
|
+
del self._mem_cache[key]
|
555
561
|
|
556
562
|
def get_stats(self) -> list[CacheStat]:
|
557
563
|
# Shallow clone our cache. Computing item sizes is potentially
|
@@ -102,14 +102,19 @@ class Cache:
|
|
102
102
|
with self._value_locks_lock:
|
103
103
|
return self._value_locks[value_key]
|
104
104
|
|
105
|
-
def clear(self):
|
106
|
-
"""Clear
|
105
|
+
def clear(self, key: str | None = None):
|
106
|
+
"""Clear values from this cache.
|
107
|
+
If no argument is passed, all items are cleared from the cache.
|
108
|
+
A key can be passed to clear that key from the cache only."""
|
107
109
|
with self._value_locks_lock:
|
108
|
-
|
109
|
-
|
110
|
+
if not key:
|
111
|
+
self._value_locks.clear()
|
112
|
+
elif key in self._value_locks:
|
113
|
+
del self._value_locks[key]
|
114
|
+
self._clear(key=key)
|
110
115
|
|
111
116
|
@abstractmethod
|
112
|
-
def _clear(self) -> None:
|
117
|
+
def _clear(self, key: str | None = None) -> None:
|
113
118
|
"""Subclasses must implement this to perform cache-clearing logic."""
|
114
119
|
raise NotImplementedError
|
115
120
|
|
@@ -154,7 +159,7 @@ def make_cached_func_wrapper(info: CachedFuncInfo) -> Callable[..., Any]:
|
|
154
159
|
value otherwise.
|
155
160
|
|
156
161
|
The wrapper also has a `clear` function that can be called to clear
|
157
|
-
all of the wrapper's cached values.
|
162
|
+
some or all of the wrapper's cached values.
|
158
163
|
"""
|
159
164
|
cached_func = CachedFunc(info)
|
160
165
|
|
@@ -303,10 +308,22 @@ class CachedFunc:
|
|
303
308
|
return_value=computed_value, func=self._info.func
|
304
309
|
)
|
305
310
|
|
306
|
-
def clear(self):
|
307
|
-
"""Clear the wrapped function's associated cache.
|
311
|
+
def clear(self, *args, **kwargs):
|
312
|
+
"""Clear the wrapped function's associated cache.
|
313
|
+
If no arguments are passed, clear the cache of all values.
|
314
|
+
If args/kwargs are provided, clear the cached value for these arguments only."""
|
308
315
|
cache = self._info.get_function_cache(self._function_key)
|
309
|
-
|
316
|
+
if args or kwargs:
|
317
|
+
key = _make_value_key(
|
318
|
+
cache_type=self._info.cache_type,
|
319
|
+
func=self._info.func,
|
320
|
+
func_args=args,
|
321
|
+
func_kwargs=kwargs,
|
322
|
+
hash_funcs=self._info.hash_funcs,
|
323
|
+
)
|
324
|
+
else:
|
325
|
+
key = None
|
326
|
+
cache.clear(key=key)
|
310
327
|
|
311
328
|
|
312
329
|
def _make_value_key(
|
@@ -33,13 +33,9 @@ from google.protobuf.message import Message
|
|
33
33
|
|
34
34
|
import streamlit as st
|
35
35
|
from streamlit import runtime, util
|
36
|
-
from streamlit.elements import NONWIDGET_ELEMENTS, WIDGETS
|
37
36
|
from streamlit.logger import get_logger
|
38
37
|
from streamlit.proto.Block_pb2 import Block
|
39
|
-
from streamlit.runtime.caching.cache_errors import
|
40
|
-
CachedStFunctionWarning,
|
41
|
-
CacheReplayClosureError,
|
42
|
-
)
|
38
|
+
from streamlit.runtime.caching.cache_errors import CacheReplayClosureError
|
43
39
|
from streamlit.runtime.caching.cache_type import CacheType
|
44
40
|
from streamlit.runtime.caching.hashing import update_hash
|
45
41
|
from streamlit.runtime.scriptrunner.script_run_context import (
|
@@ -239,15 +235,13 @@ class CachedMessageReplayContext(threading.local):
|
|
239
235
|
"""
|
240
236
|
|
241
237
|
def __init__(self, cache_type: CacheType):
|
242
|
-
self._cached_func_stack: list[types.FunctionType] = []
|
243
|
-
self._suppress_st_function_warning = 0
|
244
238
|
self._cached_message_stack: list[list[MsgData]] = []
|
245
239
|
self._seen_dg_stack: list[set[str]] = []
|
246
240
|
self._most_recent_messages: list[MsgData] = []
|
247
241
|
self._registered_metadata: WidgetMetadata[Any] | None = None
|
248
242
|
self._media_data: list[MediaMsgData] = []
|
249
243
|
self._cache_type = cache_type
|
250
|
-
self._allow_widgets:
|
244
|
+
self._allow_widgets: bool = False
|
251
245
|
|
252
246
|
def __repr__(self) -> str:
|
253
247
|
return util.repr_(self)
|
@@ -260,19 +254,36 @@ class CachedMessageReplayContext(threading.local):
|
|
260
254
|
It allows us to track any `st.foo` messages that are generated from inside the function
|
261
255
|
for playback during cache retrieval.
|
262
256
|
"""
|
263
|
-
self._cached_func_stack.append(func)
|
264
257
|
self._cached_message_stack.append([])
|
265
258
|
self._seen_dg_stack.append(set())
|
266
|
-
|
267
|
-
|
259
|
+
self._allow_widgets = allow_widgets
|
260
|
+
|
261
|
+
nested_call = False
|
262
|
+
ctx = get_script_run_ctx()
|
263
|
+
if ctx:
|
264
|
+
if ctx.disallow_cached_widget_usage:
|
265
|
+
# The disallow_cached_widget_usage is already set to true.
|
266
|
+
# This indicates that this cached function run is called from another
|
267
|
+
# cached function that disallows widget usage.
|
268
|
+
# We need to deactivate the widget usage for this cached function run
|
269
|
+
# even if it was allowed.
|
270
|
+
self._allow_widgets = False
|
271
|
+
nested_call = True
|
272
|
+
|
273
|
+
if not self._allow_widgets:
|
274
|
+
# If we're in a cached function that disallows widget usage, we need to set
|
275
|
+
# the disallow_cached_widget_usage to true for this cached function run
|
276
|
+
# to prevent widget usage (triggers a warning).
|
277
|
+
ctx.disallow_cached_widget_usage = True
|
268
278
|
try:
|
269
279
|
yield
|
270
280
|
finally:
|
271
|
-
self._cached_func_stack.pop()
|
272
281
|
self._most_recent_messages = self._cached_message_stack.pop()
|
273
282
|
self._seen_dg_stack.pop()
|
274
|
-
if
|
275
|
-
|
283
|
+
if ctx and not nested_call:
|
284
|
+
# Reset the disallow_cached_widget_usage flag. But only if this
|
285
|
+
# is not nested inside a cached function that disallows widget usage.
|
286
|
+
ctx.disallow_cached_widget_usage = False
|
276
287
|
|
277
288
|
def save_element_message(
|
278
289
|
self,
|
@@ -365,59 +376,6 @@ class CachedMessageReplayContext(threading.local):
|
|
365
376
|
) -> None:
|
366
377
|
self._media_data.append(MediaMsgData(image_data, mimetype, image_id))
|
367
378
|
|
368
|
-
@contextlib.contextmanager
|
369
|
-
def suppress_cached_st_function_warning(self) -> Iterator[None]:
|
370
|
-
self._suppress_st_function_warning += 1
|
371
|
-
try:
|
372
|
-
yield
|
373
|
-
finally:
|
374
|
-
self._suppress_st_function_warning -= 1
|
375
|
-
assert self._suppress_st_function_warning >= 0
|
376
|
-
|
377
|
-
def maybe_show_cached_st_function_warning(
|
378
|
-
self,
|
379
|
-
dg: DeltaGenerator,
|
380
|
-
st_func_name: str,
|
381
|
-
) -> None:
|
382
|
-
"""If appropriate, warn about calling st.foo inside @st.cache_data.
|
383
|
-
|
384
|
-
DeltaGenerator's @_with_element and @_widget wrappers use this to warn
|
385
|
-
the user when they're calling st.foo() from within a function that is
|
386
|
-
wrapped in @st.cache.
|
387
|
-
|
388
|
-
Parameters
|
389
|
-
----------
|
390
|
-
dg : DeltaGenerator
|
391
|
-
The DeltaGenerator to publish the warning to.
|
392
|
-
|
393
|
-
st_func_name : str
|
394
|
-
The name of the Streamlit function that was called.
|
395
|
-
|
396
|
-
"""
|
397
|
-
# There are some elements not in either list, which we still want to warn about.
|
398
|
-
# Ideally we will fix this by either updating the lists or creating a better
|
399
|
-
# way of categorizing elements.
|
400
|
-
if st_func_name in NONWIDGET_ELEMENTS:
|
401
|
-
return
|
402
|
-
if st_func_name in WIDGETS and self._allow_widgets > 0:
|
403
|
-
return
|
404
|
-
|
405
|
-
if len(self._cached_func_stack) > 0 and self._suppress_st_function_warning <= 0:
|
406
|
-
cached_func = self._cached_func_stack[-1]
|
407
|
-
self._show_cached_st_function_warning(dg, st_func_name, cached_func)
|
408
|
-
|
409
|
-
def _show_cached_st_function_warning(
|
410
|
-
self,
|
411
|
-
dg: DeltaGenerator,
|
412
|
-
st_func_name: str,
|
413
|
-
cached_func: types.FunctionType,
|
414
|
-
) -> None:
|
415
|
-
# Avoid infinite recursion by suppressing additional cached
|
416
|
-
# function warnings from within the cached function warning.
|
417
|
-
with self.suppress_cached_st_function_warning():
|
418
|
-
e = CachedStFunctionWarning(self._cache_type, st_func_name, cached_func)
|
419
|
-
dg.exception(e)
|
420
|
-
|
421
379
|
|
422
380
|
def replay_cached_messages(
|
423
381
|
result: CachedResult, cache_type: CacheType, cached_func: types.FunctionType
|
streamlit/runtime/fragment.py
CHANGED
@@ -140,7 +140,7 @@ def fragment(
|
|
140
140
|
with each fragment rerun, until the next full-script rerun.
|
141
141
|
|
142
142
|
Calling `st.sidebar` in a fragment is not supported. To write elements to
|
143
|
-
the sidebar with a fragment, call your fragment
|
143
|
+
the sidebar with a fragment, call your fragment function inside a
|
144
144
|
`with st.sidebar` context manager.
|
145
145
|
|
146
146
|
Fragment code can interact with Session State, imported modules, and
|
@@ -12,16 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from streamlit.runtime.legacy_caching.caching import
|
16
|
-
cache,
|
17
|
-
clear_cache,
|
18
|
-
get_cache_path,
|
19
|
-
maybe_show_cached_st_function_warning,
|
20
|
-
)
|
15
|
+
from streamlit.runtime.legacy_caching.caching import cache, clear_cache, get_cache_path
|
21
16
|
|
22
|
-
__all__ = [
|
23
|
-
"cache",
|
24
|
-
"clear_cache",
|
25
|
-
"get_cache_path",
|
26
|
-
"maybe_show_cached_st_function_warning",
|
27
|
-
]
|
17
|
+
__all__ = ["cache", "clear_cache", "get_cache_path"]
|
@@ -236,7 +236,6 @@ _mem_caches = _MemCaches()
|
|
236
236
|
class ThreadLocalCacheInfo(threading.local):
|
237
237
|
def __init__(self):
|
238
238
|
self.cached_func_stack: list[Callable[..., Any]] = []
|
239
|
-
self.suppress_st_function_warning = 0
|
240
239
|
|
241
240
|
def __repr__(self) -> str:
|
242
241
|
return util.repr_(self)
|
@@ -254,54 +253,6 @@ def _calling_cached_function(func: Callable[..., Any]) -> Iterator[None]:
|
|
254
253
|
_cache_info.cached_func_stack.pop()
|
255
254
|
|
256
255
|
|
257
|
-
@contextlib.contextmanager
|
258
|
-
def suppress_cached_st_function_warning() -> Iterator[None]:
|
259
|
-
_cache_info.suppress_st_function_warning += 1
|
260
|
-
try:
|
261
|
-
yield
|
262
|
-
finally:
|
263
|
-
_cache_info.suppress_st_function_warning -= 1
|
264
|
-
assert _cache_info.suppress_st_function_warning >= 0
|
265
|
-
|
266
|
-
|
267
|
-
def _show_cached_st_function_warning(
|
268
|
-
dg: st.delta_generator.DeltaGenerator,
|
269
|
-
st_func_name: str,
|
270
|
-
cached_func: Callable[..., Any],
|
271
|
-
) -> None:
|
272
|
-
# Avoid infinite recursion by suppressing additional cached
|
273
|
-
# function warnings from within the cached function warning.
|
274
|
-
with suppress_cached_st_function_warning():
|
275
|
-
e = CachedStFunctionWarning(st_func_name, cached_func)
|
276
|
-
dg.exception(e)
|
277
|
-
|
278
|
-
|
279
|
-
def maybe_show_cached_st_function_warning(
|
280
|
-
dg: st.delta_generator.DeltaGenerator, st_func_name: str
|
281
|
-
) -> None:
|
282
|
-
"""If appropriate, warn about calling st.foo inside @cache.
|
283
|
-
|
284
|
-
DeltaGenerator's @_with_element and @_widget wrappers use this to warn
|
285
|
-
the user when they're calling st.foo() from within a function that is
|
286
|
-
wrapped in @st.cache.
|
287
|
-
|
288
|
-
Parameters
|
289
|
-
----------
|
290
|
-
dg : DeltaGenerator
|
291
|
-
The DeltaGenerator to publish the warning to.
|
292
|
-
|
293
|
-
st_func_name : str
|
294
|
-
The name of the Streamlit function that was called.
|
295
|
-
|
296
|
-
"""
|
297
|
-
if (
|
298
|
-
len(_cache_info.cached_func_stack) > 0
|
299
|
-
and _cache_info.suppress_st_function_warning <= 0
|
300
|
-
):
|
301
|
-
cached_func = _cache_info.cached_func_stack[-1]
|
302
|
-
_show_cached_st_function_warning(dg, st_func_name, cached_func)
|
303
|
-
|
304
|
-
|
305
256
|
def _read_from_mem_cache(
|
306
257
|
mem_cache: MemCache,
|
307
258
|
key: str,
|
@@ -683,11 +634,7 @@ def cache(
|
|
683
634
|
_LOGGER.debug("Cache miss: %s", non_optional_func)
|
684
635
|
|
685
636
|
with _calling_cached_function(non_optional_func):
|
686
|
-
|
687
|
-
with suppress_cached_st_function_warning():
|
688
|
-
return_value = non_optional_func(*args, **kwargs)
|
689
|
-
else:
|
690
|
-
return_value = non_optional_func(*args, **kwargs)
|
637
|
+
return_value = non_optional_func(*args, **kwargs)
|
691
638
|
|
692
639
|
_write_to_cache(
|
693
640
|
mem_cache=mem_cache,
|
@@ -826,32 +773,6 @@ class CachedObjectMutationError(ValueError):
|
|
826
773
|
return util.repr_(self)
|
827
774
|
|
828
775
|
|
829
|
-
class CachedStFunctionWarning(StreamlitAPIWarning):
|
830
|
-
def __init__(self, st_func_name, cached_func):
|
831
|
-
msg = self._get_message(st_func_name, cached_func)
|
832
|
-
super().__init__(msg)
|
833
|
-
|
834
|
-
def _get_message(self, st_func_name, cached_func):
|
835
|
-
args = {
|
836
|
-
"st_func_name": "`st.%s()` or `st.write()`" % st_func_name,
|
837
|
-
"func_name": _get_cached_func_name_md(cached_func),
|
838
|
-
}
|
839
|
-
|
840
|
-
return (
|
841
|
-
"""
|
842
|
-
Your script uses %(st_func_name)s to write to your Streamlit app from within
|
843
|
-
some cached code at %(func_name)s. This code will only be called when we detect
|
844
|
-
a cache "miss", which can lead to unexpected results.
|
845
|
-
|
846
|
-
How to fix this:
|
847
|
-
* Move the %(st_func_name)s call outside %(func_name)s.
|
848
|
-
* Or, if you know what you're doing, use `@st.cache(suppress_st_warning=True)`
|
849
|
-
to suppress the warning.
|
850
|
-
"""
|
851
|
-
% args
|
852
|
-
).strip("\n")
|
853
|
-
|
854
|
-
|
855
776
|
class CachedObjectMutationWarning(StreamlitAPIWarning):
|
856
777
|
def __init__(self, orig_exc):
|
857
778
|
msg = self._get_message(orig_exc)
|
@@ -79,6 +79,9 @@ class ScriptRunContext:
|
|
79
79
|
fragment_ids_this_run: set[str] | None = None
|
80
80
|
# we allow only one dialog to be open at the same time
|
81
81
|
has_dialog_opened: bool = False
|
82
|
+
# If true, it indicates that we are in a cached function that disallows
|
83
|
+
# the usage of widgets.
|
84
|
+
disallow_cached_widget_usage: bool = False
|
82
85
|
|
83
86
|
# TODO(willhuang1997): Remove this variable when experimental query params are removed
|
84
87
|
_experimental_query_params_used = False
|
@@ -105,6 +108,7 @@ class ScriptRunContext:
|
|
105
108
|
self.current_fragment_id = None
|
106
109
|
self.fragment_ids_this_run = fragment_ids_this_run
|
107
110
|
self.has_dialog_opened = False
|
111
|
+
self.disallow_cached_widget_usage = False
|
108
112
|
|
109
113
|
parsed_query_params = parse.parse_qs(query_string, keep_blank_values=True)
|
110
114
|
with self.session_state.query_params() as qp:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"files": {
|
3
3
|
"main.css": "./static/css/main.bf304093.css",
|
4
|
-
"main.js": "./static/js/main.
|
4
|
+
"main.js": "./static/js/main.81ad100d.js",
|
5
5
|
"static/js/9336.2d95d840.chunk.js": "./static/js/9336.2d95d840.chunk.js",
|
6
6
|
"static/js/9330.d29313d4.chunk.js": "./static/js/9330.d29313d4.chunk.js",
|
7
7
|
"static/js/7217.d970c074.chunk.js": "./static/js/7217.d970c074.chunk.js",
|
@@ -9,7 +9,7 @@
|
|
9
9
|
"static/css/3092.95a45cfe.chunk.css": "./static/css/3092.95a45cfe.chunk.css",
|
10
10
|
"static/js/3092.152fd2b7.chunk.js": "./static/js/3092.152fd2b7.chunk.js",
|
11
11
|
"static/css/43.e3b876c5.chunk.css": "./static/css/43.e3b876c5.chunk.css",
|
12
|
-
"static/js/43.
|
12
|
+
"static/js/43.b0aa5759.chunk.js": "./static/js/43.b0aa5759.chunk.js",
|
13
13
|
"static/js/8427.d30dffe1.chunk.js": "./static/js/8427.d30dffe1.chunk.js",
|
14
14
|
"static/js/7323.2808d029.chunk.js": "./static/js/7323.2808d029.chunk.js",
|
15
15
|
"static/js/4185.935c68ec.chunk.js": "./static/js/4185.935c68ec.chunk.js",
|
@@ -152,6 +152,6 @@
|
|
152
152
|
},
|
153
153
|
"entrypoints": [
|
154
154
|
"static/css/main.bf304093.css",
|
155
|
-
"static/js/main.
|
155
|
+
"static/js/main.81ad100d.js"
|
156
156
|
]
|
157
157
|
}
|
streamlit/static/index.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><link rel="shortcut icon" href="./favicon.png"/><link rel="preload" href="./static/media/SourceSansPro-Regular.0d69e5ff5e92ac64a0c9.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-SemiBold.abed79cd0df1827e18cf.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-Bold.118dea98980e20a81ced.woff2" as="font" type="font/woff2" crossorigin><title>Streamlit</title><script>window.prerenderReady=!1</script><script defer="defer" src="./static/js/main.
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><link rel="shortcut icon" href="./favicon.png"/><link rel="preload" href="./static/media/SourceSansPro-Regular.0d69e5ff5e92ac64a0c9.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-SemiBold.abed79cd0df1827e18cf.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-Bold.118dea98980e20a81ced.woff2" as="font" type="font/woff2" crossorigin><title>Streamlit</title><script>window.prerenderReady=!1</script><script defer="defer" src="./static/js/main.81ad100d.js"></script><link href="./static/css/main.bf304093.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|