streamlit-nightly 1.38.1.dev20240902__py2.py3-none-any.whl → 1.38.1.dev20240903__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 (40) hide show
  1. streamlit/components/v1/custom_component.py +3 -5
  2. streamlit/delta_generator.py +5 -0
  3. streamlit/elements/arrow.py +2 -4
  4. streamlit/elements/layouts.py +19 -1
  5. streamlit/elements/lib/utils.py +120 -2
  6. streamlit/elements/media.py +3 -3
  7. streamlit/elements/plotly_chart.py +13 -9
  8. streamlit/elements/vega_charts.py +2 -4
  9. streamlit/elements/widgets/button.py +6 -6
  10. streamlit/elements/widgets/button_group.py +2 -3
  11. streamlit/elements/widgets/camera_input.py +2 -3
  12. streamlit/elements/widgets/chat.py +5 -4
  13. streamlit/elements/widgets/checkbox.py +2 -3
  14. streamlit/elements/widgets/color_picker.py +2 -3
  15. streamlit/elements/widgets/data_editor.py +2 -4
  16. streamlit/elements/widgets/file_uploader.py +2 -3
  17. streamlit/elements/widgets/multiselect.py +5 -3
  18. streamlit/elements/widgets/number_input.py +2 -3
  19. streamlit/elements/widgets/radio.py +5 -3
  20. streamlit/elements/widgets/select_slider.py +2 -3
  21. streamlit/elements/widgets/selectbox.py +5 -3
  22. streamlit/elements/widgets/slider.py +2 -3
  23. streamlit/elements/widgets/text_widgets.py +3 -5
  24. streamlit/elements/widgets/time_widgets.py +3 -5
  25. streamlit/errors.py +25 -0
  26. streamlit/proto/Block_pb2.py +28 -28
  27. streamlit/proto/Block_pb2.pyi +8 -2
  28. streamlit/runtime/app_session.py +2 -1
  29. streamlit/runtime/state/common.py +3 -51
  30. streamlit/runtime/state/widgets.py +1 -68
  31. streamlit/static/asset-manifest.json +2 -2
  32. streamlit/static/index.html +1 -1
  33. streamlit/static/static/js/{main.3454bbd6.js → main.ba0d2afb.js} +4 -4
  34. {streamlit_nightly-1.38.1.dev20240902.dist-info → streamlit_nightly-1.38.1.dev20240903.dist-info}/METADATA +1 -1
  35. {streamlit_nightly-1.38.1.dev20240902.dist-info → streamlit_nightly-1.38.1.dev20240903.dist-info}/RECORD +40 -40
  36. {streamlit_nightly-1.38.1.dev20240902.dist-info → streamlit_nightly-1.38.1.dev20240903.dist-info}/WHEEL +1 -1
  37. /streamlit/static/static/js/{main.3454bbd6.js.LICENSE.txt → main.ba0d2afb.js.LICENSE.txt} +0 -0
  38. {streamlit_nightly-1.38.1.dev20240902.data → streamlit_nightly-1.38.1.dev20240903.data}/scripts/streamlit.cmd +0 -0
  39. {streamlit_nightly-1.38.1.dev20240902.dist-info → streamlit_nightly-1.38.1.dev20240903.dist-info}/entry_points.txt +0 -0
  40. {streamlit_nightly-1.38.1.dev20240902.dist-info → streamlit_nightly-1.38.1.dev20240903.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,7 @@ from streamlit.dataframe_util import is_dataframe_like
22
22
  from streamlit.delta_generator_singletons import get_dg_singleton_instance
23
23
  from streamlit.elements.form_utils import current_form_id
24
24
  from streamlit.elements.lib.policies import check_cache_replay_rules
25
+ from streamlit.elements.lib.utils import compute_and_register_element_id
25
26
  from streamlit.errors import StreamlitAPIException
26
27
  from streamlit.proto.Components_pb2 import ArrowTable as ArrowTableProto
27
28
  from streamlit.proto.Components_pb2 import SpecialArg
@@ -29,7 +30,6 @@ from streamlit.proto.Element_pb2 import Element
29
30
  from streamlit.runtime.metrics_util import gather_metrics
30
31
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
31
32
  from streamlit.runtime.state import NoValue, register_widget
32
- from streamlit.runtime.state.common import compute_element_id
33
33
  from streamlit.type_util import is_bytes_like, to_bytes
34
34
 
35
35
  if TYPE_CHECKING:
@@ -172,7 +172,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
172
172
 
173
173
  if key is None:
174
174
  marshall_element_args()
175
- computed_id = compute_element_id(
175
+ computed_id = compute_and_register_element_id(
176
176
  "component_instance",
177
177
  user_key=key,
178
178
  name=self.name,
@@ -184,7 +184,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
184
184
  page=ctx.active_script_hash if ctx else None,
185
185
  )
186
186
  else:
187
- computed_id = compute_element_id(
187
+ computed_id = compute_and_register_element_id(
188
188
  "component_instance",
189
189
  user_key=key,
190
190
  name=self.name,
@@ -202,8 +202,6 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
202
202
  component_state = register_widget(
203
203
  element_type="component_instance",
204
204
  element_proto=element.component_instance,
205
- user_key=key,
206
- widget_func_name=self.name,
207
205
  deserializer=deserialize_component,
208
206
  serializer=lambda x: x,
209
207
  ctx=ctx,
@@ -417,6 +417,7 @@ class DeltaGenerator(
417
417
  delta_type: str,
418
418
  element_proto: Message,
419
419
  add_rows_metadata: AddRowsMetadata | None = None,
420
+ user_key: str | None = None,
420
421
  ) -> DeltaGenerator:
421
422
  """Create NewElement delta, fill it, and enqueue it.
422
423
 
@@ -426,6 +427,10 @@ class DeltaGenerator(
426
427
  The name of the streamlit method being called
427
428
  element_proto : proto
428
429
  The actual proto in the NewElement type e.g. Alert/Button/Slider
430
+ add_rows_metadata : AddRowsMetadata or None
431
+ Metadata for the add_rows method
432
+ user_key : str or None
433
+ A custom key for the element provided by the user.
429
434
 
430
435
  Returns
431
436
  -------
@@ -43,7 +43,7 @@ from streamlit.elements.lib.column_config_utils import (
43
43
  from streamlit.elements.lib.event_utils import AttributeDictionary
44
44
  from streamlit.elements.lib.pandas_styler_utils import marshall_styler
45
45
  from streamlit.elements.lib.policies import check_widget_policies
46
- from streamlit.elements.lib.utils import Key, to_key
46
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
47
47
  from streamlit.errors import StreamlitAPIException
48
48
  from streamlit.proto.Arrow_pb2 import Arrow as ArrowProto
49
49
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
@@ -53,7 +53,6 @@ from streamlit.runtime.scriptrunner_utils.script_run_context import (
53
53
  get_script_run_ctx,
54
54
  )
55
55
  from streamlit.runtime.state import WidgetCallback, register_widget
56
- from streamlit.runtime.state.common import compute_element_id
57
56
 
58
57
  if TYPE_CHECKING:
59
58
  from numpy import typing as npt
@@ -566,7 +565,7 @@ class ArrowMixin:
566
565
  proto.form_id = current_form_id(self.dg)
567
566
 
568
567
  ctx = get_script_run_ctx()
569
- proto.id = compute_element_id(
568
+ proto.id = compute_and_register_element_id(
570
569
  "dataframe",
571
570
  user_key=key,
572
571
  data=proto.data,
@@ -586,7 +585,6 @@ class ArrowMixin:
586
585
  widget_state = register_widget(
587
586
  "dataframe",
588
587
  proto,
589
- user_key=key,
590
588
  on_change_handler=on_select if callable(on_select) else None,
591
589
  deserializer=serde.deserialize,
592
590
  serializer=serde.serialize,
@@ -19,6 +19,7 @@ from typing import TYPE_CHECKING, Literal, Sequence, Union, cast
19
19
  from typing_extensions import TypeAlias
20
20
 
21
21
  from streamlit.delta_generator_singletons import get_dg_singleton_instance
22
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
22
23
  from streamlit.errors import StreamlitAPIException
23
24
  from streamlit.proto.Block_pb2 import Block as BlockProto
24
25
  from streamlit.runtime.metrics_util import gather_metrics
@@ -35,7 +36,11 @@ SpecType: TypeAlias = Union[int, Sequence[Union[int, float]]]
35
36
  class LayoutsMixin:
36
37
  @gather_metrics("container")
37
38
  def container(
38
- self, *, height: int | None = None, border: bool | None = None
39
+ self,
40
+ *,
41
+ height: int | None = None,
42
+ border: bool | None = None,
43
+ key: Key | None = None,
39
44
  ) -> DeltaGenerator:
40
45
  """Insert a multi-element container.
41
46
 
@@ -49,6 +54,7 @@ class LayoutsMixin:
49
54
 
50
55
  Parameters
51
56
  ----------
57
+
52
58
  height : int or None
53
59
  Desired height of the container expressed in pixels. If ``None`` (default)
54
60
  the container grows to fit its content. If a fixed height, scrolling is
@@ -66,6 +72,12 @@ class LayoutsMixin:
66
72
  border is shown if the container is set to a fixed height and not
67
73
  shown otherwise.
68
74
 
75
+ key : str or None
76
+ An optional string to give this container a stable identity.
77
+
78
+ Additionally, if ``key`` is provided, it will be used as CSS
79
+ class name prefixed with ``st-key-``.
80
+
69
81
 
70
82
  Examples
71
83
  --------
@@ -129,6 +141,7 @@ class LayoutsMixin:
129
141
  height: 400px
130
142
 
131
143
  """
144
+ key = to_key(key)
132
145
  block_proto = BlockProto()
133
146
  block_proto.allow_empty = False
134
147
  block_proto.vertical.border = border or False
@@ -143,6 +156,11 @@ class LayoutsMixin:
143
156
  # containers.
144
157
  block_proto.vertical.border = True
145
158
 
159
+ if key:
160
+ block_proto.id = compute_and_register_element_id(
161
+ "container", user_key=key, height=height, border=border
162
+ )
163
+
146
164
  return self.dg._block(block_proto)
147
165
 
148
166
  @gather_metrics("columns")
@@ -14,6 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import hashlib
18
+ from datetime import date, datetime, time, timedelta
17
19
  from enum import Enum, EnumMeta
18
20
  from typing import (
19
21
  TYPE_CHECKING,
@@ -27,15 +29,27 @@ from typing import (
27
29
  overload,
28
30
  )
29
31
 
32
+ from google.protobuf.message import Message
30
33
  from typing_extensions import TypeAlias
31
34
 
32
35
  from streamlit import config, dataframe_util, errors, logger
36
+ from streamlit.errors import StreamlitDuplicateElementId, StreamlitDuplicateElementKey
33
37
  from streamlit.proto.LabelVisibilityMessage_pb2 import LabelVisibilityMessage
34
- from streamlit.runtime.state.common import RegisterWidgetResult
38
+ from streamlit.runtime.scriptrunner_utils.script_run_context import (
39
+ get_script_run_ctx,
40
+ )
41
+ from streamlit.runtime.state.common import (
42
+ GENERATED_ELEMENT_ID_PREFIX,
43
+ RegisterWidgetResult,
44
+ user_key_from_element_id,
45
+ )
46
+ from streamlit.util import HASHLIB_KWARGS
35
47
 
36
48
  if TYPE_CHECKING:
37
- from streamlit.type_util import T
49
+ from builtins import ellipsis
38
50
 
51
+ from streamlit.runtime.state.widgets import NoValue
52
+ from streamlit.type_util import T
39
53
 
40
54
  _LOGGER: Final = logger.get_logger(__name__)
41
55
 
@@ -43,6 +57,19 @@ Key: TypeAlias = Union[str, int]
43
57
 
44
58
  LabelVisibility: TypeAlias = Literal["visible", "hidden", "collapsed"]
45
59
 
60
+ PROTO_SCALAR_VALUE = Union[float, int, bool, str, bytes]
61
+ SAFE_VALUES = Union[
62
+ date,
63
+ time,
64
+ datetime,
65
+ timedelta,
66
+ None,
67
+ "NoValue",
68
+ "ellipsis",
69
+ Message,
70
+ PROTO_SCALAR_VALUE,
71
+ ]
72
+
46
73
 
47
74
  def get_label_visibility_proto_value(
48
75
  label_visibility_string: LabelVisibility,
@@ -226,3 +253,94 @@ def _extract_common_class_from_iter(iterable: Iterable[Any]) -> Any:
226
253
  if all(type(item) is first_class for item in inner_iter):
227
254
  return first_class
228
255
  return None
256
+
257
+
258
+ def _register_element_id(element_type: str, element_id: str) -> None:
259
+ """Register the element ID and key for the given element.
260
+
261
+ If the element ID or key is not unique, an error is raised.
262
+
263
+ Parameters
264
+ ----------
265
+
266
+ element_type : str
267
+ The type of the element to register.
268
+
269
+ element_id : str
270
+ The ID of the element to register.
271
+
272
+ Raises
273
+ ------
274
+
275
+ StreamlitDuplicateElementKey
276
+ If the element key is not unique.
277
+
278
+ StreamlitDuplicateElementID
279
+ If the element ID is not unique.
280
+
281
+ """
282
+ ctx = get_script_run_ctx()
283
+ if ctx is None or not element_id:
284
+ return
285
+
286
+ if user_key := user_key_from_element_id(element_id):
287
+ if user_key not in ctx.widget_user_keys_this_run:
288
+ ctx.widget_user_keys_this_run.add(user_key)
289
+ else:
290
+ raise StreamlitDuplicateElementKey(user_key)
291
+
292
+ if element_id not in ctx.widget_ids_this_run:
293
+ ctx.widget_ids_this_run.add(element_id)
294
+ else:
295
+ raise StreamlitDuplicateElementId(element_type)
296
+
297
+
298
+ def _compute_element_id(
299
+ element_type: str,
300
+ user_key: str | None = None,
301
+ **kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
302
+ ) -> str:
303
+ """Compute the ID for the given element.
304
+
305
+ This ID is stable: a given set of inputs to this function will always produce
306
+ the same ID output. Only stable, deterministic values should be used to compute
307
+ element IDs. Using nondeterministic values as inputs can cause the resulting
308
+ element ID to change between runs.
309
+
310
+ The element ID includes the user_key so elements with identical arguments can
311
+ use it to be distinct. The element ID includes an easily identified prefix, and the
312
+ user_key as a suffix, to make it easy to identify it and know if a key maps to it.
313
+ """
314
+ h = hashlib.new("md5", **HASHLIB_KWARGS)
315
+ h.update(element_type.encode("utf-8"))
316
+ # This will iterate in a consistent order when the provided arguments have
317
+ # consistent order; dicts are always in insertion order.
318
+ for k, v in kwargs.items():
319
+ h.update(str(k).encode("utf-8"))
320
+ h.update(str(v).encode("utf-8"))
321
+ return f"{GENERATED_ELEMENT_ID_PREFIX}-{h.hexdigest()}-{user_key}"
322
+
323
+
324
+ def compute_and_register_element_id(
325
+ element_type: str,
326
+ user_key: str | None = None,
327
+ **kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
328
+ ) -> str:
329
+ """Compute and register the ID for the given element.
330
+
331
+ This ID is stable: a given set of inputs to this function will always produce
332
+ the same ID output. Only stable, deterministic values should be used to compute
333
+ element IDs. Using nondeterministic values as inputs can cause the resulting
334
+ element ID to change between runs.
335
+
336
+ The element ID includes the user_key so elements with identical arguments can
337
+ use it to be distinct. The element ID includes an easily identified prefix, and the
338
+ user_key as a suffix, to make it easy to identify it and know if a key maps to it.
339
+
340
+ The element ID gets registered to make sure that only one ID and user-specified
341
+ key exists at the same time. If there are duplicated IDs or keys, an error
342
+ is raised.
343
+ """
344
+ element_id = _compute_element_id(element_type, user_key, **kwargs)
345
+ _register_element_id(element_type, element_id)
346
+ return element_id
@@ -24,13 +24,13 @@ from typing_extensions import TypeAlias
24
24
 
25
25
  from streamlit import runtime, type_util, url_util
26
26
  from streamlit.elements.lib.subtitle_utils import process_subtitle_data
27
+ from streamlit.elements.lib.utils import compute_and_register_element_id
27
28
  from streamlit.errors import StreamlitAPIException
28
29
  from streamlit.proto.Audio_pb2 import Audio as AudioProto
29
30
  from streamlit.proto.Video_pb2 import Video as VideoProto
30
31
  from streamlit.runtime import caching
31
32
  from streamlit.runtime.metrics_util import gather_metrics
32
33
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
33
- from streamlit.runtime.state.common import compute_element_id
34
34
  from streamlit.time_util import time_to_seconds
35
35
  from streamlit.type_util import NumpyShape
36
36
 
@@ -567,7 +567,7 @@ def marshall_video(
567
567
  if autoplay:
568
568
  ctx = get_script_run_ctx()
569
569
  proto.autoplay = autoplay
570
- proto.id = compute_element_id(
570
+ proto.id = compute_and_register_element_id(
571
571
  "video",
572
572
  url=proto.url,
573
573
  mimetype=mimetype,
@@ -741,7 +741,7 @@ def marshall_audio(
741
741
  if autoplay:
742
742
  ctx = get_script_run_ctx()
743
743
  proto.autoplay = autoplay
744
- proto.id = compute_element_id(
744
+ proto.id = compute_and_register_element_id(
745
745
  "audio",
746
746
  url=proto.url,
747
747
  mimetype=mimetype,
@@ -42,13 +42,12 @@ from streamlit.elements.lib.policies import check_widget_policies
42
42
  from streamlit.elements.lib.streamlit_plotly_theme import (
43
43
  configure_streamlit_plotly_theme,
44
44
  )
45
- from streamlit.elements.lib.utils import Key, to_key
45
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
46
46
  from streamlit.errors import StreamlitAPIException
47
47
  from streamlit.proto.PlotlyChart_pb2 import PlotlyChart as PlotlyChartProto
48
48
  from streamlit.runtime.metrics_util import gather_metrics
49
49
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
50
50
  from streamlit.runtime.state import WidgetCallback, register_widget
51
- from streamlit.runtime.state.common import compute_element_id
52
51
 
53
52
  if TYPE_CHECKING:
54
53
  import matplotlib
@@ -212,7 +211,9 @@ class PlotlyState(TypedDict, total=False):
212
211
 
213
212
  @dataclass
214
213
  class PlotlyChartSelectionSerde:
215
- """PlotlyChartSelectionSerde is used to serialize and deserialize the Plotly Chart selection state."""
214
+ """PlotlyChartSelectionSerde is used to serialize and deserialize the Plotly Chart
215
+ selection state.
216
+ """
216
217
 
217
218
  def deserialize(self, ui_value: str | None, widget_id: str = "") -> PlotlyState:
218
219
  empty_selection_state: PlotlyState = {
@@ -442,18 +443,22 @@ class PlotlyMixin:
442
443
 
443
444
  if "sharing" in kwargs:
444
445
  show_deprecation_warning(
445
- "The `sharing` parameter has been deprecated and will be removed in a future release. "
446
- "Plotly charts will always be rendered using Streamlit's offline mode."
446
+ "The `sharing` parameter has been deprecated and will be removed "
447
+ "in a future release. Plotly charts will always be rendered using "
448
+ "Streamlit's offline mode."
447
449
  )
448
450
 
449
451
  if theme not in ["streamlit", None]:
450
452
  raise StreamlitAPIException(
451
- f'You set theme="{theme}" while Streamlit charts only support theme=”streamlit” or theme=None to fallback to the default library theme.'
453
+ f'You set theme="{theme}" while Streamlit charts only support '
454
+ "theme=”streamlit” or theme=None to fallback to the default "
455
+ "library theme."
452
456
  )
453
457
 
454
458
  if on_select not in ["ignore", "rerun"] and not callable(on_select):
455
459
  raise StreamlitAPIException(
456
- f"You have passed {on_select} to `on_select`. But only 'ignore', 'rerun', or a callable is supported."
460
+ f"You have passed {on_select} to `on_select`. But only 'ignore', "
461
+ "'rerun', or a callable is supported."
457
462
  )
458
463
 
459
464
  key = to_key(key)
@@ -498,7 +503,7 @@ class PlotlyMixin:
498
503
  # We are computing the widget id for all plotly uses
499
504
  # to also allow non-widget Plotly charts to keep their state
500
505
  # when the frontend component gets unmounted and remounted.
501
- plotly_chart_proto.id = compute_element_id(
506
+ plotly_chart_proto.id = compute_and_register_element_id(
502
507
  "plotly_chart",
503
508
  user_key=key,
504
509
  key=key,
@@ -523,7 +528,6 @@ class PlotlyMixin:
523
528
  widget_state = register_widget(
524
529
  "plotly_chart",
525
530
  plotly_chart_proto,
526
- user_key=key,
527
531
  on_change_handler=on_select if callable(on_select) else None,
528
532
  deserializer=serde.deserialize,
529
533
  serializer=serde.serialize,
@@ -47,7 +47,7 @@ from streamlit.elements.lib.built_in_chart_utils import (
47
47
  )
48
48
  from streamlit.elements.lib.event_utils import AttributeDictionary
49
49
  from streamlit.elements.lib.policies import check_widget_policies
50
- from streamlit.elements.lib.utils import Key, to_key
50
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
51
51
  from streamlit.errors import StreamlitAPIException
52
52
  from streamlit.proto.ArrowVegaLiteChart_pb2 import (
53
53
  ArrowVegaLiteChart as ArrowVegaLiteChartProto,
@@ -55,7 +55,6 @@ from streamlit.proto.ArrowVegaLiteChart_pb2 import (
55
55
  from streamlit.runtime.metrics_util import gather_metrics
56
56
  from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
57
57
  from streamlit.runtime.state import WidgetCallback, register_widget
58
- from streamlit.runtime.state.common import compute_element_id
59
58
  from streamlit.util import HASHLIB_KWARGS
60
59
 
61
60
  if TYPE_CHECKING:
@@ -1887,7 +1886,7 @@ class VegaChartsMixin:
1887
1886
  vega_lite_proto.form_id = current_form_id(self.dg)
1888
1887
 
1889
1888
  ctx = get_script_run_ctx()
1890
- vega_lite_proto.id = compute_element_id(
1889
+ vega_lite_proto.id = compute_and_register_element_id(
1891
1890
  "arrow_vega_lite_chart",
1892
1891
  user_key=key,
1893
1892
  key=key,
@@ -1910,7 +1909,6 @@ class VegaChartsMixin:
1910
1909
  widget_state = register_widget(
1911
1910
  "vega_lite_chart",
1912
1911
  vega_lite_proto,
1913
- user_key=key,
1914
1912
  on_change_handler=on_select if callable(on_select) else None,
1915
1913
  deserializer=serde.deserialize,
1916
1914
  serializer=serde.serialize,
@@ -33,7 +33,7 @@ from typing_extensions import TypeAlias
33
33
  from streamlit import runtime
34
34
  from streamlit.elements.form_utils import current_form_id, is_in_form
35
35
  from streamlit.elements.lib.policies import check_widget_policies
36
- from streamlit.elements.lib.utils import Key, to_key
36
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
37
37
  from streamlit.errors import StreamlitAPIException
38
38
  from streamlit.file_util import get_main_script_directory, normalize_path_join
39
39
  from streamlit.navigation.page import StreamlitPage
@@ -49,7 +49,9 @@ from streamlit.runtime.state import (
49
49
  WidgetKwargs,
50
50
  register_widget,
51
51
  )
52
- from streamlit.runtime.state.common import compute_element_id, save_for_app_testing
52
+ from streamlit.runtime.state.common import (
53
+ save_for_app_testing,
54
+ )
53
55
  from streamlit.string_util import validate_icon_or_emoji
54
56
  from streamlit.url_util import is_url
55
57
 
@@ -662,7 +664,7 @@ class ButtonMixin:
662
664
  writes_allowed=False,
663
665
  )
664
666
 
665
- element_id = compute_element_id(
667
+ element_id = compute_and_register_element_id(
666
668
  "download_button",
667
669
  user_key=key,
668
670
  label=label,
@@ -703,7 +705,6 @@ class ButtonMixin:
703
705
  button_state = register_widget(
704
706
  "download_button",
705
707
  download_button_proto,
706
- user_key=key,
707
708
  on_change_handler=on_click,
708
709
  args=args,
709
710
  kwargs=kwargs,
@@ -843,7 +844,7 @@ class ButtonMixin:
843
844
  enable_check_callback_rules=not is_form_submitter,
844
845
  )
845
846
 
846
- element_id = compute_element_id(
847
+ element_id = compute_and_register_element_id(
847
848
  "button",
848
849
  user_key=key,
849
850
  label=label,
@@ -892,7 +893,6 @@ class ButtonMixin:
892
893
  button_state = register_widget(
893
894
  "button",
894
895
  button_proto,
895
- user_key=key,
896
896
  on_change_handler=on_click,
897
897
  args=args,
898
898
  kwargs=kwargs,
@@ -34,6 +34,7 @@ from streamlit.elements.lib.options_selector_utils import (
34
34
  from streamlit.elements.lib.policies import check_widget_policies
35
35
  from streamlit.elements.lib.utils import (
36
36
  Key,
37
+ compute_and_register_element_id,
37
38
  maybe_coerce_enum_sequence,
38
39
  to_key,
39
40
  )
@@ -47,7 +48,6 @@ from streamlit.runtime.state.common import (
47
48
  RegisterWidgetResult,
48
49
  WidgetDeserializer,
49
50
  WidgetSerializer,
50
- compute_element_id,
51
51
  save_for_app_testing,
52
52
  )
53
53
 
@@ -396,7 +396,7 @@ class ButtonGroupMixin:
396
396
  if format_func is None
397
397
  else [format_func(option) for option in indexable_options]
398
398
  )
399
- element_id = compute_element_id(
399
+ element_id = compute_and_register_element_id(
400
400
  widget_name,
401
401
  user_key=key,
402
402
  key=key,
@@ -420,7 +420,6 @@ class ButtonGroupMixin:
420
420
  widget_state = register_widget(
421
421
  widget_name,
422
422
  proto,
423
- # user_key=key,
424
423
  on_change_handler=on_change,
425
424
  args=args,
426
425
  kwargs=kwargs,
@@ -28,6 +28,7 @@ from streamlit.elements.lib.policies import (
28
28
  from streamlit.elements.lib.utils import (
29
29
  Key,
30
30
  LabelVisibility,
31
+ compute_and_register_element_id,
31
32
  get_label_visibility_proto_value,
32
33
  to_key,
33
34
  )
@@ -43,7 +44,6 @@ from streamlit.runtime.state import (
43
44
  WidgetKwargs,
44
45
  register_widget,
45
46
  )
46
- from streamlit.runtime.state.common import compute_element_id
47
47
  from streamlit.runtime.uploaded_file_manager import DeletedFile, UploadedFile
48
48
 
49
49
  if TYPE_CHECKING:
@@ -203,7 +203,7 @@ class CameraInputMixin:
203
203
  )
204
204
  maybe_raise_label_warnings(label, label_visibility)
205
205
 
206
- element_id = compute_element_id(
206
+ element_id = compute_and_register_element_id(
207
207
  "camera_input",
208
208
  user_key=key,
209
209
  label=label,
@@ -230,7 +230,6 @@ class CameraInputMixin:
230
230
  camera_input_state = register_widget(
231
231
  "camera_input",
232
232
  camera_input_proto,
233
- user_key=key,
234
233
  on_change_handler=on_change,
235
234
  args=args,
236
235
  kwargs=kwargs,
@@ -23,7 +23,7 @@ from streamlit.delta_generator_singletons import get_dg_singleton_instance
23
23
  from streamlit.elements.form_utils import is_in_form
24
24
  from streamlit.elements.image import AtomicImage, WidthBehaviour, image_to_url
25
25
  from streamlit.elements.lib.policies import check_widget_policies
26
- from streamlit.elements.lib.utils import Key, to_key
26
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
27
27
  from streamlit.errors import StreamlitAPIException
28
28
  from streamlit.proto.Block_pb2 import Block as BlockProto
29
29
  from streamlit.proto.ChatInput_pb2 import ChatInput as ChatInputProto
@@ -37,7 +37,9 @@ from streamlit.runtime.state import (
37
37
  WidgetKwargs,
38
38
  register_widget,
39
39
  )
40
- from streamlit.runtime.state.common import compute_element_id, save_for_app_testing
40
+ from streamlit.runtime.state.common import (
41
+ save_for_app_testing,
42
+ )
41
43
  from streamlit.string_util import is_emoji, validate_material_icon
42
44
 
43
45
  if TYPE_CHECKING:
@@ -323,7 +325,7 @@ class ChatMixin:
323
325
  )
324
326
 
325
327
  ctx = get_script_run_ctx()
326
- element_id = compute_element_id(
328
+ element_id = compute_and_register_element_id(
327
329
  "chat_input",
328
330
  user_key=key,
329
331
  key=key,
@@ -368,7 +370,6 @@ class ChatMixin:
368
370
  widget_state = register_widget(
369
371
  "chat_input",
370
372
  chat_input_proto,
371
- user_key=key,
372
373
  on_change_handler=on_submit,
373
374
  args=args,
374
375
  kwargs=kwargs,
@@ -26,6 +26,7 @@ from streamlit.elements.lib.policies import (
26
26
  from streamlit.elements.lib.utils import (
27
27
  Key,
28
28
  LabelVisibility,
29
+ compute_and_register_element_id,
29
30
  get_label_visibility_proto_value,
30
31
  to_key,
31
32
  )
@@ -38,7 +39,6 @@ from streamlit.runtime.state import (
38
39
  WidgetKwargs,
39
40
  register_widget,
40
41
  )
41
- from streamlit.runtime.state.common import compute_element_id
42
42
 
43
43
  if TYPE_CHECKING:
44
44
  from streamlit.delta_generator import DeltaGenerator
@@ -291,7 +291,7 @@ class CheckboxMixin:
291
291
  )
292
292
  maybe_raise_label_warnings(label, label_visibility)
293
293
 
294
- element_id = compute_element_id(
294
+ element_id = compute_and_register_element_id(
295
295
  "toggle" if type == CheckboxProto.StyleType.TOGGLE else "checkbox",
296
296
  user_key=key,
297
297
  label=label,
@@ -321,7 +321,6 @@ class CheckboxMixin:
321
321
  checkbox_state = register_widget(
322
322
  "checkbox",
323
323
  checkbox_proto,
324
- user_key=key,
325
324
  on_change_handler=on_change,
326
325
  args=args,
327
326
  kwargs=kwargs,
@@ -27,6 +27,7 @@ from streamlit.elements.lib.policies import (
27
27
  from streamlit.elements.lib.utils import (
28
28
  Key,
29
29
  LabelVisibility,
30
+ compute_and_register_element_id,
30
31
  get_label_visibility_proto_value,
31
32
  to_key,
32
33
  )
@@ -40,7 +41,6 @@ from streamlit.runtime.state import (
40
41
  WidgetKwargs,
41
42
  register_widget,
42
43
  )
43
- from streamlit.runtime.state.common import compute_element_id
44
44
 
45
45
  if TYPE_CHECKING:
46
46
  from streamlit.delta_generator import DeltaGenerator
@@ -186,7 +186,7 @@ class ColorPickerMixin:
186
186
  )
187
187
  maybe_raise_label_warnings(label, label_visibility)
188
188
 
189
- element_id = compute_element_id(
189
+ element_id = compute_and_register_element_id(
190
190
  "color_picker",
191
191
  user_key=key,
192
192
  label=label,
@@ -241,7 +241,6 @@ class ColorPickerMixin:
241
241
  widget_state = register_widget(
242
242
  "color_picker",
243
243
  color_picker_proto,
244
- user_key=key,
245
244
  on_change_handler=on_change,
246
245
  args=args,
247
246
  kwargs=kwargs,