streamlit-nightly 1.31.2.dev20240212__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 (184) 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 +21 -29
  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/hashing.py +29 -21
  95. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -2
  96. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -5
  97. streamlit/runtime/connection_factory.py +8 -8
  98. streamlit/runtime/forward_msg_cache.py +20 -18
  99. streamlit/runtime/forward_msg_queue.py +8 -9
  100. streamlit/runtime/legacy_caching/caching.py +32 -42
  101. streamlit/runtime/legacy_caching/hashing.py +29 -25
  102. streamlit/runtime/media_file_manager.py +16 -14
  103. streamlit/runtime/media_file_storage.py +8 -8
  104. streamlit/runtime/memory_media_file_storage.py +12 -14
  105. streamlit/runtime/memory_session_storage.py +4 -3
  106. streamlit/runtime/memory_uploaded_file_manager.py +9 -10
  107. streamlit/runtime/metrics_util.py +20 -20
  108. streamlit/runtime/runtime.py +25 -27
  109. streamlit/runtime/runtime_util.py +5 -3
  110. streamlit/runtime/script_data.py +2 -0
  111. streamlit/runtime/scriptrunner/magic.py +17 -11
  112. streamlit/runtime/scriptrunner/magic_funcs.py +2 -0
  113. streamlit/runtime/scriptrunner/script_requests.py +6 -4
  114. streamlit/runtime/scriptrunner/script_run_context.py +17 -17
  115. streamlit/runtime/scriptrunner/script_runner.py +7 -5
  116. streamlit/runtime/secrets.py +4 -6
  117. streamlit/runtime/session_manager.py +14 -14
  118. streamlit/runtime/state/common.py +5 -4
  119. streamlit/runtime/state/query_params.py +8 -6
  120. streamlit/runtime/state/query_params_proxy.py +7 -5
  121. streamlit/runtime/state/safe_session_state.py +7 -5
  122. streamlit/runtime/state/session_state.py +3 -4
  123. streamlit/runtime/state/session_state_proxy.py +5 -5
  124. streamlit/runtime/state/widgets.py +20 -18
  125. streamlit/runtime/stats.py +13 -15
  126. streamlit/runtime/uploaded_file_manager.py +6 -5
  127. streamlit/runtime/websocket_session_manager.py +14 -14
  128. streamlit/source_util.py +13 -11
  129. streamlit/static/asset-manifest.json +13 -13
  130. streamlit/static/index.html +1 -1
  131. streamlit/static/static/css/2411.8b8f33d6.chunk.css +1 -0
  132. streamlit/static/static/css/43.e3b876c5.chunk.css +1 -0
  133. streamlit/static/static/css/6692.65519639.chunk.css +1 -0
  134. streamlit/static/static/js/{3075.76725a14.chunk.js → 2411.714d213e.chunk.js} +2 -2
  135. streamlit/static/static/js/4185.21ca0590.chunk.js +1 -0
  136. streamlit/static/static/js/43.36939bb1.chunk.js +1 -0
  137. streamlit/static/static/js/{5117.6a701db1.chunk.js → 5117.04bfe5d3.chunk.js} +1 -1
  138. streamlit/static/static/js/{5791.30b01ee8.chunk.js → 5791.c5138157.chunk.js} +1 -1
  139. streamlit/static/static/js/656.8c998bc8.chunk.js +2 -0
  140. streamlit/static/static/js/{6692.6ac4ea6f.chunk.js → 6692.6496cbc2.chunk.js} +1 -1
  141. streamlit/static/static/js/7142.400eefdd.chunk.js +1 -0
  142. streamlit/static/static/js/main.2737c0f9.js +2 -0
  143. streamlit/static/static/js/{main.043d802e.js.LICENSE.txt → main.2737c0f9.js.LICENSE.txt} +23 -25
  144. streamlit/string_util.py +13 -9
  145. streamlit/temporary_directory.py +3 -1
  146. streamlit/testing/v1/element_tree.py +1 -2
  147. streamlit/testing/v1/util.py +7 -3
  148. streamlit/type_util.py +30 -25
  149. streamlit/url_util.py +6 -4
  150. streamlit/user_info.py +8 -6
  151. streamlit/util.py +23 -37
  152. streamlit/version.py +16 -9
  153. streamlit/watcher/event_based_path_watcher.py +10 -10
  154. streamlit/watcher/local_sources_watcher.py +15 -13
  155. streamlit/watcher/path_watcher.py +0 -3
  156. streamlit/watcher/polling_path_watcher.py +9 -8
  157. streamlit/watcher/util.py +3 -2
  158. streamlit/web/cache_storage_manager_config.py +2 -0
  159. streamlit/web/server/app_static_file_handler.py +6 -5
  160. streamlit/web/server/browser_websocket_handler.py +10 -8
  161. streamlit/web/server/component_request_handler.py +7 -4
  162. streamlit/web/server/media_file_handler.py +5 -4
  163. streamlit/web/server/routes.py +6 -3
  164. streamlit/web/server/server.py +41 -34
  165. streamlit/web/server/server_util.py +8 -3
  166. streamlit/web/server/stats_request_handler.py +14 -5
  167. streamlit/web/server/upload_file_request_handler.py +7 -8
  168. streamlit/web/server/websocket_headers.py +2 -2
  169. {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/METADATA +1 -1
  170. {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/RECORD +176 -176
  171. streamlit/static/static/css/3075.81b3d18f.chunk.css +0 -1
  172. streamlit/static/static/css/43.c24b25fa.chunk.css +0 -1
  173. streamlit/static/static/css/6692.bb444a79.chunk.css +0 -1
  174. streamlit/static/static/js/1215.baf3721f.chunk.js +0 -2
  175. streamlit/static/static/js/4185.90e929dc.chunk.js +0 -1
  176. streamlit/static/static/js/43.8ca4bc8a.chunk.js +0 -1
  177. streamlit/static/static/js/7142.a359ed63.chunk.js +0 -1
  178. streamlit/static/static/js/main.043d802e.js +0 -2
  179. /streamlit/static/static/js/{3075.76725a14.chunk.js.LICENSE.txt → 2411.714d213e.chunk.js.LICENSE.txt} +0 -0
  180. /streamlit/static/static/js/{1215.baf3721f.chunk.js.LICENSE.txt → 656.8c998bc8.chunk.js.LICENSE.txt} +0 -0
  181. {streamlit_nightly-1.31.2.dev20240212.data → streamlit_nightly-1.31.2.dev20240214.data}/scripts/streamlit.cmd +0 -0
  182. {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/WHEEL +0 -0
  183. {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/entry_points.txt +0 -0
  184. {streamlit_nightly-1.31.2.dev20240212.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,9 @@
14
14
 
15
15
  """Runtime-related utility functions"""
16
16
 
17
- from typing import Any, Optional
17
+ from __future__ import annotations
18
+
19
+ from typing import Any
18
20
 
19
21
  from streamlit import config
20
22
  from streamlit.errors import MarkdownFormattedException
@@ -27,7 +29,7 @@ class MessageSizeError(MarkdownFormattedException):
27
29
 
28
30
  def __init__(self, failed_msg_str: Any):
29
31
  msg = self._get_message(failed_msg_str)
30
- super(MessageSizeError, self).__init__(msg)
32
+ super().__init__(msg)
31
33
 
32
34
  def _get_message(self, failed_msg_str: Any) -> str:
33
35
  # This needs to have zero indentation otherwise the markdown will render incorrectly.
@@ -82,7 +84,7 @@ def serialize_forward_msg(msg: ForwardMsg) -> bytes:
82
84
 
83
85
  # This needs to be initialized lazily to avoid calling config.get_option() and
84
86
  # thus initializing config options when this file is first imported.
85
- _max_message_size_bytes: Optional[int] = None
87
+ _max_message_size_bytes: int | None = None
86
88
 
87
89
 
88
90
  def get_max_message_size_bytes() -> int:
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import os
16
18
  from dataclasses import dataclass, field
17
19
 
@@ -12,9 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import ast
15
+ from __future__ import annotations
16
16
 
17
- from typing_extensions import Final
17
+ import ast
18
+ from typing import Any, Final
18
19
 
19
20
  from streamlit import config
20
21
 
@@ -24,7 +25,7 @@ from streamlit import config
24
25
  MAGIC_MODULE_NAME: Final = "__streamlitmagic__"
25
26
 
26
27
 
27
- def add_magic(code, script_path):
28
+ def add_magic(code: str, script_path: str) -> Any:
28
29
  """Modifies the code to support magic Streamlit commands.
29
30
 
30
31
  Parameters
@@ -51,7 +52,10 @@ def add_magic(code, script_path):
51
52
 
52
53
 
53
54
  def _modify_ast_subtree(
54
- tree, body_attr="body", is_root=False, file_ends_in_semicolon=False
55
+ tree: Any,
56
+ body_attr: str = "body",
57
+ is_root: bool = False,
58
+ file_ends_in_semicolon: bool = False,
55
59
  ):
56
60
  """Parses magic commands and modifies the given AST (sub)tree."""
57
61
 
@@ -118,7 +122,7 @@ def _modify_ast_subtree(
118
122
  return tree
119
123
 
120
124
 
121
- def _insert_import_statement(tree):
125
+ def _insert_import_statement(tree: Any) -> None:
122
126
  """Insert Streamlit import statement at the top(ish) of the tree."""
123
127
 
124
128
  st_import = _build_st_import_statement()
@@ -226,11 +230,11 @@ def _get_st_write_from_expr(
226
230
  return st_write
227
231
 
228
232
 
229
- def _is_string_constant_node(node):
233
+ def _is_string_constant_node(node) -> bool:
230
234
  return type(node) is ast.Constant and type(node.value) is str
231
235
 
232
236
 
233
- def _is_docstring_node(node, node_index, parent_type):
237
+ def _is_docstring_node(node, node_index, parent_type) -> bool:
234
238
  return (
235
239
  node_index == 0
236
240
  and _is_string_constant_node(node)
@@ -238,7 +242,7 @@ def _is_docstring_node(node, node_index, parent_type):
238
242
  )
239
243
 
240
244
 
241
- def _does_file_end_in_semicolon(tree, code):
245
+ def _does_file_end_in_semicolon(tree, code: str) -> bool:
242
246
  file_ends_in_semicolon = False
243
247
 
244
248
  # Avoid spending time with this operation if magic.displayLastExprIfNoSemicolon is
@@ -247,13 +251,15 @@ def _does_file_end_in_semicolon(tree, code):
247
251
  last_line_num = getattr(tree.body[-1], "end_lineno", None)
248
252
 
249
253
  if last_line_num is not None:
250
- last_line_str = code.split("\n")[last_line_num - 1]
254
+ last_line_str: str = code.split("\n")[last_line_num - 1]
251
255
  file_ends_in_semicolon = last_line_str.strip(" ").endswith(";")
252
256
 
253
257
  return file_ends_in_semicolon
254
258
 
255
259
 
256
- def _is_displayable_last_expr(is_root, is_last_expr, file_ends_in_semicolon):
260
+ def _is_displayable_last_expr(
261
+ is_root: bool, is_last_expr: bool, file_ends_in_semicolon: bool
262
+ ) -> bool:
257
263
  return (
258
264
  # This is a "displayable last expression" if...
259
265
  # ...it's actually the last expression...
@@ -267,5 +273,5 @@ def _is_displayable_last_expr(is_root, is_last_expr, file_ends_in_semicolon):
267
273
  )
268
274
 
269
275
 
270
- def _should_display_docstring_like_node_anyway(is_root):
276
+ def _should_display_docstring_like_node_anyway(is_root: bool) -> bool:
271
277
  return config.get_option("magic.displayRootDocString") and is_root
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from typing import Any
16
18
 
17
19
  from streamlit.runtime.metrics_util import gather_metrics
@@ -12,10 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import threading
16
18
  from dataclasses import dataclass
17
19
  from enum import Enum
18
- from typing import Optional, cast
20
+ from typing import cast
19
21
 
20
22
  from streamlit import util
21
23
  from streamlit.proto.WidgetStates_pb2 import WidgetStates
@@ -41,7 +43,7 @@ class RerunData:
41
43
  """Data attached to RERUN requests. Immutable."""
42
44
 
43
45
  query_string: str = ""
44
- widget_states: Optional[WidgetStates] = None
46
+ widget_states: WidgetStates | None = None
45
47
  page_script_hash: str = ""
46
48
  page_name: str = ""
47
49
 
@@ -54,7 +56,7 @@ class ScriptRequest:
54
56
  """A STOP or RERUN request and associated data."""
55
57
 
56
58
  type: ScriptRequestType
57
- _rerun_data: Optional[RerunData] = None
59
+ _rerun_data: RerunData | None = None
58
60
 
59
61
  @property
60
62
  def rerun_data(self) -> RerunData:
@@ -141,7 +143,7 @@ class ScriptRequests:
141
143
  # We'll never get here
142
144
  raise RuntimeError(f"Unrecognized ScriptRunnerState: {self._state}")
143
145
 
144
- def on_scriptrunner_yield(self) -> Optional[ScriptRequest]:
146
+ def on_scriptrunner_yield(self) -> ScriptRequest | None:
145
147
  """Called by the ScriptRunner when it's at a yield point.
146
148
 
147
149
  If we have no request, return None.
@@ -12,14 +12,16 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import collections
16
18
  import contextvars
17
19
  import threading
18
20
  from dataclasses import dataclass, field
19
- from typing import Callable, Counter, Dict, List, Optional, Set, Tuple
21
+ from typing import Callable, Counter, Dict, Final, Union
20
22
  from urllib import parse
21
23
 
22
- from typing_extensions import Final, TypeAlias
24
+ from typing_extensions import TypeAlias
23
25
 
24
26
  from streamlit import runtime
25
27
  from streamlit.errors import StreamlitAPIException
@@ -30,16 +32,16 @@ from streamlit.runtime.scriptrunner.script_requests import ScriptRequests
30
32
  from streamlit.runtime.state import SafeSessionState
31
33
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
32
34
 
33
- LOGGER: Final = get_logger(__name__)
35
+ _LOGGER: Final = get_logger(__name__)
34
36
 
35
- UserInfo: TypeAlias = Dict[str, Optional[str]]
37
+ UserInfo: TypeAlias = Dict[str, Union[str, None]]
36
38
 
37
39
 
38
40
  # The dg_stack tracks the currently active DeltaGenerator, and is pushed to when
39
41
  # a DeltaGenerator is entered via a `with` block. This is implemented as a ContextVar
40
42
  # so that different threads or async tasks can have their own stacks.
41
43
  dg_stack: contextvars.ContextVar[
42
- Tuple["streamlit.delta_generator.DeltaGenerator", ...]
44
+ tuple["streamlit.delta_generator.DeltaGenerator", ...]
43
45
  ] = contextvars.ContextVar("dg_stack", default=tuple())
44
46
 
45
47
 
@@ -69,15 +71,15 @@ class ScriptRunContext:
69
71
 
70
72
  gather_usage_stats: bool = False
71
73
  command_tracking_deactivated: bool = False
72
- tracked_commands: List[Command] = field(default_factory=list)
74
+ tracked_commands: list[Command] = field(default_factory=list)
73
75
  tracked_commands_counter: Counter[str] = field(default_factory=collections.Counter)
74
76
  _set_page_config_allowed: bool = True
75
77
  _has_script_started: bool = False
76
- widget_ids_this_run: Set[str] = field(default_factory=set)
77
- widget_user_keys_this_run: Set[str] = field(default_factory=set)
78
- form_ids_this_run: Set[str] = field(default_factory=set)
79
- cursors: Dict[int, "streamlit.cursor.RunningCursor"] = field(default_factory=dict)
80
- script_requests: Optional[ScriptRequests] = None
78
+ widget_ids_this_run: set[str] = field(default_factory=set)
79
+ widget_user_keys_this_run: set[str] = field(default_factory=set)
80
+ form_ids_this_run: set[str] = field(default_factory=set)
81
+ cursors: dict[int, "streamlit.cursor.RunningCursor"] = field(default_factory=dict)
82
+ script_requests: ScriptRequests | None = None
81
83
 
82
84
  # TODO(willhuang1997): Remove this variable when experimental query params are removed
83
85
  _experimental_query_params_used = False
@@ -153,7 +155,7 @@ SCRIPT_RUN_CONTEXT_ATTR_NAME: Final = "streamlit_script_run_ctx"
153
155
 
154
156
 
155
157
  def add_script_run_ctx(
156
- thread: Optional[threading.Thread] = None, ctx: Optional[ScriptRunContext] = None
158
+ thread: threading.Thread | None = None, ctx: ScriptRunContext | None = None
157
159
  ):
158
160
  """Adds the current ScriptRunContext to a newly-created thread.
159
161
 
@@ -183,7 +185,7 @@ def add_script_run_ctx(
183
185
  return thread
184
186
 
185
187
 
186
- def get_script_run_ctx(suppress_warning: bool = False) -> Optional[ScriptRunContext]:
188
+ def get_script_run_ctx(suppress_warning: bool = False) -> ScriptRunContext | None:
187
189
  """
188
190
  Parameters
189
191
  ----------
@@ -196,15 +198,13 @@ def get_script_run_ctx(suppress_warning: bool = False) -> Optional[ScriptRunCont
196
198
 
197
199
  """
198
200
  thread = threading.current_thread()
199
- ctx: Optional[ScriptRunContext] = getattr(
200
- thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None
201
- )
201
+ ctx: ScriptRunContext | None = getattr(thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None)
202
202
  if ctx is None and runtime.exists() and not suppress_warning:
203
203
  # Only warn about a missing ScriptRunContext if suppress_warning is False, and
204
204
  # we were started via `streamlit run`. Otherwise, the user is likely running a
205
205
  # script "bare", and doesn't need to be warned about streamlit
206
206
  # bits that are irrelevant when not connected to a session.
207
- LOGGER.warning("Thread '%s': missing ScriptRunContext", thread.name)
207
+ _LOGGER.warning("Thread '%s': missing ScriptRunContext", thread.name)
208
208
 
209
209
  return ctx
210
210
 
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import gc
16
18
  import sys
17
19
  import threading
@@ -19,7 +21,7 @@ import types
19
21
  from contextlib import contextmanager
20
22
  from enum import Enum
21
23
  from timeit import default_timer as timer
22
- from typing import Callable, Dict, Optional
24
+ from typing import Callable, Final
23
25
 
24
26
  from blinker import Signal
25
27
 
@@ -47,7 +49,7 @@ from streamlit.runtime.state import (
47
49
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
48
50
  from streamlit.vendor.ipython.modified_sys_path import modified_sys_path
49
51
 
50
- _LOGGER = get_logger(__name__)
52
+ _LOGGER: Final = get_logger(__name__)
51
53
 
52
54
 
53
55
  class ScriptRunnerEvent(Enum):
@@ -103,7 +105,7 @@ class ScriptRunner:
103
105
  uploaded_file_mgr: UploadedFileManager,
104
106
  script_cache: ScriptCache,
105
107
  initial_rerun_data: RerunData,
106
- user_info: Dict[str, Optional[str]],
108
+ user_info: dict[str, str | None],
107
109
  ):
108
110
  """Initialize the ScriptRunner.
109
111
 
@@ -181,7 +183,7 @@ class ScriptRunner:
181
183
  self._execing = False
182
184
 
183
185
  # This is initialized in start()
184
- self._script_thread: Optional[threading.Thread] = None
186
+ self._script_thread: threading.Thread | None = None
185
187
 
186
188
  def __repr__(self) -> str:
187
189
  return util.repr_(self)
@@ -493,7 +495,7 @@ class ScriptRunner:
493
495
 
494
496
  # This will be set to a RerunData instance if our execution
495
497
  # is interrupted by a RerunException.
496
- rerun_exception_data: Optional[RerunData] = None
498
+ rerun_exception_data: RerunData | None = None
497
499
 
498
500
  # If the script stops early, we don't want to remove unseen widgets,
499
501
  # so we track this to potentially skip session state cleanup later.
@@ -19,12 +19,10 @@ import threading
19
19
  from copy import deepcopy
20
20
  from typing import (
21
21
  Any,
22
- Dict,
23
22
  Final,
24
23
  ItemsView,
25
24
  Iterator,
26
25
  KeysView,
27
- List,
28
26
  Mapping,
29
27
  NoReturn,
30
28
  ValuesView,
@@ -37,8 +35,8 @@ import streamlit.watcher.path_watcher
37
35
  from streamlit import file_util, runtime
38
36
  from streamlit.logger import get_logger
39
37
 
40
- _LOGGER = get_logger(__name__)
41
- SECRETS_FILE_LOCS: Final[List[str]] = [
38
+ _LOGGER: Final = get_logger(__name__)
39
+ SECRETS_FILE_LOCS: Final[list[str]] = [
42
40
  file_util.get_streamlit_file_path("secrets.toml"),
43
41
  # NOTE: The order here is important! Project-level secrets should overwrite global
44
42
  # secrets.
@@ -107,7 +105,7 @@ class AttrDict(Mapping[str, Any]):
107
105
  def __setattr__(self, key, value) -> NoReturn:
108
106
  raise TypeError("Secrets does not support attribute assignment.")
109
107
 
110
- def to_dict(self) -> Dict[str, Any]:
108
+ def to_dict(self) -> dict[str, Any]:
111
109
  return deepcopy(self.__nested_secrets__)
112
110
 
113
111
 
@@ -118,7 +116,7 @@ class Secrets(Mapping[str, Any]):
118
116
  Safe to use from multiple threads.
119
117
  """
120
118
 
121
- def __init__(self, file_paths: List[str]):
119
+ def __init__(self, file_paths: list[str]):
122
120
  # Our secrets dict.
123
121
  self._secrets: Mapping[str, Any] | None = None
124
122
  self._lock = threading.RLock()
@@ -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 dataclasses import dataclass
17
- from typing import Callable, Dict, List, Optional, cast
18
-
19
- from typing_extensions import Protocol
19
+ from typing import Callable, Protocol, cast
20
20
 
21
21
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
22
22
  from streamlit.runtime.app_session import AppSession
@@ -64,7 +64,7 @@ class SessionInfo:
64
64
  the ForwardMsgCache.
65
65
  """
66
66
 
67
- client: Optional[SessionClient]
67
+ client: SessionClient | None
68
68
  session: AppSession
69
69
  script_run_count: int = 0
70
70
 
@@ -90,7 +90,7 @@ class SessionStorageError(Exception):
90
90
 
91
91
  class SessionStorage(Protocol):
92
92
  @abstractmethod
93
- def get(self, session_id: str) -> Optional[SessionInfo]:
93
+ def get(self, session_id: str) -> SessionInfo | None:
94
94
  """Return the SessionInfo corresponding to session_id, or None if one does not
95
95
  exist.
96
96
 
@@ -152,7 +152,7 @@ class SessionStorage(Protocol):
152
152
  raise NotImplementedError
153
153
 
154
154
  @abstractmethod
155
- def list(self) -> List[SessionInfo]:
155
+ def list(self) -> list[SessionInfo]:
156
156
  """List all sessions tracked by this SessionStorage.
157
157
 
158
158
  Returns
@@ -210,7 +210,7 @@ class SessionManager(Protocol):
210
210
  session_storage: SessionStorage,
211
211
  uploaded_file_manager: UploadedFileManager,
212
212
  script_cache: ScriptCache,
213
- message_enqueued_callback: Optional[Callable[[], None]],
213
+ message_enqueued_callback: Callable[[], None] | None,
214
214
  ) -> None:
215
215
  """Initialize a SessionManager with the given SessionStorage.
216
216
 
@@ -235,9 +235,9 @@ class SessionManager(Protocol):
235
235
  self,
236
236
  client: SessionClient,
237
237
  script_data: ScriptData,
238
- user_info: Dict[str, Optional[str]],
239
- existing_session_id: Optional[str] = None,
240
- session_id_override: Optional[str] = None,
238
+ user_info: dict[str, str | None],
239
+ existing_session_id: str | None = None,
240
+ session_id_override: str | None = None,
241
241
  ) -> str:
242
242
  """Create a new session or connect to an existing one.
243
243
 
@@ -290,7 +290,7 @@ class SessionManager(Protocol):
290
290
  raise NotImplementedError
291
291
 
292
292
  @abstractmethod
293
- def get_session_info(self, session_id: str) -> Optional[SessionInfo]:
293
+ def get_session_info(self, session_id: str) -> SessionInfo | None:
294
294
  """Return the SessionInfo for the given id, or None if no such session
295
295
  exists.
296
296
 
@@ -306,7 +306,7 @@ class SessionManager(Protocol):
306
306
  raise NotImplementedError
307
307
 
308
308
  @abstractmethod
309
- def list_sessions(self) -> List[SessionInfo]:
309
+ def list_sessions(self) -> list[SessionInfo]:
310
310
  """Return the SessionInfo for all sessions managed by this SessionManager.
311
311
 
312
312
  Returns
@@ -344,7 +344,7 @@ class SessionManager(Protocol):
344
344
  """
345
345
  self.close_session(session_id)
346
346
 
347
- def get_active_session_info(self, session_id: str) -> Optional[ActiveSessionInfo]:
347
+ def get_active_session_info(self, session_id: str) -> ActiveSessionInfo | None:
348
348
  """Return the ActiveSessionInfo for the given id, or None if either no such
349
349
  session exists or the session is not active.
350
350
 
@@ -371,7 +371,7 @@ class SessionManager(Protocol):
371
371
  """
372
372
  return self.get_active_session_info(session_id) is not None
373
373
 
374
- def list_active_sessions(self) -> List[ActiveSessionInfo]:
374
+ def list_active_sessions(self) -> list[ActiveSessionInfo]:
375
375
  """Return the session info for all active sessions tracked by this SessionManager.
376
376
 
377
377
  Returns
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """Functions and data structures shared by session_state.py and widgets.py"""
16
+
16
17
  from __future__ import annotations
17
18
 
18
19
  import hashlib
@@ -23,8 +24,8 @@ from typing import (
23
24
  Any,
24
25
  Callable,
25
26
  Dict,
27
+ Final,
26
28
  Generic,
27
- Optional,
28
29
  Sequence,
29
30
  Tuple,
30
31
  TypeVar,
@@ -32,7 +33,7 @@ from typing import (
32
33
  )
33
34
 
34
35
  from google.protobuf.message import Message
35
- from typing_extensions import Final, TypeAlias
36
+ from typing_extensions import TypeAlias
36
37
 
37
38
  from streamlit import util
38
39
  from streamlit.errors import StreamlitAPIException
@@ -151,7 +152,7 @@ class RegisterWidgetResult(Generic[T_co]):
151
152
  @classmethod
152
153
  def failure(
153
154
  cls, deserializer: WidgetDeserializer[T_co]
154
- ) -> "RegisterWidgetResult[T_co]":
155
+ ) -> RegisterWidgetResult[T_co]:
155
156
  """The canonical way to construct a RegisterWidgetResult in cases
156
157
  where the true widget value could not be determined.
157
158
  """
@@ -200,7 +201,7 @@ def compute_widget_id(
200
201
  return f"{GENERATED_WIDGET_ID_PREFIX}-{h.hexdigest()}-{user_key}"
201
202
 
202
203
 
203
- def user_key_from_widget_id(widget_id: str) -> Optional[str]:
204
+ def user_key_from_widget_id(widget_id: str) -> str | None:
204
205
  """Return the user key portion of a widget id, or None if the id does not
205
206
  have a user key.
206
207
 
@@ -12,8 +12,10 @@
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 dataclasses import dataclass, field
16
- from typing import Dict, Iterable, Iterator, List, MutableMapping, Union
18
+ from typing import Iterable, Iterator, MutableMapping
17
19
  from urllib import parse
18
20
 
19
21
  from streamlit.constants import EMBED_QUERY_PARAMS_KEYS
@@ -27,7 +29,7 @@ class QueryParams(MutableMapping[str, str]):
27
29
  It stores str keys with str and List[str] values.
28
30
  """
29
31
 
30
- _query_params: Dict[str, Union[List[str], str]] = field(default_factory=dict)
32
+ _query_params: dict[str, list[str] | str] = field(default_factory=dict)
31
33
 
32
34
  def __iter__(self) -> Iterator[str]:
33
35
  self._ensure_single_query_api_used()
@@ -59,7 +61,7 @@ class QueryParams(MutableMapping[str, str]):
59
61
  except KeyError:
60
62
  raise KeyError(missing_key_error_message(key))
61
63
 
62
- def __setitem__(self, key: str, value: Union[str, Iterable[str]]) -> None:
64
+ def __setitem__(self, key: str, value: str | Iterable[str]) -> None:
63
65
  if isinstance(value, dict):
64
66
  raise StreamlitAPIException(
65
67
  f"You cannot set a query params key `{key}` to a dictionary."
@@ -86,7 +88,7 @@ class QueryParams(MutableMapping[str, str]):
86
88
  except KeyError:
87
89
  raise KeyError(missing_key_error_message(key))
88
90
 
89
- def get_all(self, key: str) -> List[str]:
91
+ def get_all(self, key: str) -> list[str]:
90
92
  self._ensure_single_query_api_used()
91
93
  if key not in self._query_params or key in EMBED_QUERY_PARAMS_KEYS:
92
94
  return []
@@ -128,7 +130,7 @@ class QueryParams(MutableMapping[str, str]):
128
130
 
129
131
  self._send_query_param_msg()
130
132
 
131
- def to_dict(self) -> Dict[str, str]:
133
+ def to_dict(self) -> dict[str, str]:
132
134
  self._ensure_single_query_api_used()
133
135
  # return the last query param if multiple values are set
134
136
  return {
@@ -137,7 +139,7 @@ class QueryParams(MutableMapping[str, str]):
137
139
  if key not in EMBED_QUERY_PARAMS_KEYS
138
140
  }
139
141
 
140
- def set_with_no_forward_msg(self, key: str, val: Union[List[str], str]) -> None:
142
+ def set_with_no_forward_msg(self, key: str, val: list[str] | str) -> None:
141
143
  self._query_params[key] = val
142
144
 
143
145
  def clear_with_no_forward_msg(self) -> None:
@@ -12,7 +12,9 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Dict, Iterable, Iterator, List, MutableMapping, Union
15
+ from __future__ import annotations
16
+
17
+ from typing import Iterable, Iterator, MutableMapping
16
18
 
17
19
  from streamlit.runtime.metrics_util import gather_metrics
18
20
  from streamlit.runtime.state.query_params import missing_key_error_message
@@ -47,7 +49,7 @@ class QueryParamsProxy(MutableMapping[str, str]):
47
49
  del qp[key]
48
50
 
49
51
  @gather_metrics("query_params.set_item")
50
- def __setitem__(self, key: str, value: Union[str, Iterable[str]]) -> None:
52
+ def __setitem__(self, key: str, value: str | Iterable[str]) -> None:
51
53
  with get_session_state().query_params() as qp:
52
54
  qp[key] = value
53
55
 
@@ -67,12 +69,12 @@ class QueryParamsProxy(MutableMapping[str, str]):
67
69
  raise AttributeError(missing_key_error_message(key))
68
70
 
69
71
  @gather_metrics("query_params.set_attr")
70
- def __setattr__(self, key: str, value: Union[str, Iterable[str]]) -> None:
72
+ def __setattr__(self, key: str, value: str | Iterable[str]) -> None:
71
73
  with get_session_state().query_params() as qp:
72
74
  qp[key] = value
73
75
 
74
76
  @gather_metrics("query_params.get_all")
75
- def get_all(self, key: str) -> List[str]:
77
+ def get_all(self, key: str) -> list[str]:
76
78
  """
77
79
  Get a list of all query parameter values associated to a given key.
78
80
 
@@ -107,7 +109,7 @@ class QueryParamsProxy(MutableMapping[str, str]):
107
109
  qp.clear()
108
110
 
109
111
  @gather_metrics("query_params.to_dict")
110
- def to_dict(self) -> Dict[str, str]:
112
+ def to_dict(self) -> dict[str, str]:
111
113
  """
112
114
  Get all query parameters as a dictionary.
113
115
 
@@ -12,9 +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
  import threading
16
18
  from contextlib import contextmanager
17
- from typing import Any, Callable, Dict, Iterator, List, Optional, Set
19
+ from typing import Any, Callable, Iterator
18
20
 
19
21
  from streamlit.proto.WidgetStates_pb2 import WidgetState as WidgetStateProto
20
22
  from streamlit.proto.WidgetStates_pb2 import WidgetStates as WidgetStatesProto
@@ -47,7 +49,7 @@ class SafeSessionState:
47
49
  object.__setattr__(self, "_yield_callback", yield_callback)
48
50
 
49
51
  def register_widget(
50
- self, metadata: WidgetMetadata[T], user_key: Optional[str]
52
+ self, metadata: WidgetMetadata[T], user_key: str | None
51
53
  ) -> RegisterWidgetResult[T]:
52
54
  self._yield_callback()
53
55
  with self._lock:
@@ -62,7 +64,7 @@ class SafeSessionState:
62
64
  # to a Lock.)
63
65
  self._state.on_script_will_rerun(latest_widget_states)
64
66
 
65
- def on_script_finished(self, widget_ids_this_run: Set[str]) -> None:
67
+ def on_script_finished(self, widget_ids_this_run: set[str]) -> None:
66
68
  with self._lock:
67
69
  self._state.on_script_finished(widget_ids_this_run)
68
70
 
@@ -70,7 +72,7 @@ class SafeSessionState:
70
72
  with self._lock:
71
73
  self._state.maybe_check_serializable()
72
74
 
73
- def get_widget_states(self) -> List[WidgetStateProto]:
75
+ def get_widget_states(self) -> list[WidgetStateProto]:
74
76
  """Return a list of serialized widget values for each widget with a value."""
75
77
  with self._lock:
76
78
  return self._state.get_widget_states()
@@ -80,7 +82,7 @@ class SafeSessionState:
80
82
  return self._state.is_new_state_value(user_key)
81
83
 
82
84
  @property
83
- def filtered_state(self) -> Dict[str, Any]:
85
+ def filtered_state(self) -> dict[str, Any]:
84
86
  """The combined session and widget state, excluding keyless widgets."""
85
87
  with self._lock:
86
88
  return self._state.filtered_state