streamlit-nightly 1.37.2.dev20240819__py2.py3-none-any.whl → 1.37.2.dev20240822__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/elements/arrow.py +33 -8
- streamlit/elements/code.py +7 -0
- streamlit/elements/image.py +15 -25
- streamlit/elements/json.py +12 -5
- streamlit/elements/lib/column_types.py +3 -3
- streamlit/elements/lib/policies.py +10 -9
- streamlit/elements/map.py +13 -18
- streamlit/elements/vega_charts.py +6 -14
- streamlit/elements/widgets/button_group.py +2 -2
- streamlit/elements/widgets/data_editor.py +9 -6
- streamlit/elements/widgets/multiselect.py +4 -4
- streamlit/elements/widgets/radio.py +43 -4
- streamlit/elements/widgets/select_slider.py +63 -11
- streamlit/elements/widgets/selectbox.py +4 -4
- streamlit/elements/write.py +1 -1
- streamlit/proto/Code_pb2.py +2 -2
- streamlit/proto/Code_pb2.pyi +4 -1
- streamlit/runtime/caching/__init__.py +1 -11
- streamlit/runtime/caching/cache_data_api.py +10 -81
- streamlit/runtime/caching/cache_errors.py +13 -9
- streamlit/runtime/caching/cache_resource_api.py +8 -56
- streamlit/runtime/caching/cache_utils.py +7 -12
- streamlit/runtime/caching/cached_message_replay.py +29 -185
- streamlit/runtime/caching/legacy_cache_api.py +15 -11
- streamlit/runtime/scriptrunner_utils/script_run_context.py +9 -4
- streamlit/runtime/state/widgets.py +0 -5
- streamlit/static/asset-manifest.json +24 -24
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{1074.0db34d15.chunk.js → 1074.9d1e63cc.chunk.js} +1 -1
- streamlit/static/static/js/{1116.22f8322c.chunk.js → 1116.85ec79d5.chunk.js} +1 -1
- streamlit/static/static/js/{1168.2a9806f0.chunk.js → 1168.7c30158a.chunk.js} +1 -1
- streamlit/static/static/js/1307.2bdac721.chunk.js +1 -0
- streamlit/static/static/js/{1451.d93e956f.chunk.js → 1451.7ff31fc7.chunk.js} +1 -1
- streamlit/static/static/js/1792.d126bbd9.chunk.js +1 -0
- streamlit/static/static/js/3513.5e3a04f2.chunk.js +1 -0
- streamlit/static/static/js/3599.963d0e5a.chunk.js +5 -0
- streamlit/static/static/js/{4335.bc097c4d.chunk.js → 4335.b166a7b6.chunk.js} +1 -1
- streamlit/static/static/js/{4477.edb1d80a.chunk.js → 4477.568118b6.chunk.js} +1 -1
- streamlit/static/static/js/5106.62135ac5.chunk.js +1 -0
- streamlit/static/static/js/{5441.4cdb2690.chunk.js → 5441.63087272.chunk.js} +1 -1
- streamlit/static/static/js/6013.b6375a8d.chunk.js +5 -0
- streamlit/static/static/js/6718.f5745d2b.chunk.js +1 -0
- streamlit/static/static/js/{7175.70728640.chunk.js → 7175.a10184bd.chunk.js} +1 -1
- streamlit/static/static/js/{7323.4e64ad2c.chunk.js → 7323.05e7058a.chunk.js} +2 -2
- streamlit/static/static/js/7602.a6e1d802.chunk.js +1 -0
- streamlit/static/static/js/7702.b905bebd.chunk.js +1 -0
- streamlit/static/static/js/7805.23670b3c.chunk.js +1 -0
- streamlit/static/static/js/8148.8bd2f9d3.chunk.js +1 -0
- streamlit/static/static/js/8536.bdf41383.chunk.js +1 -0
- streamlit/static/static/js/8691.ee55fefc.chunk.js +5 -0
- streamlit/static/static/js/main.33cac65c.js +28 -0
- {streamlit_nightly-1.37.2.dev20240819.dist-info → streamlit_nightly-1.37.2.dev20240822.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.37.2.dev20240819.dist-info → streamlit_nightly-1.37.2.dev20240822.dist-info}/RECORD +59 -59
- {streamlit_nightly-1.37.2.dev20240819.dist-info → streamlit_nightly-1.37.2.dev20240822.dist-info}/WHEEL +1 -1
- streamlit/static/static/js/1307.74a443f7.chunk.js +0 -1
- streamlit/static/static/js/1792.eb8a836f.chunk.js +0 -1
- streamlit/static/static/js/3513.577f3dc5.chunk.js +0 -1
- streamlit/static/static/js/3599.eaeac234.chunk.js +0 -5
- streamlit/static/static/js/4666.0e91bb87.chunk.js +0 -1
- streamlit/static/static/js/5106.4c60cfa4.chunk.js +0 -1
- streamlit/static/static/js/6013.fb4531df.chunk.js +0 -5
- streamlit/static/static/js/6718.6fb2aa21.chunk.js +0 -1
- streamlit/static/static/js/7602.33571c14.chunk.js +0 -1
- streamlit/static/static/js/7805.ba32ae70.chunk.js +0 -1
- streamlit/static/static/js/8148.b905db99.chunk.js +0 -1
- streamlit/static/static/js/8536.b7b2ef90.chunk.js +0 -1
- streamlit/static/static/js/8691.93a29403.chunk.js +0 -5
- streamlit/static/static/js/main.8c6fc86e.js +0 -28
- /streamlit/static/static/js/{7323.4e64ad2c.chunk.js.LICENSE.txt → 7323.05e7058a.chunk.js.LICENSE.txt} +0 -0
- /streamlit/static/static/js/{main.8c6fc86e.js.LICENSE.txt → main.33cac65c.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.37.2.dev20240819.data → streamlit_nightly-1.37.2.dev20240822.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.37.2.dev20240819.dist-info → streamlit_nightly-1.37.2.dev20240822.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.37.2.dev20240819.dist-info → streamlit_nightly-1.37.2.dev20240822.dist-info}/top_level.txt +0 -0
streamlit/proto/Code_pb2.py
CHANGED
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|
14
14
|
|
15
15
|
|
16
16
|
|
17
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1astreamlit/proto/Code.proto\"
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1astreamlit/proto/Code.proto\"Z\n\x04\x43ode\x12\x11\n\tcode_text\x18\x01 \x01(\t\x12\x10\n\x08language\x18\x02 \x01(\t\x12\x19\n\x11show_line_numbers\x18\x03 \x01(\x08\x12\x12\n\nwrap_lines\x18\x04 \x01(\x08\x42)\n\x1c\x63om.snowflake.apps.streamlitB\tCodeProtob\x06proto3')
|
18
18
|
|
19
19
|
_globals = globals()
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -23,5 +23,5 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
23
23
|
_globals['DESCRIPTOR']._loaded_options = None
|
24
24
|
_globals['DESCRIPTOR']._serialized_options = b'\n\034com.snowflake.apps.streamlitB\tCodeProto'
|
25
25
|
_globals['_CODE']._serialized_start=30
|
26
|
-
_globals['_CODE']._serialized_end=
|
26
|
+
_globals['_CODE']._serialized_end=120
|
27
27
|
# @@protoc_insertion_point(module_scope)
|
streamlit/proto/Code_pb2.pyi
CHANGED
@@ -33,17 +33,20 @@ class Code(google.protobuf.message.Message):
|
|
33
33
|
CODE_TEXT_FIELD_NUMBER: builtins.int
|
34
34
|
LANGUAGE_FIELD_NUMBER: builtins.int
|
35
35
|
SHOW_LINE_NUMBERS_FIELD_NUMBER: builtins.int
|
36
|
+
WRAP_LINES_FIELD_NUMBER: builtins.int
|
36
37
|
code_text: builtins.str
|
37
38
|
"""Content to display."""
|
38
39
|
language: builtins.str
|
39
40
|
show_line_numbers: builtins.bool
|
41
|
+
wrap_lines: builtins.bool
|
40
42
|
def __init__(
|
41
43
|
self,
|
42
44
|
*,
|
43
45
|
code_text: builtins.str = ...,
|
44
46
|
language: builtins.str = ...,
|
45
47
|
show_line_numbers: builtins.bool = ...,
|
48
|
+
wrap_lines: builtins.bool = ...,
|
46
49
|
) -> None: ...
|
47
|
-
def ClearField(self, field_name: typing.Literal["code_text", b"code_text", "language", b"language", "show_line_numbers", b"show_line_numbers"]) -> None: ...
|
50
|
+
def ClearField(self, field_name: typing.Literal["code_text", b"code_text", "language", b"language", "show_line_numbers", b"show_line_numbers", "wrap_lines", b"wrap_lines"]) -> None: ...
|
48
51
|
|
49
52
|
global___Code = Code
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
-
from typing import TYPE_CHECKING
|
17
|
+
from typing import TYPE_CHECKING
|
18
18
|
|
19
19
|
from streamlit.runtime.caching.cache_data_api import (
|
20
20
|
CACHE_DATA_MESSAGE_REPLAY_CTX,
|
@@ -33,7 +33,6 @@ if TYPE_CHECKING:
|
|
33
33
|
from google.protobuf.message import Message
|
34
34
|
|
35
35
|
from streamlit.proto.Block_pb2 import Block
|
36
|
-
from streamlit.runtime.state.common import WidgetMetadata
|
37
36
|
|
38
37
|
|
39
38
|
def save_element_message(
|
@@ -73,14 +72,6 @@ def save_block_message(
|
|
73
72
|
)
|
74
73
|
|
75
74
|
|
76
|
-
def save_widget_metadata(metadata: WidgetMetadata[Any]) -> None:
|
77
|
-
"""Save a widget's metadata to a thread-local callstack, so the widget
|
78
|
-
can be registered again when that widget is replayed.
|
79
|
-
"""
|
80
|
-
CACHE_DATA_MESSAGE_REPLAY_CTX.save_widget_metadata(metadata)
|
81
|
-
CACHE_RESOURCE_MESSAGE_REPLAY_CTX.save_widget_metadata(metadata)
|
82
|
-
|
83
|
-
|
84
75
|
def save_media_data(image_data: bytes | str, mimetype: str, image_id: str) -> None:
|
85
76
|
CACHE_DATA_MESSAGE_REPLAY_CTX.save_image_data(image_data, mimetype, image_id)
|
86
77
|
CACHE_RESOURCE_MESSAGE_REPLAY_CTX.save_image_data(image_data, mimetype, image_id)
|
@@ -99,7 +90,6 @@ __all__ = [
|
|
99
90
|
"CACHE_DOCS_URL",
|
100
91
|
"save_element_message",
|
101
92
|
"save_block_message",
|
102
|
-
"save_widget_metadata",
|
103
93
|
"save_media_data",
|
104
94
|
"get_data_cache_stats_provider",
|
105
95
|
"get_resource_cache_stats_provider",
|
@@ -47,9 +47,7 @@ from streamlit.runtime.caching.cache_utils import (
|
|
47
47
|
from streamlit.runtime.caching.cached_message_replay import (
|
48
48
|
CachedMessageReplayContext,
|
49
49
|
CachedResult,
|
50
|
-
ElementMsgData,
|
51
50
|
MsgData,
|
52
|
-
MultiCacheResults,
|
53
51
|
show_widget_replay_deprecation,
|
54
52
|
)
|
55
53
|
from streamlit.runtime.caching.storage import (
|
@@ -66,7 +64,6 @@ from streamlit.runtime.caching.storage.dummy_cache_storage import (
|
|
66
64
|
MemoryCacheStorageManager,
|
67
65
|
)
|
68
66
|
from streamlit.runtime.metrics_util import gather_metrics
|
69
|
-
from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
|
70
67
|
from streamlit.runtime.stats import CacheStat, CacheStatsProvider, group_stats
|
71
68
|
from streamlit.time_util import time_to_seconds
|
72
69
|
|
@@ -93,13 +90,11 @@ class CachedDataFuncInfo(CachedFuncInfo):
|
|
93
90
|
persist: CachePersistType,
|
94
91
|
max_entries: int | None,
|
95
92
|
ttl: float | timedelta | str | None,
|
96
|
-
allow_widgets: bool,
|
97
93
|
hash_funcs: HashFuncsDict | None = None,
|
98
94
|
):
|
99
95
|
super().__init__(
|
100
96
|
func,
|
101
97
|
show_spinner=show_spinner,
|
102
|
-
allow_widgets=allow_widgets,
|
103
98
|
hash_funcs=hash_funcs,
|
104
99
|
)
|
105
100
|
self.persist = persist
|
@@ -128,7 +123,6 @@ class CachedDataFuncInfo(CachedFuncInfo):
|
|
128
123
|
max_entries=self.max_entries,
|
129
124
|
ttl=self.ttl,
|
130
125
|
display_name=self.display_name,
|
131
|
-
allow_widgets=self.allow_widgets,
|
132
126
|
)
|
133
127
|
|
134
128
|
def validate_params(self) -> None:
|
@@ -160,7 +154,6 @@ class DataCaches(CacheStatsProvider):
|
|
160
154
|
max_entries: int | None,
|
161
155
|
ttl: int | float | timedelta | str | None,
|
162
156
|
display_name: str,
|
163
|
-
allow_widgets: bool,
|
164
157
|
) -> DataCache:
|
165
158
|
"""Return the mem cache for the given key.
|
166
159
|
|
@@ -220,7 +213,6 @@ class DataCaches(CacheStatsProvider):
|
|
220
213
|
max_entries=max_entries,
|
221
214
|
ttl_seconds=ttl_seconds,
|
222
215
|
display_name=display_name,
|
223
|
-
allow_widgets=allow_widgets,
|
224
216
|
)
|
225
217
|
self._function_caches[key] = cache
|
226
218
|
return cache
|
@@ -443,9 +435,6 @@ class CacheDataAPI:
|
|
443
435
|
|
444
436
|
experimental_allow_widgets : bool
|
445
437
|
Allow widgets to be used in the cached function. Defaults to False.
|
446
|
-
Support for widgets in cached functions is currently experimental.
|
447
|
-
Setting this parameter to True may lead to excessive memory use since the
|
448
|
-
widget value is treated as an additional input parameter to the cache.
|
449
438
|
|
450
439
|
hash_funcs : dict or None
|
451
440
|
Mapping of types or fully qualified names to hash functions.
|
@@ -456,8 +445,10 @@ class CacheDataAPI:
|
|
456
445
|
of how this can be used.
|
457
446
|
|
458
447
|
.. deprecated::
|
459
|
-
|
460
|
-
|
448
|
+
The cached widget replay functionality was removed in 1.38. Please
|
449
|
+
remove the ``experimental_allow_widgets`` parameter from your
|
450
|
+
caching decorators. This parameter will be removed in a future
|
451
|
+
version.
|
461
452
|
|
462
453
|
Example
|
463
454
|
-------
|
@@ -574,7 +565,6 @@ class CacheDataAPI:
|
|
574
565
|
show_spinner=show_spinner,
|
575
566
|
max_entries=max_entries,
|
576
567
|
ttl=ttl,
|
577
|
-
allow_widgets=experimental_allow_widgets,
|
578
568
|
hash_funcs=hash_funcs,
|
579
569
|
)
|
580
570
|
)
|
@@ -589,7 +579,6 @@ class CacheDataAPI:
|
|
589
579
|
show_spinner=show_spinner,
|
590
580
|
max_entries=max_entries,
|
591
581
|
ttl=ttl,
|
592
|
-
allow_widgets=experimental_allow_widgets,
|
593
582
|
hash_funcs=hash_funcs,
|
594
583
|
)
|
595
584
|
)
|
@@ -611,7 +600,6 @@ class DataCache(Cache):
|
|
611
600
|
max_entries: int | None,
|
612
601
|
ttl_seconds: float | None,
|
613
602
|
display_name: str,
|
614
|
-
allow_widgets: bool = False,
|
615
603
|
):
|
616
604
|
super().__init__()
|
617
605
|
self.key = key
|
@@ -620,7 +608,6 @@ class DataCache(Cache):
|
|
620
608
|
self.ttl_seconds = ttl_seconds
|
621
609
|
self.max_entries = max_entries
|
622
610
|
self.persist = persist
|
623
|
-
self.allow_widgets = allow_widgets
|
624
611
|
|
625
612
|
def get_stats(self) -> list[CacheStat]:
|
626
613
|
if isinstance(self.storage, CacheStatsProvider):
|
@@ -641,21 +628,12 @@ class DataCache(Cache):
|
|
641
628
|
|
642
629
|
try:
|
643
630
|
entry = pickle.loads(pickled_entry)
|
644
|
-
if not isinstance(entry,
|
631
|
+
if not isinstance(entry, CachedResult):
|
645
632
|
# Loaded an old cache file format, remove it and let the caller
|
646
633
|
# rerun the function.
|
647
634
|
self.storage.delete(key)
|
648
635
|
raise CacheKeyNotFoundError()
|
649
|
-
|
650
|
-
ctx = get_script_run_ctx()
|
651
|
-
if not ctx:
|
652
|
-
raise CacheKeyNotFoundError()
|
653
|
-
|
654
|
-
widget_key = entry.get_current_widget_key(ctx, CacheType.DATA)
|
655
|
-
if widget_key in entry.results:
|
656
|
-
return entry.results[widget_key]
|
657
|
-
else:
|
658
|
-
raise CacheKeyNotFoundError()
|
636
|
+
return entry
|
659
637
|
except pickle.UnpicklingError as exc:
|
660
638
|
raise CacheError(f"Failed to unpickle {key}") from exc
|
661
639
|
|
@@ -664,43 +642,13 @@ class DataCache(Cache):
|
|
664
642
|
"""Write a value and associated messages to the cache.
|
665
643
|
The value must be pickleable.
|
666
644
|
"""
|
667
|
-
ctx = get_script_run_ctx()
|
668
|
-
if ctx is None:
|
669
|
-
return
|
670
|
-
|
671
|
-
main_id = st._main.id
|
672
|
-
sidebar_id = st.sidebar.id
|
673
|
-
|
674
|
-
if self.allow_widgets:
|
675
|
-
widgets = {
|
676
|
-
msg.widget_metadata.widget_id
|
677
|
-
for msg in messages
|
678
|
-
if isinstance(msg, ElementMsgData) and msg.widget_metadata is not None
|
679
|
-
}
|
680
|
-
else:
|
681
|
-
widgets = set()
|
682
|
-
|
683
|
-
multi_cache_results: MultiCacheResults | None = None
|
684
|
-
|
685
|
-
# Try to find in cache storage, then falling back to a new result instance
|
686
|
-
try:
|
687
|
-
multi_cache_results = self._read_multi_results_from_storage(key)
|
688
|
-
except (CacheKeyNotFoundError, pickle.UnpicklingError):
|
689
|
-
pass
|
690
|
-
|
691
|
-
if multi_cache_results is None:
|
692
|
-
multi_cache_results = MultiCacheResults(widget_ids=widgets, results={})
|
693
|
-
multi_cache_results.widget_ids.update(widgets)
|
694
|
-
widget_key = multi_cache_results.get_current_widget_key(ctx, CacheType.DATA)
|
695
|
-
|
696
|
-
result = CachedResult(value, messages, main_id, sidebar_id)
|
697
|
-
multi_cache_results.results[widget_key] = result
|
698
|
-
|
699
645
|
try:
|
700
|
-
|
646
|
+
main_id = st._main.id
|
647
|
+
sidebar_id = st.sidebar.id
|
648
|
+
entry = CachedResult(value, messages, main_id, sidebar_id)
|
649
|
+
pickled_entry = pickle.dumps(entry)
|
701
650
|
except (pickle.PicklingError, TypeError) as exc:
|
702
651
|
raise CacheError(f"Failed to pickle {key}") from exc
|
703
|
-
|
704
652
|
self.storage.set(key, pickled_entry)
|
705
653
|
|
706
654
|
def _clear(self, key: str | None = None) -> None:
|
@@ -708,22 +656,3 @@ class DataCache(Cache):
|
|
708
656
|
self.storage.clear()
|
709
657
|
else:
|
710
658
|
self.storage.delete(key)
|
711
|
-
|
712
|
-
def _read_multi_results_from_storage(self, key: str) -> MultiCacheResults:
|
713
|
-
"""Look up the results from storage and ensure it has the right type.
|
714
|
-
|
715
|
-
Raises a `CacheKeyNotFoundError` if the key has no entry, or if the
|
716
|
-
entry is malformed.
|
717
|
-
"""
|
718
|
-
try:
|
719
|
-
pickled = self.storage.get(key)
|
720
|
-
except CacheStorageKeyNotFoundError as e:
|
721
|
-
raise CacheKeyNotFoundError(str(e)) from e
|
722
|
-
|
723
|
-
maybe_results = pickle.loads(pickled)
|
724
|
-
|
725
|
-
if isinstance(maybe_results, MultiCacheResults):
|
726
|
-
return maybe_results
|
727
|
-
else:
|
728
|
-
self.storage.delete(key)
|
729
|
-
raise CacheKeyNotFoundError()
|
@@ -29,7 +29,7 @@ CACHE_DOCS_URL = "https://docs.streamlit.io/develop/concepts/architecture/cachin
|
|
29
29
|
def get_cached_func_name_md(func: Any) -> str:
|
30
30
|
"""Get markdown representation of the function name."""
|
31
31
|
if hasattr(func, "__name__"):
|
32
|
-
return "
|
32
|
+
return f"`{func.__name__}()`"
|
33
33
|
elif hasattr(type(func), "__name__"):
|
34
34
|
return f"`{type(func).__name__}`"
|
35
35
|
return f"`{type(func)}`"
|
@@ -105,9 +105,10 @@ class CacheReplayClosureError(StreamlitAPIException):
|
|
105
105
|
|
106
106
|
msg = (
|
107
107
|
f"""
|
108
|
-
While running {func_name}, a streamlit element is called on some layout block
|
109
|
-
This is incompatible with replaying the cached
|
110
|
-
the referenced block might not exist when
|
108
|
+
While running {func_name}, a streamlit element is called on some layout block
|
109
|
+
created outside the function. This is incompatible with replaying the cached
|
110
|
+
effect of that element, because the the referenced block might not exist when
|
111
|
+
the replay happens.
|
111
112
|
|
112
113
|
How to fix this:
|
113
114
|
* Move the creation of $THING inside {func_name}.
|
@@ -124,11 +125,14 @@ class UnserializableReturnValueError(MarkdownFormattedException):
|
|
124
125
|
MarkdownFormattedException.__init__(
|
125
126
|
self,
|
126
127
|
f"""
|
127
|
-
Cannot serialize the return value (of type {get_return_value_type(return_value)})
|
128
|
-
`st.cache_data` uses
|
129
|
-
|
130
|
-
|
131
|
-
|
128
|
+
Cannot serialize the return value (of type {get_return_value_type(return_value)})
|
129
|
+
in {get_cached_func_name_md(func)}. `st.cache_data` uses
|
130
|
+
[pickle](https://docs.python.org/3/library/pickle.html) to serialize the
|
131
|
+
function's return value and safely store it in the cache
|
132
|
+
without mutating the original object. Please convert the return value to a
|
133
|
+
pickle-serializable type. If you want to cache unserializable objects such
|
134
|
+
as database connections or Tensorflow sessions, use `st.cache_resource`
|
135
|
+
instead (see [our docs]({CACHE_DOCS_URL}) for differences).""",
|
132
136
|
)
|
133
137
|
|
134
138
|
|
@@ -37,13 +37,10 @@ from streamlit.runtime.caching.cache_utils import (
|
|
37
37
|
from streamlit.runtime.caching.cached_message_replay import (
|
38
38
|
CachedMessageReplayContext,
|
39
39
|
CachedResult,
|
40
|
-
ElementMsgData,
|
41
40
|
MsgData,
|
42
|
-
MultiCacheResults,
|
43
41
|
show_widget_replay_deprecation,
|
44
42
|
)
|
45
43
|
from streamlit.runtime.metrics_util import gather_metrics
|
46
|
-
from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
|
47
44
|
from streamlit.runtime.stats import CacheStat, CacheStatsProvider, group_stats
|
48
45
|
from streamlit.time_util import time_to_seconds
|
49
46
|
|
@@ -83,7 +80,6 @@ class ResourceCaches(CacheStatsProvider):
|
|
83
80
|
max_entries: int | float | None,
|
84
81
|
ttl: float | timedelta | str | None,
|
85
82
|
validate: ValidateFunc | None,
|
86
|
-
allow_widgets: bool,
|
87
83
|
) -> ResourceCache:
|
88
84
|
"""Return the mem cache for the given key.
|
89
85
|
|
@@ -114,7 +110,6 @@ class ResourceCaches(CacheStatsProvider):
|
|
114
110
|
max_entries=max_entries,
|
115
111
|
ttl_seconds=ttl_seconds,
|
116
112
|
validate=validate,
|
117
|
-
allow_widgets=allow_widgets,
|
118
113
|
)
|
119
114
|
self._function_caches[key] = cache
|
120
115
|
return cache
|
@@ -155,13 +150,11 @@ class CachedResourceFuncInfo(CachedFuncInfo):
|
|
155
150
|
max_entries: int | None,
|
156
151
|
ttl: float | timedelta | str | None,
|
157
152
|
validate: ValidateFunc | None,
|
158
|
-
allow_widgets: bool,
|
159
153
|
hash_funcs: HashFuncsDict | None = None,
|
160
154
|
):
|
161
155
|
super().__init__(
|
162
156
|
func,
|
163
157
|
show_spinner=show_spinner,
|
164
|
-
allow_widgets=allow_widgets,
|
165
158
|
hash_funcs=hash_funcs,
|
166
159
|
)
|
167
160
|
self.max_entries = max_entries
|
@@ -188,7 +181,6 @@ class CachedResourceFuncInfo(CachedFuncInfo):
|
|
188
181
|
max_entries=self.max_entries,
|
189
182
|
ttl=self.ttl,
|
190
183
|
validate=self.validate,
|
191
|
-
allow_widgets=self.allow_widgets,
|
192
184
|
)
|
193
185
|
|
194
186
|
|
@@ -315,9 +307,6 @@ class CacheResourceAPI:
|
|
315
307
|
|
316
308
|
experimental_allow_widgets : bool
|
317
309
|
Allow widgets to be used in the cached function. Defaults to False.
|
318
|
-
Support for widgets in cached functions is currently experimental.
|
319
|
-
Setting this parameter to True may lead to excessive memory use since the
|
320
|
-
widget value is treated as an additional input parameter to the cache.
|
321
310
|
|
322
311
|
hash_funcs : dict or None
|
323
312
|
Mapping of types or fully qualified names to hash functions.
|
@@ -328,8 +317,10 @@ class CacheResourceAPI:
|
|
328
317
|
of how this can be used.
|
329
318
|
|
330
319
|
.. deprecated::
|
331
|
-
|
332
|
-
|
320
|
+
The cached widget replay functionality was removed in 1.38. Please
|
321
|
+
remove the ``experimental_allow_widgets`` parameter from your
|
322
|
+
caching decorators. This parameter will be removed in a future
|
323
|
+
version.
|
333
324
|
|
334
325
|
Example
|
335
326
|
-------
|
@@ -426,7 +417,6 @@ class CacheResourceAPI:
|
|
426
417
|
max_entries=max_entries,
|
427
418
|
ttl=ttl,
|
428
419
|
validate=validate,
|
429
|
-
allow_widgets=experimental_allow_widgets,
|
430
420
|
hash_funcs=hash_funcs,
|
431
421
|
)
|
432
422
|
)
|
@@ -438,7 +428,6 @@ class CacheResourceAPI:
|
|
438
428
|
max_entries=max_entries,
|
439
429
|
ttl=ttl,
|
440
430
|
validate=validate,
|
441
|
-
allow_widgets=experimental_allow_widgets,
|
442
431
|
hash_funcs=hash_funcs,
|
443
432
|
)
|
444
433
|
)
|
@@ -459,17 +448,15 @@ class ResourceCache(Cache):
|
|
459
448
|
ttl_seconds: float,
|
460
449
|
validate: ValidateFunc | None,
|
461
450
|
display_name: str,
|
462
|
-
allow_widgets: bool,
|
463
451
|
):
|
464
452
|
super().__init__()
|
465
453
|
self.key = key
|
466
454
|
self.display_name = display_name
|
467
|
-
self._mem_cache: TTLCache[str,
|
455
|
+
self._mem_cache: TTLCache[str, CachedResult] = TTLCache(
|
468
456
|
maxsize=max_entries, ttl=ttl_seconds, timer=cache_utils.TTLCACHE_TIMER
|
469
457
|
)
|
470
458
|
self._mem_cache_lock = threading.Lock()
|
471
459
|
self.validate = validate
|
472
|
-
self.allow_widgets = allow_widgets
|
473
460
|
|
474
461
|
@property
|
475
462
|
def max_entries(self) -> float:
|
@@ -488,24 +475,11 @@ class ResourceCache(Cache):
|
|
488
475
|
# key does not exist in cache.
|
489
476
|
raise CacheKeyNotFoundError()
|
490
477
|
|
491
|
-
|
492
|
-
|
493
|
-
ctx = get_script_run_ctx()
|
494
|
-
if not ctx:
|
495
|
-
# ScriptRunCtx does not exist (we're probably running in "raw" mode).
|
496
|
-
raise CacheKeyNotFoundError()
|
497
|
-
|
498
|
-
widget_key = multi_results.get_current_widget_key(ctx, CacheType.RESOURCE)
|
499
|
-
if widget_key not in multi_results.results:
|
500
|
-
# widget_key does not exist in cache (this combination of widgets hasn't been
|
501
|
-
# seen for the value_key yet).
|
502
|
-
raise CacheKeyNotFoundError()
|
503
|
-
|
504
|
-
result = multi_results.results[widget_key]
|
478
|
+
result = self._mem_cache[key]
|
505
479
|
|
506
480
|
if self.validate is not None and not self.validate(result.value):
|
507
481
|
# Validate failed: delete the entry and raise an error.
|
508
|
-
del
|
482
|
+
del self._mem_cache[key]
|
509
483
|
raise CacheKeyNotFoundError()
|
510
484
|
|
511
485
|
return result
|
@@ -513,33 +487,11 @@ class ResourceCache(Cache):
|
|
513
487
|
@gather_metrics("_cache_resource_object")
|
514
488
|
def write_result(self, key: str, value: Any, messages: list[MsgData]) -> None:
|
515
489
|
"""Write a value and associated messages to the cache."""
|
516
|
-
ctx = get_script_run_ctx()
|
517
|
-
if ctx is None:
|
518
|
-
return
|
519
|
-
|
520
490
|
main_id = st._main.id
|
521
491
|
sidebar_id = st.sidebar.id
|
522
|
-
if self.allow_widgets:
|
523
|
-
widgets = {
|
524
|
-
msg.widget_metadata.widget_id
|
525
|
-
for msg in messages
|
526
|
-
if isinstance(msg, ElementMsgData) and msg.widget_metadata is not None
|
527
|
-
}
|
528
|
-
else:
|
529
|
-
widgets = set()
|
530
492
|
|
531
493
|
with self._mem_cache_lock:
|
532
|
-
|
533
|
-
multi_results = self._mem_cache[key]
|
534
|
-
except KeyError:
|
535
|
-
multi_results = MultiCacheResults(widget_ids=widgets, results={})
|
536
|
-
|
537
|
-
multi_results.widget_ids.update(widgets)
|
538
|
-
widget_key = multi_results.get_current_widget_key(ctx, CacheType.RESOURCE)
|
539
|
-
|
540
|
-
result = CachedResult(value, messages, main_id, sidebar_id)
|
541
|
-
multi_results.results[widget_key] = result
|
542
|
-
self._mem_cache[key] = multi_results
|
494
|
+
self._mem_cache[key] = CachedResult(value, messages, main_id, sidebar_id)
|
543
495
|
|
544
496
|
def _clear(self, key: str | None = None) -> None:
|
545
497
|
with self._mem_cache_lock:
|
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
+
import contextlib
|
19
20
|
import functools
|
20
21
|
import hashlib
|
21
22
|
import inspect
|
@@ -125,12 +126,10 @@ class CachedFuncInfo:
|
|
125
126
|
self,
|
126
127
|
func: FunctionType,
|
127
128
|
show_spinner: bool | str,
|
128
|
-
allow_widgets: bool,
|
129
129
|
hash_funcs: HashFuncsDict | None,
|
130
130
|
):
|
131
131
|
self.func = func
|
132
132
|
self.show_spinner = show_spinner
|
133
|
-
self.allow_widgets = allow_widgets
|
134
133
|
self.hash_funcs = hash_funcs
|
135
134
|
|
136
135
|
@property
|
@@ -230,11 +229,9 @@ class CachedFunc:
|
|
230
229
|
hash_funcs=self._info.hash_funcs,
|
231
230
|
)
|
232
231
|
|
233
|
-
|
232
|
+
with contextlib.suppress(CacheKeyNotFoundError):
|
234
233
|
cached_result = cache.read_result(value_key)
|
235
234
|
return self._handle_cache_hit(cached_result)
|
236
|
-
except CacheKeyNotFoundError:
|
237
|
-
pass
|
238
235
|
return self._handle_cache_miss(cache, value_key, func_args, func_kwargs)
|
239
236
|
|
240
237
|
def _handle_cache_hit(self, result: CachedResult) -> Any:
|
@@ -279,17 +276,14 @@ class CachedFunc:
|
|
279
276
|
# We've acquired the lock - but another thread may have acquired it first
|
280
277
|
# and already computed the value. So we need to test for a cache hit again,
|
281
278
|
# before computing.
|
282
|
-
|
279
|
+
with contextlib.suppress(CacheKeyNotFoundError):
|
283
280
|
cached_result = cache.read_result(value_key)
|
284
281
|
# Another thread computed the value before us. Early exit!
|
285
282
|
return self._handle_cache_hit(cached_result)
|
286
283
|
|
287
|
-
except CacheKeyNotFoundError:
|
288
|
-
pass
|
289
|
-
|
290
284
|
# We acquired the lock before any other thread. Compute the value!
|
291
285
|
with self._info.cached_message_replay_ctx.calling_cached_function(
|
292
|
-
self._info.func
|
286
|
+
self._info.func
|
293
287
|
):
|
294
288
|
computed_value = self._info.func(*func_args, **func_kwargs)
|
295
289
|
|
@@ -329,8 +323,10 @@ class CachedFunc:
|
|
329
323
|
|
330
324
|
Parameters
|
331
325
|
----------
|
326
|
+
|
332
327
|
*args: Any
|
333
328
|
Arguments of the cached functions.
|
329
|
+
|
334
330
|
**kwargs: Any
|
335
331
|
Keyword arguments of the cached function.
|
336
332
|
|
@@ -471,8 +467,7 @@ def _make_function_key(cache_type: CacheType, func: FunctionType) -> str:
|
|
471
467
|
source_code, hasher=func_hasher, cache_type=cache_type, hash_source=func
|
472
468
|
)
|
473
469
|
|
474
|
-
|
475
|
-
return cache_key
|
470
|
+
return func_hasher.hexdigest()
|
476
471
|
|
477
472
|
|
478
473
|
def _get_positional_arg_name(func: FunctionType, arg_index: int) -> str | None:
|