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
@@ -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
  from dataclasses import dataclass
16
18
  from textwrap import dedent
17
- from typing import TYPE_CHECKING, Optional, cast
19
+ from typing import TYPE_CHECKING, cast
18
20
 
19
21
  from streamlit.elements.form import current_form_id
20
22
  from streamlit.elements.utils import (
@@ -45,7 +47,7 @@ class CheckboxSerde:
45
47
  def serialize(self, v: bool) -> bool:
46
48
  return bool(v)
47
49
 
48
- def deserialize(self, ui_value: Optional[bool], widget_id: str = "") -> bool:
50
+ def deserialize(self, ui_value: bool | None, widget_id: str = "") -> bool:
49
51
  return bool(ui_value if ui_value is not None else self.value)
50
52
 
51
53
 
@@ -55,11 +57,11 @@ class CheckboxMixin:
55
57
  self,
56
58
  label: str,
57
59
  value: bool = False,
58
- key: Optional[Key] = None,
59
- help: Optional[str] = None,
60
- on_change: Optional[WidgetCallback] = None,
61
- args: Optional[WidgetArgs] = None,
62
- kwargs: Optional[WidgetKwargs] = None,
60
+ key: Key | None = None,
61
+ help: str | None = None,
62
+ on_change: WidgetCallback | None = None,
63
+ args: WidgetArgs | None = None,
64
+ kwargs: WidgetKwargs | None = None,
63
65
  *, # keyword-only arguments:
64
66
  disabled: bool = False,
65
67
  label_visibility: LabelVisibility = "visible",
@@ -158,11 +160,11 @@ class CheckboxMixin:
158
160
  self,
159
161
  label: str,
160
162
  value: bool = False,
161
- key: Optional[Key] = None,
162
- help: Optional[str] = None,
163
- on_change: Optional[WidgetCallback] = None,
164
- args: Optional[WidgetArgs] = None,
165
- kwargs: Optional[WidgetKwargs] = None,
163
+ key: Key | None = None,
164
+ help: str | None = None,
165
+ on_change: WidgetCallback | None = None,
166
+ args: WidgetArgs | None = None,
167
+ kwargs: WidgetKwargs | None = None,
166
168
  *, # keyword-only arguments:
167
169
  disabled: bool = False,
168
170
  label_visibility: LabelVisibility = "visible",
@@ -260,16 +262,16 @@ class CheckboxMixin:
260
262
  self,
261
263
  label: str,
262
264
  value: bool = False,
263
- key: Optional[Key] = None,
264
- help: Optional[str] = None,
265
- on_change: Optional[WidgetCallback] = None,
266
- args: Optional[WidgetArgs] = None,
267
- kwargs: Optional[WidgetKwargs] = None,
265
+ key: Key | None = None,
266
+ help: str | None = None,
267
+ on_change: WidgetCallback | None = None,
268
+ args: WidgetArgs | None = None,
269
+ kwargs: WidgetKwargs | None = None,
268
270
  *, # keyword-only arguments:
269
271
  disabled: bool = False,
270
272
  label_visibility: LabelVisibility = "visible",
271
273
  type: CheckboxProto.StyleType.ValueType = CheckboxProto.StyleType.DEFAULT,
272
- ctx: Optional[ScriptRunContext] = None,
274
+ ctx: ScriptRunContext | None = None,
273
275
  ) -> bool:
274
276
  key = to_key(key)
275
277
  check_callback_rules(self.dg, on_change)
@@ -326,6 +328,6 @@ class CheckboxMixin:
326
328
  return checkbox_state.value
327
329
 
328
330
  @property
329
- def dg(self) -> "DeltaGenerator":
331
+ def dg(self) -> DeltaGenerator:
330
332
  """Get our DeltaGenerator."""
331
333
  return cast("DeltaGenerator", self)
@@ -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 re
16
18
  from dataclasses import dataclass
17
19
  from textwrap import dedent
18
- from typing import Optional, cast
20
+ from typing import cast
19
21
 
20
22
  import streamlit
21
23
  from streamlit.elements.form import current_form_id
@@ -45,7 +47,7 @@ class ColorPickerSerde:
45
47
  def serialize(self, v: str) -> str:
46
48
  return str(v)
47
49
 
48
- def deserialize(self, ui_value: Optional[str], widget_id: str = "") -> str:
50
+ def deserialize(self, ui_value: str | None, widget_id: str = "") -> str:
49
51
  return str(ui_value if ui_value is not None else self.value)
50
52
 
51
53
 
@@ -54,12 +56,12 @@ class ColorPickerMixin:
54
56
  def color_picker(
55
57
  self,
56
58
  label: str,
57
- value: Optional[str] = None,
58
- key: Optional[Key] = None,
59
- help: Optional[str] = None,
60
- on_change: Optional[WidgetCallback] = None,
61
- args: Optional[WidgetArgs] = None,
62
- kwargs: Optional[WidgetKwargs] = None,
59
+ value: str | None = None,
60
+ key: Key | None = None,
61
+ help: str | None = None,
62
+ on_change: WidgetCallback | None = None,
63
+ args: WidgetArgs | None = None,
64
+ kwargs: WidgetKwargs | None = None,
63
65
  *, # keyword-only arguments:
64
66
  disabled: bool = False,
65
67
  label_visibility: LabelVisibility = "visible",
@@ -155,16 +157,16 @@ class ColorPickerMixin:
155
157
  def _color_picker(
156
158
  self,
157
159
  label: str,
158
- value: Optional[str] = None,
159
- key: Optional[Key] = None,
160
- help: Optional[str] = None,
161
- on_change: Optional[WidgetCallback] = None,
162
- args: Optional[WidgetArgs] = None,
163
- kwargs: Optional[WidgetKwargs] = None,
160
+ value: str | None = None,
161
+ key: Key | None = None,
162
+ help: str | None = None,
163
+ on_change: WidgetCallback | None = None,
164
+ args: WidgetArgs | None = None,
165
+ kwargs: WidgetKwargs | None = None,
164
166
  *, # keyword-only arguments:
165
167
  disabled: bool = False,
166
168
  label_visibility: LabelVisibility = "visible",
167
- ctx: Optional[ScriptRunContext] = None,
169
+ ctx: ScriptRunContext | None = None,
168
170
  ) -> str:
169
171
  key = to_key(key)
170
172
  check_callback_rules(self.dg, on_change)
@@ -243,6 +245,6 @@ class ColorPickerMixin:
243
245
  return widget_state.value
244
246
 
245
247
  @property
246
- def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
248
+ def dg(self) -> streamlit.delta_generator.DeltaGenerator:
247
249
  """Get our DeltaGenerator."""
248
250
  return cast("streamlit.delta_generator.DeltaGenerator", self)
@@ -130,9 +130,9 @@ class EditingState(TypedDict, total=False):
130
130
  A list of deleted rows, where each row is the numerical position of the deleted row.
131
131
  """
132
132
 
133
- edited_rows: Dict[int, Dict[str, str | int | float | bool | None]]
134
- added_rows: List[Dict[str, str | int | float | bool | None]]
135
- deleted_rows: List[int]
133
+ edited_rows: dict[int, dict[str, str | int | float | bool | None]]
134
+ added_rows: list[dict[str, str | int | float | bool | None]]
135
+ deleted_rows: list[int]
136
136
 
137
137
 
138
138
  @dataclass
@@ -281,7 +281,7 @@ def _apply_cell_edits(
281
281
 
282
282
  def _apply_row_additions(
283
283
  df: pd.DataFrame,
284
- added_rows: List[Dict[str, Any]],
284
+ added_rows: list[dict[str, Any]],
285
285
  dataframe_schema: DataframeSchema,
286
286
  ) -> None:
287
287
  """Apply row additions to the provided dataframe (inplace).
@@ -315,7 +315,7 @@ def _apply_row_additions(
315
315
 
316
316
  for added_row in added_rows:
317
317
  index_value = None
318
- new_row: List[Any] = [None for _ in range(df.shape[1])]
318
+ new_row: list[Any] = [None for _ in range(df.shape[1])]
319
319
  for col_name in added_row.keys():
320
320
  value = added_row[col_name]
321
321
  if col_name == INDEX_IDENTIFIER:
@@ -339,7 +339,7 @@ def _apply_row_additions(
339
339
  df.loc[index_value, :] = new_row
340
340
 
341
341
 
342
- def _apply_row_deletions(df: pd.DataFrame, deleted_rows: List[int]) -> None:
342
+ def _apply_row_deletions(df: pd.DataFrame, deleted_rows: list[int]) -> None:
343
343
  """Apply row deletions to the provided dataframe (inplace).
344
344
 
345
345
  Parameters
@@ -930,7 +930,7 @@ class DataEditorMixin:
930
930
  return type_util.convert_df_to_data_format(data_df, data_format)
931
931
 
932
932
  @property
933
- def dg(self) -> "DeltaGenerator":
933
+ def dg(self) -> DeltaGenerator:
934
934
  """Get our DeltaGenerator."""
935
935
  return cast("DeltaGenerator", self)
936
936
 
@@ -11,13 +11,15 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
14
17
  from dataclasses import dataclass
15
18
  from textwrap import dedent
16
- from typing import List, Optional, Sequence, Union, cast, overload
19
+ from typing import TYPE_CHECKING, List, Literal, Sequence, Union, cast, overload
17
20
 
18
- from typing_extensions import Literal
21
+ from typing_extensions import TypeAlias
19
22
 
20
- import streamlit
21
23
  from streamlit import config
22
24
  from streamlit.elements.form import current_form_id
23
25
  from streamlit.elements.utils import (
@@ -40,13 +42,17 @@ from streamlit.runtime.state.common import compute_widget_id
40
42
  from streamlit.runtime.uploaded_file_manager import DeletedFile, UploadedFile
41
43
  from streamlit.type_util import Key, LabelVisibility, maybe_raise_label_warnings, to_key
42
44
 
43
- SomeUploadedFiles = Union[
45
+ if TYPE_CHECKING:
46
+ from streamlit.delta_generator import DeltaGenerator
47
+
48
+ SomeUploadedFiles: TypeAlias = Union[
44
49
  UploadedFile,
45
50
  DeletedFile,
46
51
  List[Union[UploadedFile, DeletedFile]],
47
52
  None,
48
53
  ]
49
54
 
55
+
50
56
  TYPE_PAIRS = [
51
57
  (".jpg", ".jpeg"),
52
58
  (".mpg", ".mpeg"),
@@ -57,8 +63,8 @@ TYPE_PAIRS = [
57
63
 
58
64
 
59
65
  def _get_upload_files(
60
- widget_value: Optional[FileUploaderStateProto],
61
- ) -> List[Union[UploadedFile, DeletedFile]]:
66
+ widget_value: FileUploaderStateProto | None,
67
+ ) -> list[UploadedFile | DeletedFile]:
62
68
  if widget_value is None:
63
69
  return []
64
70
 
@@ -77,7 +83,7 @@ def _get_upload_files(
77
83
 
78
84
  file_recs = {f.file_id: f for f in file_recs_list}
79
85
 
80
- collected_files: List[Union[UploadedFile, DeletedFile]] = []
86
+ collected_files: list[UploadedFile | DeletedFile] = []
81
87
 
82
88
  for f in uploaded_file_info:
83
89
  maybe_file_rec = file_recs.get(f.file_id)
@@ -95,7 +101,7 @@ class FileUploaderSerde:
95
101
  accept_multiple_files: bool
96
102
 
97
103
  def deserialize(
98
- self, ui_value: Optional[FileUploaderStateProto], widget_id: str
104
+ self, ui_value: FileUploaderStateProto | None, widget_id: str
99
105
  ) -> SomeUploadedFiles:
100
106
  upload_files = _get_upload_files(ui_value)
101
107
 
@@ -144,17 +150,17 @@ class FileUploaderMixin:
144
150
  def file_uploader(
145
151
  self,
146
152
  label: str,
147
- type: Union[str, Sequence[str], None],
153
+ type: str | Sequence[str] | None,
148
154
  accept_multiple_files: Literal[True],
149
- key: Optional[Key] = None,
150
- help: Optional[str] = None,
151
- on_change: Optional[WidgetCallback] = None,
152
- args: Optional[WidgetArgs] = None,
153
- kwargs: Optional[WidgetKwargs] = None,
155
+ key: Key | None = None,
156
+ help: str | None = None,
157
+ on_change: WidgetCallback | None = None,
158
+ args: WidgetArgs | None = None,
159
+ kwargs: WidgetKwargs | None = None,
154
160
  *,
155
161
  disabled: bool = False,
156
162
  label_visibility: LabelVisibility = "visible",
157
- ) -> Optional[List[UploadedFile]]:
163
+ ) -> list[UploadedFile] | None:
158
164
  ...
159
165
 
160
166
  # 1. type is given as not a keyword-only argument
@@ -163,17 +169,17 @@ class FileUploaderMixin:
163
169
  def file_uploader(
164
170
  self,
165
171
  label: str,
166
- type: Union[str, Sequence[str], None],
172
+ type: str | Sequence[str] | None,
167
173
  accept_multiple_files: Literal[False] = False,
168
- key: Optional[Key] = None,
169
- help: Optional[str] = None,
170
- on_change: Optional[WidgetCallback] = None,
171
- args: Optional[WidgetArgs] = None,
172
- kwargs: Optional[WidgetKwargs] = None,
174
+ key: Key | None = None,
175
+ help: str | None = None,
176
+ on_change: WidgetCallback | None = None,
177
+ args: WidgetArgs | None = None,
178
+ kwargs: WidgetKwargs | None = None,
173
179
  *,
174
180
  disabled: bool = False,
175
181
  label_visibility: LabelVisibility = "visible",
176
- ) -> Optional[UploadedFile]:
182
+ ) -> UploadedFile | None:
177
183
  ...
178
184
 
179
185
  # The following 2 overloads represent the cases where
@@ -189,15 +195,15 @@ class FileUploaderMixin:
189
195
  label: str,
190
196
  *,
191
197
  accept_multiple_files: Literal[True],
192
- type: Union[str, Sequence[str], None] = None,
193
- key: Optional[Key] = None,
194
- help: Optional[str] = None,
195
- on_change: Optional[WidgetCallback] = None,
196
- args: Optional[WidgetArgs] = None,
197
- kwargs: Optional[WidgetKwargs] = None,
198
+ type: str | Sequence[str] | None = None,
199
+ key: Key | None = None,
200
+ help: str | None = None,
201
+ on_change: WidgetCallback | None = None,
202
+ args: WidgetArgs | None = None,
203
+ kwargs: WidgetKwargs | None = None,
198
204
  disabled: bool = False,
199
205
  label_visibility: LabelVisibility = "visible",
200
- ) -> Optional[List[UploadedFile]]:
206
+ ) -> list[UploadedFile] | None:
201
207
  ...
202
208
 
203
209
  # 1. type is skipped or a keyword argument
@@ -208,32 +214,32 @@ class FileUploaderMixin:
208
214
  label: str,
209
215
  *,
210
216
  accept_multiple_files: Literal[False] = False,
211
- type: Union[str, Sequence[str], None] = None,
212
- key: Optional[Key] = None,
213
- help: Optional[str] = None,
214
- on_change: Optional[WidgetCallback] = None,
215
- args: Optional[WidgetArgs] = None,
216
- kwargs: Optional[WidgetKwargs] = None,
217
+ type: str | Sequence[str] | None = None,
218
+ key: Key | None = None,
219
+ help: str | None = None,
220
+ on_change: WidgetCallback | None = None,
221
+ args: WidgetArgs | None = None,
222
+ kwargs: WidgetKwargs | None = None,
217
223
  disabled: bool = False,
218
224
  label_visibility: LabelVisibility = "visible",
219
- ) -> Optional[UploadedFile]:
225
+ ) -> UploadedFile | None:
220
226
  ...
221
227
 
222
228
  @gather_metrics("file_uploader")
223
229
  def file_uploader(
224
230
  self,
225
231
  label: str,
226
- type: Union[str, Sequence[str], None] = None,
232
+ type: str | Sequence[str] | None = None,
227
233
  accept_multiple_files: bool = False,
228
- key: Optional[Key] = None,
229
- help: Optional[str] = None,
230
- on_change: Optional[WidgetCallback] = None,
231
- args: Optional[WidgetArgs] = None,
232
- kwargs: Optional[WidgetKwargs] = None,
234
+ key: Key | None = None,
235
+ help: str | None = None,
236
+ on_change: WidgetCallback | None = None,
237
+ args: WidgetArgs | None = None,
238
+ kwargs: WidgetKwargs | None = None,
233
239
  *, # keyword-only arguments:
234
240
  disabled: bool = False,
235
241
  label_visibility: LabelVisibility = "visible",
236
- ) -> Union[UploadedFile, List[UploadedFile], None]:
242
+ ) -> UploadedFile | list[UploadedFile] | None:
237
243
  r"""Display a file uploader widget.
238
244
  By default, uploaded files are limited to 200MB. You can configure
239
245
  this using the `server.maxUploadSize` config option. For more info
@@ -379,18 +385,18 @@ class FileUploaderMixin:
379
385
  def _file_uploader(
380
386
  self,
381
387
  label: str,
382
- type: Union[str, Sequence[str], None] = None,
388
+ type: str | Sequence[str] | None = None,
383
389
  accept_multiple_files: bool = False,
384
- key: Optional[Key] = None,
385
- help: Optional[str] = None,
386
- on_change: Optional[WidgetCallback] = None,
387
- args: Optional[WidgetArgs] = None,
388
- kwargs: Optional[WidgetKwargs] = None,
390
+ key: Key | None = None,
391
+ help: str | None = None,
392
+ on_change: WidgetCallback | None = None,
393
+ args: WidgetArgs | None = None,
394
+ kwargs: WidgetKwargs | None = None,
389
395
  *, # keyword-only arguments:
390
396
  label_visibility: LabelVisibility = "visible",
391
397
  disabled: bool = False,
392
- ctx: Optional[ScriptRunContext] = None,
393
- ) -> Union[UploadedFile, List[UploadedFile], None]:
398
+ ctx: ScriptRunContext | None = None,
399
+ ) -> UploadedFile | list[UploadedFile] | None:
394
400
  key = to_key(key)
395
401
  check_callback_rules(self.dg, on_change)
396
402
  check_session_state_rules(default_value=None, key=key, writes_allowed=False)
@@ -463,8 +469,6 @@ class FileUploaderMixin:
463
469
 
464
470
  self.dg._enqueue("file_uploader", file_uploader_proto)
465
471
 
466
- filtered_value: Union[UploadedFile, List[UploadedFile], None]
467
-
468
472
  if isinstance(widget_state.value, DeletedFile):
469
473
  return None
470
474
  elif isinstance(widget_state.value, list):
@@ -473,6 +477,6 @@ class FileUploaderMixin:
473
477
  return widget_state.value
474
478
 
475
479
  @property
476
- def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
480
+ def dg(self) -> DeltaGenerator:
477
481
  """Get our DeltaGenerator."""
478
- return cast("streamlit.delta_generator.DeltaGenerator", self)
482
+ return cast("DeltaGenerator", self)
@@ -12,20 +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 dataclasses import dataclass
16
18
  from textwrap import dedent
17
- from typing import (
18
- TYPE_CHECKING,
19
- Any,
20
- Callable,
21
- Generic,
22
- List,
23
- Optional,
24
- Sequence,
25
- Union,
26
- cast,
27
- overload,
28
- )
19
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Sequence, cast, overload
29
20
 
30
21
  from streamlit.elements.form import current_form_id
31
22
  from streamlit.elements.utils import (
@@ -65,20 +56,20 @@ if TYPE_CHECKING:
65
56
  @overload
66
57
  def _check_and_convert_to_indices( # type: ignore[misc]
67
58
  opt: Sequence[Any], default_values: None
68
- ) -> Optional[List[int]]:
59
+ ) -> list[int] | None:
69
60
  ...
70
61
 
71
62
 
72
63
  @overload
73
64
  def _check_and_convert_to_indices(
74
- opt: Sequence[Any], default_values: Union[Sequence[Any], Any]
75
- ) -> List[int]:
65
+ opt: Sequence[Any], default_values: Sequence[Any] | Any
66
+ ) -> list[int]:
76
67
  ...
77
68
 
78
69
 
79
70
  def _check_and_convert_to_indices(
80
- opt: Sequence[Any], default_values: Union[Sequence[Any], Any, None]
81
- ) -> Optional[List[int]]:
71
+ opt: Sequence[Any], default_values: Sequence[Any] | Any | None
72
+ ) -> list[int] | None:
82
73
  """Perform validation checks and return indices based on the default values."""
83
74
  if default_values is None and None not in opt:
84
75
  return None
@@ -105,7 +96,7 @@ def _check_and_convert_to_indices(
105
96
  return [opt.index(value) for value in default_values]
106
97
 
107
98
 
108
- def _get_default_count(default: Union[Sequence[Any], Any, None]) -> int:
99
+ def _get_default_count(default: Sequence[Any] | Any | None) -> int:
109
100
  if default is None:
110
101
  return 0
111
102
  if not is_iterable(default):
@@ -128,17 +119,17 @@ Please select at most {max_selections} {max_selections_noun}.
128
119
  @dataclass
129
120
  class MultiSelectSerde(Generic[T]):
130
121
  options: Sequence[T]
131
- default_value: List[int]
122
+ default_value: list[int]
132
123
 
133
- def serialize(self, value: List[T]) -> List[int]:
124
+ def serialize(self, value: list[T]) -> list[int]:
134
125
  return _check_and_convert_to_indices(self.options, value)
135
126
 
136
127
  def deserialize(
137
128
  self,
138
- ui_value: Optional[List[int]],
129
+ ui_value: list[int] | None,
139
130
  widget_id: str = "",
140
- ) -> List[T]:
141
- current_value: List[int] = (
131
+ ) -> list[T]:
132
+ current_value: list[int] = (
142
133
  ui_value if ui_value is not None else self.default_value
143
134
  )
144
135
  return [self.options[i] for i in current_value]
@@ -150,19 +141,19 @@ class MultiSelectMixin:
150
141
  self,
151
142
  label: str,
152
143
  options: OptionSequence[T],
153
- default: Optional[Any] = None,
144
+ default: Any | None = None,
154
145
  format_func: Callable[[Any], Any] = str,
155
- key: Optional[Key] = None,
156
- help: Optional[str] = None,
157
- on_change: Optional[WidgetCallback] = None,
158
- args: Optional[WidgetArgs] = None,
159
- kwargs: Optional[WidgetKwargs] = None,
146
+ key: Key | None = None,
147
+ help: str | None = None,
148
+ on_change: WidgetCallback | None = None,
149
+ args: WidgetArgs | None = None,
150
+ kwargs: WidgetKwargs | None = None,
160
151
  *, # keyword-only arguments:
161
- max_selections: Optional[int] = None,
152
+ max_selections: int | None = None,
162
153
  placeholder: str = "Choose an option",
163
154
  disabled: bool = False,
164
155
  label_visibility: LabelVisibility = "visible",
165
- ) -> List[T]:
156
+ ) -> list[T]:
166
157
  r"""Display a multiselect widget.
167
158
  The multiselect widget starts as empty.
168
159
 
@@ -276,20 +267,20 @@ class MultiSelectMixin:
276
267
  self,
277
268
  label: str,
278
269
  options: OptionSequence[T],
279
- default: Union[Sequence[Any], Any, None] = None,
270
+ default: Sequence[Any] | Any | None = None,
280
271
  format_func: Callable[[Any], Any] = str,
281
- key: Optional[Key] = None,
282
- help: Optional[str] = None,
283
- on_change: Optional[WidgetCallback] = None,
284
- args: Optional[WidgetArgs] = None,
285
- kwargs: Optional[WidgetKwargs] = None,
272
+ key: Key | None = None,
273
+ help: str | None = None,
274
+ on_change: WidgetCallback | None = None,
275
+ args: WidgetArgs | None = None,
276
+ kwargs: WidgetKwargs | None = None,
286
277
  *, # keyword-only arguments:
287
- max_selections: Optional[int] = None,
278
+ max_selections: int | None = None,
288
279
  placeholder: str = "Choose an option",
289
280
  disabled: bool = False,
290
281
  label_visibility: LabelVisibility = "visible",
291
- ctx: Optional[ScriptRunContext] = None,
292
- ) -> List[T]:
282
+ ctx: ScriptRunContext | None = None,
283
+ ) -> list[T]:
293
284
  key = to_key(key)
294
285
  check_callback_rules(self.dg, on_change)
295
286
  check_session_state_rules(default_value=default, key=key)
@@ -314,7 +305,7 @@ class MultiSelectMixin:
314
305
  page=ctx.page_script_hash if ctx else None,
315
306
  )
316
307
 
317
- default_value: List[int] = [] if indices is None else indices
308
+ default_value: list[int] = [] if indices is None else indices
318
309
 
319
310
  multiselect_proto = MultiSelectProto()
320
311
  multiselect_proto.id = id
@@ -360,6 +351,6 @@ class MultiSelectMixin:
360
351
  return widget_state.value
361
352
 
362
353
  @property
363
- def dg(self) -> "DeltaGenerator":
354
+ def dg(self) -> DeltaGenerator:
364
355
  """Get our DeltaGenerator."""
365
356
  return cast("DeltaGenerator", self)
@@ -17,9 +17,10 @@ from __future__ import annotations
17
17
  import numbers
18
18
  from dataclasses import dataclass
19
19
  from textwrap import dedent
20
- from typing import Literal, Union, cast, overload
20
+ from typing import TYPE_CHECKING, Literal, Union, cast, overload
21
+
22
+ from typing_extensions import TypeAlias
21
23
 
22
- import streamlit
23
24
  from streamlit.elements.form import current_form_id
24
25
  from streamlit.elements.utils import (
25
26
  check_callback_rules,
@@ -40,7 +41,11 @@ from streamlit.runtime.state import (
40
41
  from streamlit.runtime.state.common import compute_widget_id
41
42
  from streamlit.type_util import Key, LabelVisibility, maybe_raise_label_warnings, to_key
42
43
 
43
- Number = Union[int, float]
44
+ if TYPE_CHECKING:
45
+ from streamlit.delta_generator import DeltaGenerator
46
+
47
+
48
+ Number: TypeAlias = Union[int, float]
44
49
 
45
50
 
46
51
  @dataclass
@@ -461,6 +466,6 @@ class NumberInputMixin:
461
466
  return widget_state.value
462
467
 
463
468
  @property
464
- def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
469
+ def dg(self) -> DeltaGenerator:
465
470
  """Get our DeltaGenerator."""
466
- return cast("streamlit.delta_generator.DeltaGenerator", self)
471
+ return cast("DeltaGenerator", self)
@@ -334,6 +334,6 @@ class RadioMixin:
334
334
  return widget_state.value
335
335
 
336
336
  @property
337
- def dg(self) -> "DeltaGenerator":
337
+ def dg(self) -> DeltaGenerator:
338
338
  """Get our DeltaGenerator."""
339
339
  return cast("DeltaGenerator", self)