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.
Files changed (44) hide show
  1. streamlit/components/v1/custom_component.py +2 -0
  2. streamlit/delta_generator.py +0 -5
  3. streamlit/elements/__init__.py +0 -57
  4. streamlit/elements/arrow_vega_lite.py +8 -1
  5. streamlit/elements/form.py +5 -1
  6. streamlit/elements/spinner.py +16 -30
  7. streamlit/elements/utils.py +36 -1
  8. streamlit/elements/widgets/button.py +20 -1
  9. streamlit/elements/widgets/camera_input.py +3 -0
  10. streamlit/elements/widgets/chat.py +8 -1
  11. streamlit/elements/widgets/checkbox.py +3 -1
  12. streamlit/elements/widgets/color_picker.py +3 -0
  13. streamlit/elements/widgets/data_editor.py +10 -1
  14. streamlit/elements/widgets/file_uploader.py +3 -0
  15. streamlit/elements/widgets/multiselect.py +13 -6
  16. streamlit/elements/widgets/number_input.py +8 -0
  17. streamlit/elements/widgets/radio.py +9 -0
  18. streamlit/elements/widgets/select_slider.py +4 -0
  19. streamlit/elements/widgets/selectbox.py +8 -1
  20. streamlit/elements/widgets/slider.py +3 -1
  21. streamlit/elements/widgets/text_widgets.py +13 -2
  22. streamlit/elements/widgets/time_widgets.py +27 -10
  23. streamlit/runtime/caching/__init__.py +1 -19
  24. streamlit/runtime/caching/cache_data_api.py +8 -2
  25. streamlit/runtime/caching/cache_errors.py +0 -38
  26. streamlit/runtime/caching/cache_resource_api.py +8 -2
  27. streamlit/runtime/caching/cache_utils.py +26 -9
  28. streamlit/runtime/caching/cached_message_replay.py +25 -67
  29. streamlit/runtime/fragment.py +1 -1
  30. streamlit/runtime/legacy_caching/__init__.py +2 -12
  31. streamlit/runtime/legacy_caching/caching.py +1 -80
  32. streamlit/runtime/scriptrunner/script_run_context.py +4 -0
  33. streamlit/static/asset-manifest.json +3 -3
  34. streamlit/static/index.html +1 -1
  35. streamlit/static/static/js/43.b0aa5759.chunk.js +1 -0
  36. streamlit/static/static/js/{main.713dd29d.js → main.81ad100d.js} +2 -2
  37. {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/METADATA +3 -3
  38. {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/RECORD +43 -43
  39. streamlit/static/static/js/43.9ae03282.chunk.js +0 -1
  40. /streamlit/static/static/js/{main.713dd29d.js.LICENSE.txt → main.81ad100d.js.LICENSE.txt} +0 -0
  41. {streamlit_nightly-1.33.1.dev20240416.data → streamlit_nightly-1.33.1.dev20240418.data}/scripts/streamlit.cmd +0 -0
  42. {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/WHEEL +0 -0
  43. {streamlit_nightly-1.33.1.dev20240416.dist-info → streamlit_nightly-1.33.1.dev20240418.dist-info}/entry_points.txt +0 -0
  44. {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=_parse_min_date(
165
- min_value=min_value,
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 contextlib
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
- self.storage.clear()
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
- self._mem_cache.clear()
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 all values from this cache."""
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
- self._value_locks.clear()
109
- self._clear()
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
- cache.clear()
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: int = 0
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
- if allow_widgets:
267
- self._allow_widgets += 1
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 allow_widgets:
275
- self._allow_widgets -= 1
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
@@ -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 funciton inside a
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
- if suppress_st_warning:
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.713dd29d.js",
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.9ae03282.chunk.js": "./static/js/43.9ae03282.chunk.js",
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.713dd29d.js"
155
+ "static/js/main.81ad100d.js"
156
156
  ]
157
157
  }
@@ -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.713dd29d.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>
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>