streamlit-nightly 1.38.1.dev20240923__py2.py3-none-any.whl → 1.38.1.dev20240925__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 (48) hide show
  1. streamlit/__init__.py +1 -1
  2. streamlit/config_option.py +2 -0
  3. streamlit/delta_generator.py +2 -0
  4. streamlit/elements/deck_gl_json_chart.py +260 -36
  5. streamlit/elements/widgets/audio_input.py +248 -0
  6. streamlit/elements/widgets/button_group.py +1 -1
  7. streamlit/proto/AudioInput_pb2.py +28 -0
  8. streamlit/proto/AudioInput_pb2.pyi +58 -0
  9. streamlit/proto/DeckGlJsonChart_pb2.py +4 -2
  10. streamlit/proto/DeckGlJsonChart_pb2.pyi +40 -2
  11. streamlit/proto/Element_pb2.py +4 -3
  12. streamlit/proto/Element_pb2.pyi +9 -4
  13. streamlit/runtime/state/common.py +4 -0
  14. streamlit/runtime/state/widgets.py +3 -1
  15. streamlit/static/asset-manifest.json +15 -13
  16. streamlit/static/index.html +1 -1
  17. streamlit/static/static/js/195.8e0d331c.chunk.js +2 -0
  18. streamlit/static/static/js/238.8d3a7d25.chunk.js +1 -0
  19. streamlit/static/static/js/245.f99079b1.chunk.js +1 -0
  20. streamlit/static/static/js/266.e595f506.chunk.js +1 -0
  21. streamlit/static/static/js/3710.d73e609f.chunk.js +1 -0
  22. streamlit/static/static/js/5281.02b3ddc4.chunk.js +1 -0
  23. streamlit/static/static/js/{5625.fe6c22ad.chunk.js → 5625.d9509933.chunk.js} +1 -1
  24. streamlit/static/static/js/{6088.c137d543.chunk.js → 6088.1164e19b.chunk.js} +1 -1
  25. streamlit/static/static/js/708.a5252e2f.chunk.js +1 -0
  26. streamlit/static/static/js/8642.58110d15.chunk.js +2 -0
  27. streamlit/static/static/js/{8815.0284d089.chunk.js → 8815.9d336691.chunk.js} +1 -1
  28. streamlit/static/static/js/9943.6af344bb.chunk.js +1 -0
  29. streamlit/static/static/js/main.e9d8ce9e.js +28 -0
  30. streamlit/web/cli.py +2 -0
  31. {streamlit_nightly-1.38.1.dev20240923.dist-info → streamlit_nightly-1.38.1.dev20240925.dist-info}/METADATA +1 -1
  32. {streamlit_nightly-1.38.1.dev20240923.dist-info → streamlit_nightly-1.38.1.dev20240925.dist-info}/RECORD +40 -35
  33. streamlit/static/static/js/2055.bca43613.chunk.js +0 -1
  34. streamlit/static/static/js/245.68a062da.chunk.js +0 -1
  35. streamlit/static/static/js/5180.e826dd46.chunk.js +0 -1
  36. streamlit/static/static/js/6789.f8dde736.chunk.js +0 -2
  37. streamlit/static/static/js/8485.81bdf474.chunk.js +0 -1
  38. streamlit/static/static/js/8642.dfef7dcb.chunk.js +0 -2
  39. streamlit/static/static/js/9943.d18fdff1.chunk.js +0 -1
  40. streamlit/static/static/js/main.829dd23b.js +0 -28
  41. /streamlit/static/static/css/{6789.81b3d18f.chunk.css → 195.81b3d18f.chunk.css} +0 -0
  42. /streamlit/static/static/js/{6789.f8dde736.chunk.js.LICENSE.txt → 195.8e0d331c.chunk.js.LICENSE.txt} +0 -0
  43. /streamlit/static/static/js/{8642.dfef7dcb.chunk.js.LICENSE.txt → 8642.58110d15.chunk.js.LICENSE.txt} +0 -0
  44. /streamlit/static/static/js/{main.829dd23b.js.LICENSE.txt → main.e9d8ce9e.js.LICENSE.txt} +0 -0
  45. {streamlit_nightly-1.38.1.dev20240923.data → streamlit_nightly-1.38.1.dev20240925.data}/scripts/streamlit.cmd +0 -0
  46. {streamlit_nightly-1.38.1.dev20240923.dist-info → streamlit_nightly-1.38.1.dev20240925.dist-info}/WHEEL +0 -0
  47. {streamlit_nightly-1.38.1.dev20240923.dist-info → streamlit_nightly-1.38.1.dev20240925.dist-info}/entry_points.txt +0 -0
  48. {streamlit_nightly-1.38.1.dev20240923.dist-info → streamlit_nightly-1.38.1.dev20240925.dist-info}/top_level.txt +0 -0
streamlit/__init__.py CHANGED
@@ -204,7 +204,6 @@ metric = _main.metric
204
204
  multiselect = _main.multiselect
205
205
  number_input = _main.number_input
206
206
  page_link = _main.page_link
207
- pills = _main.pills
208
207
  plotly_chart = _main.plotly_chart
209
208
  popover = _main.popover
210
209
  progress = _main.progress
@@ -266,6 +265,7 @@ dialog = _dialog_decorator
266
265
  fragment = _fragment
267
266
 
268
267
  # Experimental APIs
268
+ experimental_audio_input = _main.experimental_audio_input
269
269
  experimental_dialog = _experimental_dialog_decorator
270
270
  experimental_fragment = _experimental_fragment
271
271
  experimental_user = _UserInfoProxy()
@@ -179,6 +179,8 @@ class ConfigOption:
179
179
  self.where_defined = ConfigOption.DEFAULT_DEFINITION
180
180
  self.type = type_
181
181
  self.sensitive = sensitive
182
+ # infer multiple values if the default value is a list or tuple
183
+ self.multiple = isinstance(default_val, (list, tuple))
182
184
 
183
185
  if self.replaced_by:
184
186
  self.deprecated = True
@@ -74,6 +74,7 @@ from streamlit.elements.snow import SnowMixin
74
74
  from streamlit.elements.text import TextMixin
75
75
  from streamlit.elements.toast import ToastMixin
76
76
  from streamlit.elements.vega_charts import VegaChartsMixin
77
+ from streamlit.elements.widgets.audio_input import AudioInputMixin
77
78
  from streamlit.elements.widgets.button import ButtonMixin
78
79
  from streamlit.elements.widgets.button_group import ButtonGroupMixin
79
80
  from streamlit.elements.widgets.camera_input import CameraInputMixin
@@ -144,6 +145,7 @@ def _maybe_print_use_warning() -> None:
144
145
 
145
146
  class DeltaGenerator(
146
147
  AlertMixin,
148
+ AudioInputMixin,
147
149
  BalloonsMixin,
148
150
  BokehMixin,
149
151
  ButtonMixin,
@@ -15,11 +15,35 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import json
18
- from typing import TYPE_CHECKING, Any, Dict, Final, Mapping, cast
18
+ from dataclasses import dataclass
19
+ from typing import (
20
+ TYPE_CHECKING,
21
+ Any,
22
+ Dict,
23
+ Final,
24
+ Iterable,
25
+ Literal,
26
+ Mapping,
27
+ TypedDict,
28
+ cast,
29
+ overload,
30
+ )
31
+
32
+ from typing_extensions import TypeAlias
19
33
 
20
34
  from streamlit import config
35
+ from streamlit.elements.lib.event_utils import AttributeDictionary
36
+ from streamlit.elements.lib.form_utils import current_form_id
37
+ from streamlit.elements.lib.policies import check_widget_policies
38
+ from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
39
+ from streamlit.errors import StreamlitAPIException
21
40
  from streamlit.proto.DeckGlJsonChart_pb2 import DeckGlJsonChart as PydeckProto
22
41
  from streamlit.runtime.metrics_util import gather_metrics
42
+ from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
43
+ from streamlit.runtime.state import (
44
+ WidgetCallback,
45
+ register_widget,
46
+ )
23
47
 
24
48
  if TYPE_CHECKING:
25
49
  from pydeck import Deck
@@ -32,16 +56,146 @@ EMPTY_MAP: Final[Mapping[str, Any]] = {
32
56
  "initialViewState": {"latitude": 0, "longitude": 0, "pitch": 0, "zoom": 1},
33
57
  }
34
58
 
59
+ SelectionMode: TypeAlias = Literal["single-object", "multi-object"]
60
+ _SELECTION_MODES: Final[set[SelectionMode]] = {
61
+ "single-object",
62
+ "multi-object",
63
+ }
64
+
65
+
66
+ def parse_selection_mode(
67
+ selection_mode: SelectionMode | Iterable[SelectionMode],
68
+ ) -> set[PydeckProto.SelectionMode.ValueType]:
69
+ """Parse and check the user provided selection modes."""
70
+ if isinstance(selection_mode, str):
71
+ # Only a single selection mode was passed
72
+ selection_mode_set = {selection_mode}
73
+ else:
74
+ # Multiple selection modes were passed.
75
+ # This is not yet supported as a functionality, but the infra is here to
76
+ # support it in the future!
77
+ # @see DeckGlJsonChart.tsx
78
+ raise StreamlitAPIException(
79
+ f"Invalid selection mode: {selection_mode}. ",
80
+ "Selection mode must be a single value, but got a set instead.",
81
+ )
82
+
83
+ if not selection_mode_set.issubset(_SELECTION_MODES):
84
+ raise StreamlitAPIException(
85
+ f"Invalid selection mode: {selection_mode}. "
86
+ f"Valid options are: {_SELECTION_MODES}"
87
+ )
88
+
89
+ if selection_mode_set.issuperset({"single-object", "multi-object"}):
90
+ raise StreamlitAPIException(
91
+ "Only one of `single-object` or `multi-object` can be selected as selection mode."
92
+ )
93
+
94
+ parsed_selection_modes = []
95
+ for selection_mode in selection_mode_set:
96
+ if selection_mode == "single-object":
97
+ parsed_selection_modes.append(PydeckProto.SelectionMode.SINGLE_OBJECT)
98
+ elif selection_mode == "multi-object":
99
+ parsed_selection_modes.append(PydeckProto.SelectionMode.MULTI_OBJECT)
100
+ return set(parsed_selection_modes)
101
+
102
+
103
+ class LayerSelectionState(TypedDict, total=False):
104
+ """
105
+ The schema for the PyDeck Layer Selection State
106
+
107
+ Attributes
108
+ ----------
109
+ indices : dict[str, list[int]]
110
+ Dictionary where keys are the layer id and values are lists of indices
111
+ of selected objects.
112
+ objects : dict[str, list[dict[str, Any]]]
113
+ Dictionary where keys are the layer id and values are lists of metadata
114
+ objects for the selected items.
115
+ """
116
+
117
+ indices: dict[str, list[int]]
118
+ objects: dict[str, list[dict[str, Any]]]
119
+
120
+
121
+ class PydeckState(TypedDict, total=False):
122
+ """
123
+ The schema for the PyDeck State
124
+
125
+ Attributes
126
+ ----------
127
+ selection : LayerSelectionState
128
+ The selection state of the PyDeck layers.
129
+ """
130
+
131
+ selection: LayerSelectionState
132
+
133
+
134
+ @dataclass
135
+ class PydeckSelectionSerde:
136
+ """PydeckSelectionSerde is used to serialize and deserialize the Pydeck selection state."""
137
+
138
+ def deserialize(self, ui_value: str | None, widget_id: str = "") -> PydeckState:
139
+ empty_selection_state: PydeckState = {
140
+ "selection": {
141
+ "indices": {},
142
+ "objects": {},
143
+ }
144
+ }
145
+
146
+ selection_state = (
147
+ empty_selection_state if ui_value is None else json.loads(ui_value)
148
+ )
149
+
150
+ # We have seen some situations where the ui_value was just an empty
151
+ # dict, so we want to ensure that it always returns the empty state in
152
+ # case this happens.
153
+ if "selection" not in selection_state:
154
+ selection_state = empty_selection_state
155
+
156
+ return cast(PydeckState, AttributeDictionary(selection_state))
157
+
158
+ def serialize(self, selection_state: PydeckState) -> str:
159
+ return json.dumps(selection_state, default=str)
160
+
35
161
 
36
162
  class PydeckMixin:
163
+ @overload
164
+ def pydeck_chart(
165
+ self,
166
+ pydeck_obj: Deck | None = None,
167
+ *,
168
+ use_container_width: bool = False,
169
+ selection_mode: Literal[
170
+ "single-object"
171
+ ], # Selection mode will only be activated by on_select param, this is a default value here to make it work with mypy
172
+ on_select: Literal["ignore"], # No default value here to make it work with mypy
173
+ key: Key | None = None,
174
+ ) -> DeltaGenerator: ...
175
+
176
+ @overload
177
+ def pydeck_chart(
178
+ self,
179
+ pydeck_obj: Deck | None = None,
180
+ *,
181
+ use_container_width: bool = False,
182
+ selection_mode: SelectionMode = "single-object",
183
+ on_select: Literal["rerun"] | WidgetCallback = "rerun",
184
+ key: Key | None = None,
185
+ ) -> PydeckState: ...
186
+
37
187
  @gather_metrics("pydeck_chart")
38
188
  def pydeck_chart(
39
189
  self,
40
190
  pydeck_obj: Deck | None = None,
191
+ *,
41
192
  use_container_width: bool = False,
42
193
  width: int | None = None,
43
194
  height: int | None = None,
44
- ) -> DeltaGenerator:
195
+ selection_mode: SelectionMode = "single-object",
196
+ on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
197
+ key: Key | None = None,
198
+ ) -> DeltaGenerator | PydeckState:
45
199
  """Draw a chart using the PyDeck library.
46
200
 
47
201
  This supports 3D maps, point clouds, and more! More info about PyDeck
@@ -92,6 +246,37 @@ class PydeckMixin:
92
246
  Desired height of the chart expressed in pixels. If ``height`` is
93
247
  ``None`` (default), Streamlit sets the height of the chart to fit
94
248
  its contents according to the plotting library.
249
+ on_select : "ignore" or "rerun" or callable
250
+ How the chart should respond to user selection events. This controls
251
+ whether or not the dataframe behaves like an input widget.
252
+ ``on_select`` can be one of the following:
253
+
254
+ - ``"ignore"`` (default): Streamlit will not react to any selection
255
+ events in the dataframe. The dataframe will not behave like an
256
+ input widget.
257
+ - ``"rerun"``: Rerun the script when a selection is made.
258
+ - callable: A Python callable that will be called when a selection
259
+ is made. The callable will be passed the selection state as a
260
+ dictionary.
261
+
262
+ If ``on_select`` is not ``"ignore"``, ensure that the layers given
263
+ to the ``pydeck_obj`` have stable IDs so that selection state can be
264
+ maintained across reruns.
265
+ selection_mode : "single-object" or "multi-object"
266
+ The types of selections Streamlit should allow. This can be one of
267
+ the following:
268
+
269
+ - ``"single-object"`` (default): Only one object can be selected at
270
+ a time.
271
+ - ``"multi-object"``: Multiple objects can be selected at a time.
272
+ key : str
273
+ An optional string to use for giving this element a stable
274
+ identity. If ``key`` is ``None`` (default), this element's identity
275
+ will be determined based on the values of the other parameters.
276
+
277
+ Additionally, if selections are activated and ``key`` is provided,
278
+ Streamlit will register the key in Session State to store the
279
+ selection state. The selection state is read-only.
95
280
 
96
281
  Example
97
282
  -------
@@ -149,9 +334,79 @@ class PydeckMixin:
149
334
 
150
335
  """
151
336
  pydeck_proto = PydeckProto()
152
- marshall(
153
- pydeck_proto, pydeck_obj, use_container_width, width=width, height=height
154
- )
337
+
338
+ ctx = get_script_run_ctx()
339
+
340
+ if pydeck_obj is None:
341
+ spec = json.dumps(EMPTY_MAP)
342
+ else:
343
+ spec = pydeck_obj.to_json()
344
+
345
+ pydeck_proto.json = spec
346
+ pydeck_proto.use_container_width = use_container_width
347
+
348
+ if width:
349
+ pydeck_proto.width = width
350
+ if height:
351
+ pydeck_proto.height = height
352
+
353
+ tooltip = _get_pydeck_tooltip(pydeck_obj)
354
+ if tooltip:
355
+ pydeck_proto.tooltip = json.dumps(tooltip)
356
+
357
+ mapbox_token = config.get_option("mapbox.token")
358
+ if mapbox_token:
359
+ pydeck_proto.mapbox_token = mapbox_token
360
+
361
+ key = to_key(key)
362
+ is_selection_activated = on_select != "ignore"
363
+
364
+ if on_select not in ["ignore", "rerun"] and not callable(on_select):
365
+ raise StreamlitAPIException(
366
+ f"You have passed {on_select} to `on_select`. But only 'ignore', 'rerun', or a callable is supported."
367
+ )
368
+
369
+ if is_selection_activated:
370
+ # Selections are activated, treat Pydeck as a widget:
371
+ pydeck_proto.selection_mode.extend(parse_selection_mode(selection_mode))
372
+
373
+ # Run some checks that are only relevant when selections are activated
374
+ is_callback = callable(on_select)
375
+ check_widget_policies(
376
+ self.dg,
377
+ key,
378
+ on_change=cast(WidgetCallback, on_select) if is_callback else None,
379
+ default_value=None,
380
+ writes_allowed=False,
381
+ enable_check_callback_rules=is_callback,
382
+ )
383
+ pydeck_proto.form_id = current_form_id(self.dg)
384
+
385
+ pydeck_proto.id = compute_and_register_element_id(
386
+ "deck_gl_json_chart",
387
+ user_key=key,
388
+ is_selection_activated=is_selection_activated,
389
+ selection_mode=selection_mode,
390
+ use_container_width=use_container_width,
391
+ spec=spec,
392
+ form_id=pydeck_proto.form_id,
393
+ )
394
+
395
+ serde = PydeckSelectionSerde()
396
+
397
+ widget_state = register_widget(
398
+ "deck_gl_json_chart",
399
+ pydeck_proto,
400
+ ctx=ctx,
401
+ deserializer=serde.deserialize,
402
+ on_change_handler=on_select if callable(on_select) else None,
403
+ serializer=serde.serialize,
404
+ )
405
+
406
+ self.dg._enqueue("deck_gl_json_chart", pydeck_proto)
407
+
408
+ return cast(PydeckState, widget_state.value)
409
+
155
410
  return self.dg._enqueue("deck_gl_json_chart", pydeck_proto)
156
411
 
157
412
  @property
@@ -176,34 +431,3 @@ def _get_pydeck_tooltip(pydeck_obj: Deck | None) -> dict[str, str] | None:
176
431
  return cast(Dict[str, str], tooltip)
177
432
 
178
433
  return None
179
-
180
-
181
- def marshall(
182
- pydeck_proto: PydeckProto,
183
- pydeck_obj: Deck | None,
184
- use_container_width: bool,
185
- width: int | None = None,
186
- height: int | None = None,
187
- ) -> None:
188
- if pydeck_obj is None:
189
- spec = json.dumps(EMPTY_MAP)
190
- else:
191
- spec = pydeck_obj.to_json()
192
-
193
- pydeck_proto.json = spec
194
- pydeck_proto.use_container_width = use_container_width
195
-
196
- if width:
197
- pydeck_proto.width = width
198
- if height:
199
- pydeck_proto.height = height
200
-
201
- pydeck_proto.id = ""
202
-
203
- tooltip = _get_pydeck_tooltip(pydeck_obj)
204
- if tooltip:
205
- pydeck_proto.tooltip = json.dumps(tooltip)
206
-
207
- mapbox_token = config.get_option("mapbox.token")
208
- if mapbox_token:
209
- pydeck_proto.mapbox_token = mapbox_token
@@ -0,0 +1,248 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ from dataclasses import dataclass
18
+ from textwrap import dedent
19
+ from typing import TYPE_CHECKING, Union, cast
20
+
21
+ from typing_extensions import TypeAlias
22
+
23
+ from streamlit.elements.lib.form_utils import current_form_id
24
+ from streamlit.elements.lib.policies import (
25
+ check_widget_policies,
26
+ maybe_raise_label_warnings,
27
+ )
28
+ from streamlit.elements.lib.utils import (
29
+ Key,
30
+ LabelVisibility,
31
+ compute_and_register_element_id,
32
+ get_label_visibility_proto_value,
33
+ to_key,
34
+ )
35
+ from streamlit.elements.widgets.file_uploader import _get_upload_files
36
+ from streamlit.proto.AudioInput_pb2 import AudioInput as AudioInputProto
37
+ from streamlit.proto.Common_pb2 import FileUploaderState as FileUploaderStateProto
38
+ from streamlit.proto.Common_pb2 import UploadedFileInfo as UploadedFileInfoProto
39
+ from streamlit.runtime.metrics_util import gather_metrics
40
+ from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
41
+ from streamlit.runtime.state import (
42
+ WidgetArgs,
43
+ WidgetCallback,
44
+ WidgetKwargs,
45
+ register_widget,
46
+ )
47
+ from streamlit.runtime.uploaded_file_manager import DeletedFile, UploadedFile
48
+
49
+ if TYPE_CHECKING:
50
+ from streamlit.delta_generator import DeltaGenerator
51
+
52
+ SomeUploadedAudioFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
53
+
54
+
55
+ @dataclass
56
+ class AudioInputSerde:
57
+ def serialize(
58
+ self,
59
+ audio_file: SomeUploadedAudioFile,
60
+ ) -> FileUploaderStateProto:
61
+ state_proto = FileUploaderStateProto()
62
+
63
+ if audio_file is None or isinstance(audio_file, DeletedFile):
64
+ return state_proto
65
+
66
+ file_info: UploadedFileInfoProto = state_proto.uploaded_file_info.add()
67
+ file_info.file_id = audio_file.file_id
68
+ file_info.name = audio_file.name
69
+ file_info.size = audio_file.size
70
+ file_info.file_urls.CopyFrom(audio_file._file_urls)
71
+
72
+ return state_proto
73
+
74
+ def deserialize(
75
+ self, ui_value: FileUploaderStateProto | None, widget_id: str
76
+ ) -> SomeUploadedAudioFile:
77
+ upload_files = _get_upload_files(ui_value)
78
+ if len(upload_files) == 0:
79
+ return_value = None
80
+ else:
81
+ return_value = upload_files[0]
82
+ return return_value
83
+
84
+
85
+ class AudioInputMixin:
86
+ @gather_metrics("experimental_audio_input")
87
+ def experimental_audio_input(
88
+ self,
89
+ label: str,
90
+ *,
91
+ key: Key | None = None,
92
+ help: str | None = None,
93
+ on_change: WidgetCallback | None = None,
94
+ args: WidgetArgs | None = None,
95
+ kwargs: WidgetKwargs | None = None,
96
+ disabled: bool = False,
97
+ label_visibility: LabelVisibility = "visible",
98
+ ) -> UploadedFile | None:
99
+ r"""Display a widget that returns audio recording from the user's microphone.
100
+
101
+ Parameters
102
+ ----------
103
+ label : str
104
+ A short label explaining to the user what this widget is used for.
105
+ The label can optionally contain GitHub-flavored Markdown of the
106
+ following types: Bold, Italics, Strikethroughs, Inline Code, and
107
+ Links.
108
+
109
+ Unsupported Markdown elements are unwrapped so only their children
110
+ (text contents) render. Display unsupported elements as literal
111
+ characters by backslash-escaping them. E.g.,
112
+ ``"1\. Not an ordered list"``.
113
+
114
+ See the ``body`` parameter of |st.markdown|_ for additional,
115
+ supported Markdown directives.
116
+
117
+ For accessibility reasons, you should never set an empty label (label="")
118
+ but hide it with label_visibility if needed. In the future, we may disallow
119
+ empty labels by raising an exception.
120
+
121
+ .. |st.markdown| replace:: ``st.markdown``
122
+ .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
123
+
124
+ key : str or int
125
+ An optional string or integer to use as the unique key for the widget.
126
+ If this is omitted, a key will be generated for the widget
127
+ based on its content. Multiple widgets of the same type may
128
+ not share the same key.
129
+
130
+ help : str
131
+ A tooltip that gets displayed next to the audio input.
132
+
133
+ on_change : callable
134
+ An optional callback invoked when this audio_input's value
135
+ changes.
136
+
137
+ args : tuple
138
+ An optional tuple of args to pass to the callback.
139
+
140
+ kwargs : dict
141
+ An optional dict of kwargs to pass to the callback.
142
+
143
+ disabled : bool
144
+ An optional boolean, which disables the audio input if set to
145
+ True. Default is False.
146
+ label_visibility : "visible", "hidden", or "collapsed"
147
+ The visibility of the label. If "hidden", the label doesn't show but there
148
+ is still empty space for it above the widget (equivalent to label="").
149
+ If "collapsed", both the label and the space are removed. Default is
150
+ "visible".
151
+
152
+ Returns
153
+ -------
154
+ None or UploadedFile
155
+ The UploadedFile class is a subclass of BytesIO, and therefore
156
+ it is "file-like". This means you can pass them anywhere where
157
+ a file is expected.
158
+
159
+ Examples
160
+ --------
161
+ >>> import streamlit as st
162
+ >>>
163
+ >>> audio_value = st.experimental_audio_input("Record a voice message")
164
+ >>>
165
+ >>> if audio_value:
166
+ ... st.audio(audio_value)
167
+
168
+ """
169
+ ctx = get_script_run_ctx()
170
+ return self._audio_input(
171
+ label=label,
172
+ key=key,
173
+ help=help,
174
+ on_change=on_change,
175
+ args=args,
176
+ kwargs=kwargs,
177
+ disabled=disabled,
178
+ label_visibility=label_visibility,
179
+ ctx=ctx,
180
+ )
181
+
182
+ def _audio_input(
183
+ self,
184
+ label: str,
185
+ key: Key | None = None,
186
+ help: str | None = None,
187
+ on_change: WidgetCallback | None = None,
188
+ args: WidgetArgs | None = None,
189
+ kwargs: WidgetKwargs | None = None,
190
+ *, # keyword-only arguments:
191
+ disabled: bool = False,
192
+ label_visibility: LabelVisibility = "visible",
193
+ ctx: ScriptRunContext | None = None,
194
+ ) -> UploadedFile | None:
195
+ key = to_key(key)
196
+
197
+ check_widget_policies(
198
+ self.dg,
199
+ key,
200
+ on_change,
201
+ default_value=None,
202
+ writes_allowed=False,
203
+ )
204
+ maybe_raise_label_warnings(label, label_visibility)
205
+
206
+ element_id = compute_and_register_element_id(
207
+ "audio_input",
208
+ user_key=key,
209
+ form_id=current_form_id(self.dg),
210
+ label=label,
211
+ help=help,
212
+ )
213
+
214
+ audio_input_proto = AudioInputProto()
215
+ audio_input_proto.id = element_id
216
+ audio_input_proto.label = label
217
+ audio_input_proto.form_id = current_form_id(self.dg)
218
+ audio_input_proto.disabled = disabled
219
+ audio_input_proto.label_visibility.value = get_label_visibility_proto_value(
220
+ label_visibility
221
+ )
222
+
223
+ if label and help is not None:
224
+ audio_input_proto.help = dedent(help)
225
+
226
+ serde = AudioInputSerde()
227
+
228
+ audio_input_state = register_widget(
229
+ "audio_input",
230
+ audio_input_proto,
231
+ on_change_handler=on_change,
232
+ args=args,
233
+ kwargs=kwargs,
234
+ deserializer=serde.deserialize,
235
+ serializer=serde.serialize,
236
+ ctx=ctx,
237
+ )
238
+
239
+ self.dg._enqueue("audio_input", audio_input_proto)
240
+
241
+ if isinstance(audio_input_state.value, DeletedFile):
242
+ return None
243
+ return audio_input_state.value
244
+
245
+ @property
246
+ def dg(self) -> DeltaGenerator:
247
+ """Get our DeltaGenerator."""
248
+ return cast("DeltaGenerator", self)
@@ -389,7 +389,7 @@ class ButtonGroupMixin:
389
389
  return sentiment.value
390
390
 
391
391
  @gather_metrics("pills")
392
- def pills(
392
+ def _pills(
393
393
  self,
394
394
  label: str,
395
395
  options: OptionSequence[V],
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: streamlit/proto/AudioInput.proto
4
+ # Protobuf Python Version: 5.26.1
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+ from streamlit.proto import LabelVisibilityMessage_pb2 as streamlit_dot_proto_dot_LabelVisibilityMessage__pb2
16
+
17
+
18
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n streamlit/proto/AudioInput.proto\x1a,streamlit/proto/LabelVisibilityMessage.proto\"\x8b\x01\n\nAudioInput\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05label\x18\x02 \x01(\t\x12\x0c\n\x04help\x18\x03 \x01(\t\x12\x0f\n\x07\x66orm_id\x18\x04 \x01(\t\x12\x10\n\x08\x64isabled\x18\x05 \x01(\x08\x12\x31\n\x10label_visibility\x18\x06 \x01(\x0b\x32\x17.LabelVisibilityMessageB/\n\x1c\x63om.snowflake.apps.streamlitB\x0f\x41udioInputProtob\x06proto3')
19
+
20
+ _globals = globals()
21
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
22
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.AudioInput_pb2', _globals)
23
+ if not _descriptor._USE_C_DESCRIPTORS:
24
+ _globals['DESCRIPTOR']._loaded_options = None
25
+ _globals['DESCRIPTOR']._serialized_options = b'\n\034com.snowflake.apps.streamlitB\017AudioInputProto'
26
+ _globals['_AUDIOINPUT']._serialized_start=83
27
+ _globals['_AUDIOINPUT']._serialized_end=222
28
+ # @@protoc_insertion_point(module_scope)