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.
Files changed (153) hide show
  1. streamlit/case_converters.py +9 -4
  2. streamlit/cli_util.py +2 -0
  3. streamlit/code_util.py +5 -2
  4. streamlit/color_util.py +2 -0
  5. streamlit/column_config.py +2 -0
  6. streamlit/commands/execution_control.py +4 -2
  7. streamlit/commands/experimental_query_params.py +7 -4
  8. streamlit/commands/page_config.py +11 -9
  9. streamlit/components/v1/components.py +23 -16
  10. streamlit/config.py +3 -5
  11. streamlit/config_option.py +12 -11
  12. streamlit/connections/base_connection.py +4 -2
  13. streamlit/connections/snowflake_connection.py +4 -4
  14. streamlit/connections/snowpark_connection.py +3 -3
  15. streamlit/connections/sql_connection.py +6 -6
  16. streamlit/connections/util.py +8 -5
  17. streamlit/constants.py +2 -0
  18. streamlit/cursor.py +16 -14
  19. streamlit/delta_generator.py +10 -13
  20. streamlit/deprecation_util.py +4 -3
  21. streamlit/echo.py +5 -3
  22. streamlit/elements/alert.py +16 -14
  23. streamlit/elements/altair_utils.py +8 -6
  24. streamlit/elements/arrow.py +4 -4
  25. streamlit/elements/arrow_altair.py +24 -34
  26. streamlit/elements/arrow_vega_lite.py +9 -14
  27. streamlit/elements/balloons.py +4 -2
  28. streamlit/elements/bokeh_chart.py +7 -7
  29. streamlit/elements/code.py +6 -4
  30. streamlit/elements/deck_gl_json_chart.py +8 -8
  31. streamlit/elements/doc_string.py +5 -9
  32. streamlit/elements/empty.py +4 -2
  33. streamlit/elements/exception.py +10 -10
  34. streamlit/elements/form.py +1 -3
  35. streamlit/elements/graphviz_chart.py +5 -6
  36. streamlit/elements/heading.py +16 -14
  37. streamlit/elements/iframe.py +14 -12
  38. streamlit/elements/image.py +8 -8
  39. streamlit/elements/json.py +6 -4
  40. streamlit/elements/layouts.py +12 -10
  41. streamlit/elements/lib/column_config_utils.py +2 -2
  42. streamlit/elements/lib/column_types.py +23 -23
  43. streamlit/elements/lib/dicttools.py +10 -6
  44. streamlit/elements/lib/mutable_status_container.py +7 -7
  45. streamlit/elements/lib/pandas_styler_utils.py +6 -6
  46. streamlit/elements/lib/streamlit_plotly_theme.py +2 -0
  47. streamlit/elements/map.py +11 -22
  48. streamlit/elements/markdown.py +16 -14
  49. streamlit/elements/media.py +16 -16
  50. streamlit/elements/metric.py +9 -7
  51. streamlit/elements/plotly_chart.py +5 -5
  52. streamlit/elements/progress.py +6 -6
  53. streamlit/elements/pyplot.py +10 -13
  54. streamlit/elements/snow.py +4 -2
  55. streamlit/elements/spinner.py +2 -0
  56. streamlit/elements/text.py +7 -5
  57. streamlit/elements/toast.py +6 -4
  58. streamlit/elements/utils.py +15 -28
  59. streamlit/elements/widgets/button.py +39 -39
  60. streamlit/elements/widgets/camera_input.py +21 -17
  61. streamlit/elements/widgets/chat.py +6 -7
  62. streamlit/elements/widgets/checkbox.py +21 -19
  63. streamlit/elements/widgets/color_picker.py +18 -16
  64. streamlit/elements/widgets/data_editor.py +7 -7
  65. streamlit/elements/widgets/file_uploader.py +59 -55
  66. streamlit/elements/widgets/multiselect.py +33 -42
  67. streamlit/elements/widgets/number_input.py +10 -5
  68. streamlit/elements/widgets/radio.py +1 -1
  69. streamlit/elements/widgets/select_slider.py +25 -34
  70. streamlit/elements/widgets/selectbox.py +1 -1
  71. streamlit/elements/widgets/slider.py +28 -36
  72. streamlit/elements/widgets/text_widgets.py +6 -6
  73. streamlit/elements/widgets/time_widgets.py +13 -13
  74. streamlit/elements/write.py +8 -19
  75. streamlit/env_util.py +5 -3
  76. streamlit/error_util.py +7 -3
  77. streamlit/errors.py +3 -1
  78. streamlit/external/langchain/streamlit_callback_handler.py +26 -24
  79. streamlit/file_util.py +18 -14
  80. streamlit/folder_black_list.py +3 -1
  81. streamlit/git_util.py +5 -3
  82. streamlit/js_number.py +10 -13
  83. streamlit/logger.py +5 -5
  84. streamlit/net_util.py +14 -11
  85. streamlit/platform.py +2 -0
  86. streamlit/runtime/__init__.py +2 -0
  87. streamlit/runtime/app_session.py +42 -42
  88. streamlit/runtime/caching/__init__.py +4 -4
  89. streamlit/runtime/caching/cache_data_api.py +3 -3
  90. streamlit/runtime/caching/cache_errors.py +5 -3
  91. streamlit/runtime/caching/cache_type.py +2 -0
  92. streamlit/runtime/caching/cache_utils.py +2 -4
  93. streamlit/runtime/caching/cached_message_replay.py +12 -5
  94. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -2
  95. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -5
  96. streamlit/runtime/connection_factory.py +8 -8
  97. streamlit/runtime/forward_msg_cache.py +20 -18
  98. streamlit/runtime/forward_msg_queue.py +8 -9
  99. streamlit/runtime/legacy_caching/caching.py +32 -42
  100. streamlit/runtime/media_file_manager.py +16 -14
  101. streamlit/runtime/media_file_storage.py +8 -8
  102. streamlit/runtime/memory_media_file_storage.py +12 -14
  103. streamlit/runtime/memory_session_storage.py +4 -3
  104. streamlit/runtime/memory_uploaded_file_manager.py +9 -10
  105. streamlit/runtime/metrics_util.py +20 -20
  106. streamlit/runtime/runtime.py +25 -27
  107. streamlit/runtime/runtime_util.py +5 -3
  108. streamlit/runtime/script_data.py +2 -0
  109. streamlit/runtime/scriptrunner/magic.py +17 -11
  110. streamlit/runtime/scriptrunner/magic_funcs.py +2 -0
  111. streamlit/runtime/scriptrunner/script_requests.py +6 -4
  112. streamlit/runtime/scriptrunner/script_run_context.py +17 -17
  113. streamlit/runtime/scriptrunner/script_runner.py +7 -5
  114. streamlit/runtime/secrets.py +4 -6
  115. streamlit/runtime/session_manager.py +14 -14
  116. streamlit/runtime/state/common.py +5 -4
  117. streamlit/runtime/state/query_params.py +8 -6
  118. streamlit/runtime/state/query_params_proxy.py +7 -5
  119. streamlit/runtime/state/safe_session_state.py +7 -5
  120. streamlit/runtime/state/session_state.py +3 -4
  121. streamlit/runtime/state/session_state_proxy.py +5 -5
  122. streamlit/runtime/state/widgets.py +20 -18
  123. streamlit/runtime/uploaded_file_manager.py +6 -5
  124. streamlit/runtime/websocket_session_manager.py +14 -14
  125. streamlit/source_util.py +13 -11
  126. streamlit/string_util.py +13 -9
  127. streamlit/temporary_directory.py +3 -1
  128. streamlit/testing/v1/element_tree.py +1 -2
  129. streamlit/type_util.py +21 -25
  130. streamlit/url_util.py +6 -4
  131. streamlit/user_info.py +8 -6
  132. streamlit/util.py +23 -37
  133. streamlit/watcher/event_based_path_watcher.py +10 -10
  134. streamlit/watcher/local_sources_watcher.py +15 -13
  135. streamlit/watcher/path_watcher.py +0 -3
  136. streamlit/watcher/polling_path_watcher.py +9 -8
  137. streamlit/watcher/util.py +3 -2
  138. streamlit/web/cache_storage_manager_config.py +2 -0
  139. streamlit/web/server/app_static_file_handler.py +6 -5
  140. streamlit/web/server/browser_websocket_handler.py +10 -8
  141. streamlit/web/server/component_request_handler.py +7 -4
  142. streamlit/web/server/media_file_handler.py +5 -4
  143. streamlit/web/server/routes.py +6 -3
  144. streamlit/web/server/server.py +31 -31
  145. streamlit/web/server/server_util.py +4 -2
  146. streamlit/web/server/upload_file_request_handler.py +7 -8
  147. streamlit/web/server/websocket_headers.py +2 -2
  148. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/METADATA +1 -1
  149. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/RECORD +153 -153
  150. {streamlit_nightly-1.31.2.dev20240213.data → streamlit_nightly-1.31.2.dev20240214.data}/scripts/streamlit.cmd +0 -0
  151. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/WHEEL +0 -0
  152. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/entry_points.txt +0 -0
  153. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/top_level.txt +0 -0
@@ -12,14 +12,13 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Any, Dict, List, Optional, Tuple
15
+ from __future__ import annotations
16
+
17
+ from typing import Any
16
18
 
17
- from streamlit.logger import get_logger
18
19
  from streamlit.proto.Delta_pb2 import Delta
19
20
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
20
21
 
21
- LOGGER = get_logger(__name__)
22
-
23
22
 
24
23
  class ForwardMsgQueue:
25
24
  """Accumulates a session's outgoing ForwardMsgs.
@@ -33,15 +32,15 @@ class ForwardMsgQueue:
33
32
  """
34
33
 
35
34
  def __init__(self):
36
- self._queue: List[ForwardMsg] = []
35
+ self._queue: list[ForwardMsg] = []
37
36
  # A mapping of (delta_path -> _queue.indexof(msg)) for each
38
37
  # Delta message in the queue. We use this for coalescing
39
38
  # redundant outgoing Deltas (where a newer Delta supersedes
40
39
  # an older Delta, with the same delta_path, that's still in the
41
40
  # queue).
42
- self._delta_index_map: Dict[Tuple[int, ...], int] = dict()
41
+ self._delta_index_map: dict[tuple[int, ...], int] = dict()
43
42
 
44
- def get_debug(self) -> Dict[str, Any]:
43
+ def get_debug(self) -> dict[str, Any]:
45
44
  from google.protobuf.json_format import MessageToDict
46
45
 
47
46
  return {
@@ -85,7 +84,7 @@ class ForwardMsgQueue:
85
84
  self._queue = []
86
85
  self._delta_index_map = dict()
87
86
 
88
- def flush(self) -> List[ForwardMsg]:
87
+ def flush(self) -> list[ForwardMsg]:
89
88
  """Clear the queue and return a list of the messages it contained
90
89
  before being cleared.
91
90
  """
@@ -107,7 +106,7 @@ def _is_composable_message(msg: ForwardMsg) -> bool:
107
106
  return delta_type != "add_rows" and delta_type != "arrow_add_rows"
108
107
 
109
108
 
110
- def _maybe_compose_deltas(old_delta: Delta, new_delta: Delta) -> Optional[Delta]:
109
+ def _maybe_compose_deltas(old_delta: Delta, new_delta: Delta) -> Delta | None:
111
110
  """Combines new_delta onto old_delta if possible.
112
111
 
113
112
  If the combination takes place, the function returns a new Delta that
@@ -14,6 +14,8 @@
14
14
 
15
15
  """A library of caching utilities."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import contextlib
18
20
  import functools
19
21
  import hashlib
@@ -26,19 +28,7 @@ import threading
26
28
  import time
27
29
  from collections import namedtuple
28
30
  from dataclasses import dataclass
29
- from typing import (
30
- Any,
31
- Callable,
32
- Dict,
33
- Final,
34
- Iterator,
35
- List,
36
- Optional,
37
- TypeVar,
38
- Union,
39
- cast,
40
- overload,
41
- )
31
+ from typing import Any, Callable, Final, Iterator, TypeVar, cast, overload
42
32
 
43
33
  from cachetools import TTLCache
44
34
 
@@ -72,7 +62,7 @@ _DiskCacheEntry = namedtuple("_DiskCacheEntry", ["value"])
72
62
 
73
63
  # When we show the "st.cache is deprecated" warning, we make a recommendation about which new
74
64
  # cache decorator to switch to for the following data types:
75
- NEW_CACHE_FUNC_RECOMMENDATIONS: Dict[str, CacheType] = {
65
+ NEW_CACHE_FUNC_RECOMMENDATIONS: dict[str, CacheType] = {
76
66
  # cache_data recommendations:
77
67
  "str": CacheType.DATA,
78
68
  "float": CacheType.DATA,
@@ -165,7 +155,7 @@ class _MemCaches(CacheStatsProvider):
165
155
  def __init__(self):
166
156
  # Contains a cache object for each st.cache'd function
167
157
  self._lock = threading.RLock()
168
- self._function_caches: Dict[str, MemCache] = {}
158
+ self._function_caches: dict[str, MemCache] = {}
169
159
 
170
160
  def __repr__(self) -> str:
171
161
  return util.repr_(self)
@@ -173,8 +163,8 @@ class _MemCaches(CacheStatsProvider):
173
163
  def get_cache(
174
164
  self,
175
165
  key: str,
176
- max_entries: Optional[float],
177
- ttl: Optional[float],
166
+ max_entries: float | None,
167
+ ttl: float | None,
178
168
  display_name: str = "",
179
169
  ) -> MemCache:
180
170
  """Return the mem cache for the given key.
@@ -220,7 +210,7 @@ class _MemCaches(CacheStatsProvider):
220
210
  with self._lock:
221
211
  self._function_caches = {}
222
212
 
223
- def get_stats(self) -> List[CacheStat]:
213
+ def get_stats(self) -> list[CacheStat]:
224
214
  with self._lock:
225
215
  # Shallow-clone our caches. We don't want to hold the global
226
216
  # lock during stats-gathering.
@@ -245,7 +235,7 @@ _mem_caches = _MemCaches()
245
235
  # and decremented when we exit.
246
236
  class ThreadLocalCacheInfo(threading.local):
247
237
  def __init__(self):
248
- self.cached_func_stack: List[Callable[..., Any]] = []
238
+ self.cached_func_stack: list[Callable[..., Any]] = []
249
239
  self.suppress_st_function_warning = 0
250
240
 
251
241
  def __repr__(self) -> str:
@@ -275,7 +265,7 @@ def suppress_cached_st_function_warning() -> Iterator[None]:
275
265
 
276
266
 
277
267
  def _show_cached_st_function_warning(
278
- dg: "st.delta_generator.DeltaGenerator",
268
+ dg: st.delta_generator.DeltaGenerator,
279
269
  st_func_name: str,
280
270
  cached_func: Callable[..., Any],
281
271
  ) -> None:
@@ -287,7 +277,7 @@ def _show_cached_st_function_warning(
287
277
 
288
278
 
289
279
  def maybe_show_cached_st_function_warning(
290
- dg: "st.delta_generator.DeltaGenerator", st_func_name: str
280
+ dg: st.delta_generator.DeltaGenerator, st_func_name: str
291
281
  ) -> None:
292
282
  """If appropriate, warn about calling st.foo inside @cache.
293
283
 
@@ -317,7 +307,7 @@ def _read_from_mem_cache(
317
307
  key: str,
318
308
  allow_output_mutation: bool,
319
309
  func_or_code: Callable[..., Any],
320
- hash_funcs: Optional[HashFuncsDict],
310
+ hash_funcs: HashFuncsDict | None,
321
311
  ) -> Any:
322
312
  cache = mem_cache.cache
323
313
  if key in cache:
@@ -347,7 +337,7 @@ def _write_to_mem_cache(
347
337
  value: Any,
348
338
  allow_output_mutation: bool,
349
339
  func_or_code: Callable[..., Any],
350
- hash_funcs: Optional[HashFuncsDict],
340
+ hash_funcs: HashFuncsDict | None,
351
341
  ) -> None:
352
342
  if allow_output_mutation:
353
343
  hash = None
@@ -359,7 +349,7 @@ def _write_to_mem_cache(
359
349
 
360
350
 
361
351
  def _get_output_hash(
362
- value: Any, func_or_code: Callable[..., Any], hash_funcs: Optional[HashFuncsDict]
352
+ value: Any, func_or_code: Callable[..., Any], hash_funcs: HashFuncsDict | None
363
353
  ) -> bytes:
364
354
  hasher = hashlib.new("md5", **HASHLIB_KWARGS)
365
355
  update_hash(
@@ -400,7 +390,7 @@ def _write_to_disk_cache(key: str, value: Any) -> None:
400
390
  # Clean up file so we don't leave zero byte files.
401
391
  try:
402
392
  os.remove(path)
403
- except (FileNotFoundError, IOError, OSError):
393
+ except (FileNotFoundError, OSError):
404
394
  # If we can't remove the file, it's not a big deal.
405
395
  pass
406
396
  raise CacheError("Unable to write to cache: %s" % e)
@@ -412,7 +402,7 @@ def _read_from_cache(
412
402
  persist: bool,
413
403
  allow_output_mutation: bool,
414
404
  func_or_code: Callable[..., Any],
415
- hash_funcs: Optional[HashFuncsDict] = None,
405
+ hash_funcs: HashFuncsDict | None = None,
416
406
  ) -> Any:
417
407
  """Read a value from the cache.
418
408
 
@@ -447,7 +437,7 @@ def _write_to_cache(
447
437
  persist: bool,
448
438
  allow_output_mutation: bool,
449
439
  func_or_code: Callable[..., Any],
450
- hash_funcs: Optional[HashFuncsDict] = None,
440
+ hash_funcs: HashFuncsDict | None = None,
451
441
  ):
452
442
  _write_to_mem_cache(
453
443
  mem_cache, key, value, allow_output_mutation, func_or_code, hash_funcs
@@ -466,9 +456,9 @@ def cache(
466
456
  allow_output_mutation: bool = False,
467
457
  show_spinner: bool = True,
468
458
  suppress_st_warning: bool = False,
469
- hash_funcs: Optional[HashFuncsDict] = None,
470
- max_entries: Optional[int] = None,
471
- ttl: Optional[float] = None,
459
+ hash_funcs: HashFuncsDict | None = None,
460
+ max_entries: int | None = None,
461
+ ttl: float | None = None,
472
462
  ) -> F:
473
463
  ...
474
464
 
@@ -480,23 +470,23 @@ def cache(
480
470
  allow_output_mutation: bool = False,
481
471
  show_spinner: bool = True,
482
472
  suppress_st_warning: bool = False,
483
- hash_funcs: Optional[HashFuncsDict] = None,
484
- max_entries: Optional[int] = None,
485
- ttl: Optional[float] = None,
473
+ hash_funcs: HashFuncsDict | None = None,
474
+ max_entries: int | None = None,
475
+ ttl: float | None = None,
486
476
  ) -> Callable[[F], F]:
487
477
  ...
488
478
 
489
479
 
490
480
  def cache(
491
- func: Optional[F] = None,
481
+ func: F | None = None,
492
482
  persist: bool = False,
493
483
  allow_output_mutation: bool = False,
494
484
  show_spinner: bool = True,
495
485
  suppress_st_warning: bool = False,
496
- hash_funcs: Optional[HashFuncsDict] = None,
497
- max_entries: Optional[int] = None,
498
- ttl: Optional[float] = None,
499
- ) -> Union[Callable[[F], F], F]:
486
+ hash_funcs: HashFuncsDict | None = None,
487
+ max_entries: int | None = None,
488
+ ttl: float | None = None,
489
+ ) -> Callable[[F], F] | F:
500
490
  """Function decorator to memoize function executions.
501
491
 
502
492
  Parameters
@@ -674,7 +664,7 @@ def cache(
674
664
 
675
665
  # Avoid recomputing the body's hash by just appending the
676
666
  # previously-computed hash to the arg hash.
677
- value_key = "%s-%s" % (value_key, cache_key)
667
+ value_key = "{}-{}".format(value_key, cache_key)
678
668
 
679
669
  _LOGGER.debug("Cache key: %s", value_key)
680
670
 
@@ -731,7 +721,7 @@ def cache(
731
721
  return cast(F, wrapped_func)
732
722
 
733
723
 
734
- def _hash_func(func: Callable[..., Any], hash_funcs: Optional[HashFuncsDict]) -> str:
724
+ def _hash_func(func: Callable[..., Any], hash_funcs: HashFuncsDict | None) -> str:
735
725
  # Create the unique key for a function's cache. The cache will be retrieved
736
726
  # from inside the wrapped function.
737
727
  #
@@ -839,7 +829,7 @@ class CachedObjectMutationError(ValueError):
839
829
  class CachedStFunctionWarning(StreamlitAPIWarning):
840
830
  def __init__(self, st_func_name, cached_func):
841
831
  msg = self._get_message(st_func_name, cached_func)
842
- super(CachedStFunctionWarning, self).__init__(msg)
832
+ super().__init__(msg)
843
833
 
844
834
  def _get_message(self, st_func_name, cached_func):
845
835
  args = {
@@ -865,7 +855,7 @@ to suppress the warning.
865
855
  class CachedObjectMutationWarning(StreamlitAPIWarning):
866
856
  def __init__(self, orig_exc):
867
857
  msg = self._get_message(orig_exc)
868
- super(CachedObjectMutationWarning, self).__init__(msg)
858
+ super().__init__(msg)
869
859
 
870
860
  def _get_message(self, orig_exc):
871
861
  return (
@@ -14,14 +14,16 @@
14
14
 
15
15
  """Provides global MediaFileManager object as `media_file_manager`."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import collections
18
20
  import threading
19
- from typing import Dict, Optional, Set, Union
21
+ from typing import Final
20
22
 
21
23
  from streamlit.logger import get_logger
22
24
  from streamlit.runtime.media_file_storage import MediaFileKind, MediaFileStorage
23
25
 
24
- LOGGER = get_logger(__name__)
26
+ _LOGGER: Final = get_logger(__name__)
25
27
 
26
28
 
27
29
  def _get_session_id() -> str:
@@ -80,11 +82,11 @@ class MediaFileManager:
80
82
  self._storage = storage
81
83
 
82
84
  # Dict of [file_id -> MediaFileMetadata]
83
- self._file_metadata: Dict[str, MediaFileMetadata] = dict()
85
+ self._file_metadata: dict[str, MediaFileMetadata] = dict()
84
86
 
85
87
  # Dict[session ID][coordinates] -> file_id.
86
- self._files_by_session_and_coord: Dict[
87
- str, Dict[str, str]
88
+ self._files_by_session_and_coord: dict[
89
+ str, dict[str, str]
88
90
  ] = collections.defaultdict(dict)
89
91
 
90
92
  # MediaFileManager is used from multiple threads, so all operations
@@ -92,7 +94,7 @@ class MediaFileManager:
92
94
  # means taking it multiple times from the same thread will deadlock.)
93
95
  self._lock = threading.Lock()
94
96
 
95
- def _get_inactive_file_ids(self) -> Set[str]:
97
+ def _get_inactive_file_ids(self) -> set[str]:
96
98
  """Compute the set of files that are stored in the manager, but are
97
99
  not referenced by any active session. These are files that can be
98
100
  safely deleted.
@@ -113,7 +115,7 @@ class MediaFileManager:
113
115
 
114
116
  Safe to call from any thread.
115
117
  """
116
- LOGGER.debug("Removing orphaned files...")
118
+ _LOGGER.debug("Removing orphaned files...")
117
119
 
118
120
  with self._lock:
119
121
  for file_id in self._get_inactive_file_ids():
@@ -132,11 +134,11 @@ class MediaFileManager:
132
134
 
133
135
  Thread safety: callers must hold `self._lock`.
134
136
  """
135
- LOGGER.debug("Deleting File: %s", file_id)
137
+ _LOGGER.debug("Deleting File: %s", file_id)
136
138
  self._storage.delete_file(file_id)
137
139
  del self._file_metadata[file_id]
138
140
 
139
- def clear_session_refs(self, session_id: Optional[str] = None) -> None:
141
+ def clear_session_refs(self, session_id: str | None = None) -> None:
140
142
  """Remove the given session's file references.
141
143
 
142
144
  (This does not remove any files from the manager - you must call
@@ -149,17 +151,17 @@ class MediaFileManager:
149
151
  if session_id is None:
150
152
  session_id = _get_session_id()
151
153
 
152
- LOGGER.debug("Disconnecting files for session with ID %s", session_id)
154
+ _LOGGER.debug("Disconnecting files for session with ID %s", session_id)
153
155
 
154
156
  with self._lock:
155
157
  if session_id in self._files_by_session_and_coord:
156
158
  del self._files_by_session_and_coord[session_id]
157
159
 
158
- LOGGER.debug(
160
+ _LOGGER.debug(
159
161
  "Sessions still active: %r", self._files_by_session_and_coord.keys()
160
162
  )
161
163
 
162
- LOGGER.debug(
164
+ _LOGGER.debug(
163
165
  "Files: %s; Sessions with files: %s",
164
166
  len(self._file_metadata),
165
167
  len(self._files_by_session_and_coord),
@@ -167,10 +169,10 @@ class MediaFileManager:
167
169
 
168
170
  def add(
169
171
  self,
170
- path_or_data: Union[bytes, str],
172
+ path_or_data: bytes | str,
171
173
  mimetype: str,
172
174
  coordinates: str,
173
- file_name: Optional[str] = None,
175
+ file_name: str | None = None,
174
176
  is_for_static_download: bool = False,
175
177
  ) -> str:
176
178
  """Add a new MediaFile with the given parameters and return its URL.
@@ -12,11 +12,11 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from abc import abstractmethod
16
18
  from enum import Enum
17
- from typing import Optional, Union
18
-
19
- from typing_extensions import Protocol
19
+ from typing import Protocol
20
20
 
21
21
 
22
22
  class MediaFileKind(Enum):
@@ -43,17 +43,17 @@ class MediaFileStorage(Protocol):
43
43
  @abstractmethod
44
44
  def load_and_get_id(
45
45
  self,
46
- path_or_data: Union[str, bytes],
46
+ path_or_data: str | bytes,
47
47
  mimetype: str,
48
48
  kind: MediaFileKind,
49
- filename: Optional[str] = None,
49
+ filename: str | None = None,
50
50
  ) -> str:
51
51
  """Load the given file path or bytes into the manager and return
52
52
  an ID that uniquely identifies it.
53
53
 
54
- Its an error to pass a URL to this function. (Media stored at
54
+ It's an error to pass a URL to this function. (Media stored at
55
55
  external URLs can be served directly to the Streamlit frontend;
56
- theres no need to store this data in MediaFileStorage.)
56
+ there's no need to store this data in MediaFileStorage.)
57
57
 
58
58
  Parameters
59
59
  ----------
@@ -61,7 +61,7 @@ class MediaFileStorage(Protocol):
61
61
  A path to a file, or the file's raw data as bytes.
62
62
 
63
63
  mimetype
64
- The medias mimetype. Used to set the Content-Type header when
64
+ The media's mimetype. Used to set the Content-Type header when
65
65
  serving the media over HTTP.
66
66
 
67
67
  kind
@@ -14,13 +14,13 @@
14
14
 
15
15
  """MediaFileStorage implementation that stores files in memory."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import contextlib
18
20
  import hashlib
19
21
  import mimetypes
20
22
  import os.path
21
- from typing import Dict, List, NamedTuple, Optional, Union
22
-
23
- from typing_extensions import Final
23
+ from typing import Final, NamedTuple
24
24
 
25
25
  from streamlit.logger import get_logger
26
26
  from streamlit.runtime.media_file_storage import (
@@ -31,7 +31,7 @@ from streamlit.runtime.media_file_storage import (
31
31
  from streamlit.runtime.stats import CacheStat, CacheStatsProvider, group_stats
32
32
  from streamlit.util import HASHLIB_KWARGS
33
33
 
34
- LOGGER = get_logger(__name__)
34
+ _LOGGER: Final = get_logger(__name__)
35
35
 
36
36
  # Mimetype -> filename extension map for the `get_extension_for_mimetype`
37
37
  # function. We use Python's `mimetypes.guess_extension` for most mimetypes,
@@ -42,9 +42,7 @@ PREFERRED_MIMETYPE_EXTENSION_MAP: Final = {
42
42
  }
43
43
 
44
44
 
45
- def _calculate_file_id(
46
- data: bytes, mimetype: str, filename: Optional[str] = None
47
- ) -> str:
45
+ def _calculate_file_id(data: bytes, mimetype: str, filename: str | None = None) -> str:
48
46
  """Hash data, mimetype, and an optional filename to generate a stable file ID.
49
47
 
50
48
  Parameters
@@ -83,7 +81,7 @@ class MemoryFile(NamedTuple):
83
81
  content: bytes
84
82
  mimetype: str
85
83
  kind: MediaFileKind
86
- filename: Optional[str]
84
+ filename: str | None
87
85
 
88
86
  @property
89
87
  def content_size(self) -> int:
@@ -100,15 +98,15 @@ class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
100
98
  The name of the local endpoint that media is served from.
101
99
  This endpoint should start with a forward-slash (e.g. "/media").
102
100
  """
103
- self._files_by_id: Dict[str, MemoryFile] = {}
101
+ self._files_by_id: dict[str, MemoryFile] = {}
104
102
  self._media_endpoint = media_endpoint
105
103
 
106
104
  def load_and_get_id(
107
105
  self,
108
- path_or_data: Union[str, bytes],
106
+ path_or_data: str | bytes,
109
107
  mimetype: str,
110
108
  kind: MediaFileKind,
111
- filename: Optional[str] = None,
109
+ filename: str | None = None,
112
110
  ) -> str:
113
111
  """Add a file to the manager and return its ID."""
114
112
  file_data: bytes
@@ -121,7 +119,7 @@ class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
121
119
  # given ID, we don't need to create a new one.
122
120
  file_id = _calculate_file_id(file_data, mimetype, filename)
123
121
  if file_id not in self._files_by_id:
124
- LOGGER.debug("Adding media file %s", file_id)
122
+ _LOGGER.debug("Adding media file %s", file_id)
125
123
  media_file = MemoryFile(
126
124
  content=file_data, mimetype=mimetype, kind=kind, filename=filename
127
125
  )
@@ -167,12 +165,12 @@ class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
167
165
  except Exception as ex:
168
166
  raise MediaFileStorageError(f"Error opening '{filename}'") from ex
169
167
 
170
- def get_stats(self) -> List[CacheStat]:
168
+ def get_stats(self) -> list[CacheStat]:
171
169
  # We operate on a copy of our dict, to avoid race conditions
172
170
  # with other threads that may be manipulating the cache.
173
171
  files_by_id = self._files_by_id.copy()
174
172
 
175
- stats: List[CacheStat] = []
173
+ stats: list[CacheStat] = []
176
174
  for file_id, file in files_by_id.items():
177
175
  stats.append(
178
176
  CacheStat(
@@ -12,8 +12,9 @@
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
15
16
 
16
- from typing import List, MutableMapping, Optional
17
+ from typing import MutableMapping
17
18
 
18
19
  from streamlit.runtime.session_manager import SessionInfo, SessionStorage
19
20
  from streamlit.util import TimedCleanupCache
@@ -59,7 +60,7 @@ class MemorySessionStorage(SessionStorage):
59
60
  maxsize=maxsize, ttl=ttl_seconds
60
61
  )
61
62
 
62
- def get(self, session_id: str) -> Optional[SessionInfo]:
63
+ def get(self, session_id: str) -> SessionInfo | None:
63
64
  return self._cache.get(session_id, None)
64
65
 
65
66
  def save(self, session_info: SessionInfo) -> None:
@@ -68,5 +69,5 @@ class MemorySessionStorage(SessionStorage):
68
69
  def delete(self, session_id: str) -> None:
69
70
  del self._cache[session_id]
70
71
 
71
- def list(self) -> List[SessionInfo]:
72
+ def list(self) -> list[SessionInfo]:
72
73
  return list(self._cache.values())
@@ -12,12 +12,13 @@
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 uuid
16
18
  from collections import defaultdict
17
- from typing import Dict, List, Sequence
19
+ from typing import Sequence
18
20
 
19
21
  from streamlit import util
20
- from streamlit.logger import get_logger
21
22
  from streamlit.runtime.stats import CacheStat, group_stats
22
23
  from streamlit.runtime.uploaded_file_manager import (
23
24
  UploadedFileManager,
@@ -25,8 +26,6 @@ from streamlit.runtime.uploaded_file_manager import (
25
26
  UploadFileUrlInfo,
26
27
  )
27
28
 
28
- LOGGER = get_logger(__name__)
29
-
30
29
 
31
30
  class MemoryUploadedFileManager(UploadedFileManager):
32
31
  """Holds files uploaded by users of the running Streamlit app.
@@ -34,12 +33,12 @@ class MemoryUploadedFileManager(UploadedFileManager):
34
33
  """
35
34
 
36
35
  def __init__(self, upload_endpoint: str):
37
- self.file_storage: Dict[str, Dict[str, UploadedFileRec]] = defaultdict(dict)
36
+ self.file_storage: dict[str, dict[str, UploadedFileRec]] = defaultdict(dict)
38
37
  self.endpoint = upload_endpoint
39
38
 
40
39
  def get_files(
41
40
  self, session_id: str, file_ids: Sequence[str]
42
- ) -> List[UploadedFileRec]:
41
+ ) -> list[UploadedFileRec]:
43
42
  """Return a list of UploadedFileRec for a given sequence of file_ids.
44
43
 
45
44
  Parameters
@@ -97,7 +96,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
97
96
 
98
97
  def get_upload_urls(
99
98
  self, session_id: str, file_names: Sequence[str]
100
- ) -> List[UploadFileUrlInfo]:
99
+ ) -> list[UploadFileUrlInfo]:
101
100
  """Return a list of UploadFileUrlInfo for a given sequence of file_names."""
102
101
  result = []
103
102
  for _ in file_names:
@@ -111,13 +110,13 @@ class MemoryUploadedFileManager(UploadedFileManager):
111
110
  )
112
111
  return result
113
112
 
114
- def get_stats(self) -> List[CacheStat]:
113
+ def get_stats(self) -> list[CacheStat]:
115
114
  """Return the manager's CacheStats.
116
115
 
117
116
  Safe to call from any thread.
118
117
  """
119
118
  # Flatten all files into a single list
120
- all_files: List[UploadedFileRec] = []
119
+ all_files: list[UploadedFileRec] = []
121
120
  # Make copy of self.file_storage for thread safety, to be sure
122
121
  # that main storage won't be changed form other thread
123
122
  file_storage_copy = self.file_storage.copy()
@@ -125,7 +124,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
125
124
  for session_storage in file_storage_copy.values():
126
125
  all_files.extend(session_storage.values())
127
126
 
128
- stats: List[CacheStat] = [
127
+ stats: list[CacheStat] = [
129
128
  CacheStat(
130
129
  category_name="UploadedFileManager",
131
130
  cache_name="",