streamlit-nightly 1.36.1.dev20240702__py2.py3-none-any.whl → 1.36.1.dev20240703__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/commands/navigation.py +1 -1
  2. streamlit/components/v1/component_arrow.py +16 -11
  3. streamlit/components/v1/custom_component.py +2 -1
  4. streamlit/dataframe_util.py +835 -0
  5. streamlit/delta_generator.py +5 -3
  6. streamlit/elements/arrow.py +17 -13
  7. streamlit/elements/lib/built_in_chart_utils.py +78 -12
  8. streamlit/elements/lib/column_config_utils.py +1 -1
  9. streamlit/elements/lib/pandas_styler_utils.py +2 -2
  10. streamlit/elements/lib/policies.py +20 -2
  11. streamlit/elements/lib/utils.py +100 -10
  12. streamlit/elements/map.py +2 -2
  13. streamlit/elements/metric.py +5 -2
  14. streamlit/elements/plotly_chart.py +1 -1
  15. streamlit/elements/vega_charts.py +6 -5
  16. streamlit/elements/widgets/button.py +1 -1
  17. streamlit/elements/widgets/camera_input.py +7 -2
  18. streamlit/elements/widgets/chat.py +1 -1
  19. streamlit/elements/widgets/checkbox.py +7 -2
  20. streamlit/elements/widgets/color_picker.py +7 -2
  21. streamlit/elements/widgets/data_editor.py +10 -9
  22. streamlit/elements/widgets/file_uploader.py +7 -2
  23. streamlit/elements/widgets/multiselect.py +6 -7
  24. streamlit/elements/widgets/number_input.py +7 -2
  25. streamlit/elements/widgets/radio.py +6 -7
  26. streamlit/elements/widgets/select_slider.py +6 -7
  27. streamlit/elements/widgets/selectbox.py +6 -7
  28. streamlit/elements/widgets/slider.py +7 -2
  29. streamlit/elements/widgets/text_widgets.py +8 -5
  30. streamlit/elements/widgets/time_widgets.py +7 -2
  31. streamlit/elements/write.py +5 -5
  32. streamlit/runtime/caching/cache_utils.py +1 -1
  33. streamlit/runtime/state/common.py +51 -2
  34. streamlit/runtime/state/session_state.py +2 -1
  35. streamlit/runtime/state/session_state_proxy.py +1 -1
  36. streamlit/runtime/state/widgets.py +1 -1
  37. streamlit/static/asset-manifest.json +2 -2
  38. streamlit/static/index.html +1 -1
  39. streamlit/static/static/js/{main.e2ab315a.js → main.28e3c6e9.js} +2 -2
  40. streamlit/testing/v1/element_tree.py +3 -3
  41. streamlit/type_util.py +0 -1069
  42. {streamlit_nightly-1.36.1.dev20240702.dist-info → streamlit_nightly-1.36.1.dev20240703.dist-info}/METADATA +1 -1
  43. {streamlit_nightly-1.36.1.dev20240702.dist-info → streamlit_nightly-1.36.1.dev20240703.dist-info}/RECORD +48 -47
  44. /streamlit/static/static/js/{main.e2ab315a.js.LICENSE.txt → main.28e3c6e9.js.LICENSE.txt} +0 -0
  45. {streamlit_nightly-1.36.1.dev20240702.data → streamlit_nightly-1.36.1.dev20240703.data}/scripts/streamlit.cmd +0 -0
  46. {streamlit_nightly-1.36.1.dev20240702.dist-info → streamlit_nightly-1.36.1.dev20240703.dist-info}/WHEEL +0 -0
  47. {streamlit_nightly-1.36.1.dev20240702.dist-info → streamlit_nightly-1.36.1.dev20240703.dist-info}/entry_points.txt +0 -0
  48. {streamlit_nightly-1.36.1.dev20240702.dist-info → streamlit_nightly-1.36.1.dev20240703.dist-info}/top_level.txt +0 -0
@@ -38,10 +38,10 @@ from streamlit import (
38
38
  cli_util,
39
39
  config,
40
40
  cursor,
41
+ dataframe_util,
41
42
  env_util,
42
43
  logger,
43
44
  runtime,
44
- type_util,
45
45
  util,
46
46
  )
47
47
  from streamlit.elements.alert import AlertMixin
@@ -705,8 +705,10 @@ def _prep_data_for_add_rows(
705
705
  add_rows_metadata: AddRowsMetadata | None,
706
706
  ) -> tuple[Data, AddRowsMetadata | None]:
707
707
  if not add_rows_metadata:
708
- # When calling add_rows on st.table or st.dataframe we want styles to pass through.
709
- return type_util.convert_anything_to_df(data, allow_styler=True), None
708
+ if dataframe_util.is_pandas_styler(data):
709
+ # When calling add_rows on st.table or st.dataframe we want styles to pass through.
710
+ return data, None
711
+ return dataframe_util.convert_anything_to_pandas_df(data), None
710
712
 
711
713
  # If add_rows_metadata is set, it indicates that the add_rows used called
712
714
  # on a chart based on our built-in chart commands.
@@ -32,7 +32,7 @@ from typing import (
32
32
 
33
33
  from typing_extensions import TypeAlias
34
34
 
35
- from streamlit import type_util
35
+ from streamlit import dataframe_util
36
36
  from streamlit.elements.lib.column_config_utils import (
37
37
  INDEX_IDENTIFIER,
38
38
  ColumnConfigMappingInput,
@@ -48,13 +48,13 @@ from streamlit.elements.lib.policies import (
48
48
  check_callback_rules,
49
49
  check_session_state_rules,
50
50
  )
51
+ from streamlit.elements.lib.utils import Key, to_key
51
52
  from streamlit.errors import StreamlitAPIException
52
53
  from streamlit.proto.Arrow_pb2 import Arrow as ArrowProto
53
54
  from streamlit.runtime.metrics_util import gather_metrics
54
55
  from streamlit.runtime.scriptrunner import get_script_run_ctx
55
56
  from streamlit.runtime.state import WidgetCallback, register_widget
56
57
  from streamlit.runtime.state.common import compute_widget_id
57
- from streamlit.type_util import Key, to_key
58
58
 
59
59
  if TYPE_CHECKING:
60
60
  import pyarrow as pa
@@ -511,15 +511,15 @@ class ArrowMixin:
511
511
 
512
512
  if isinstance(data, pa.Table):
513
513
  # For pyarrow tables, we can just serialize the table directly
514
- proto.data = type_util.pyarrow_table_to_bytes(data)
514
+ proto.data = dataframe_util.pyarrow_table_to_bytes(data)
515
515
  else:
516
516
  # For all other data formats, we need to convert them to a pandas.DataFrame
517
517
  # thereby, we also apply some data specific configs
518
518
 
519
519
  # Determine the input data format
520
- data_format = type_util.determine_data_format(data)
520
+ data_format = dataframe_util.determine_data_format(data)
521
521
 
522
- if type_util.is_pandas_styler(data):
522
+ if dataframe_util.is_pandas_styler(data):
523
523
  # If pandas.Styler uuid is not provided, a hash of the position
524
524
  # of the element will be used. This will cause a rerender of the table
525
525
  # when the position of the element is changed.
@@ -528,7 +528,9 @@ class ArrowMixin:
528
528
  marshall_styler(proto, data, default_uuid)
529
529
 
530
530
  # Convert the input data into a pandas.DataFrame
531
- data_df = type_util.convert_anything_to_df(data, ensure_copy=False)
531
+ data_df = dataframe_util.convert_anything_to_pandas_df(
532
+ data, ensure_copy=False
533
+ )
532
534
  apply_data_specific_configs(
533
535
  column_config_mapping,
534
536
  data_df,
@@ -536,7 +538,7 @@ class ArrowMixin:
536
538
  check_arrow_compatibility=False,
537
539
  )
538
540
  # Serialize the data to bytes:
539
- proto.data = type_util.data_frame_to_bytes(data_df)
541
+ proto.data = dataframe_util.data_frame_to_bytes(data_df)
540
542
 
541
543
  if hide_index is not None:
542
544
  update_column_config(
@@ -615,8 +617,10 @@ class ArrowMixin:
615
617
 
616
618
  # Check if data is uncollected, and collect it but with 100 rows max, instead of 10k rows, which is done in all other cases.
617
619
  # Avoid this and use 100 rows in st.table, because large tables render slowly, take too much screen space, and can crush the app.
618
- if type_util.is_unevaluated_data_object(data):
619
- data = type_util.convert_anything_to_df(data, max_unevaluated_rows=100)
620
+ if dataframe_util.is_unevaluated_data_object(data):
621
+ data = dataframe_util.convert_anything_to_pandas_df(
622
+ data, max_unevaluated_rows=100
623
+ )
620
624
 
621
625
  # If pandas.Styler uuid is not provided, a hash of the position
622
626
  # of the element will be used. This will cause a rerender of the table
@@ -707,7 +711,7 @@ def marshall(proto: ArrowProto, data: Data, default_uuid: str | None = None) ->
707
711
  """
708
712
  import pyarrow as pa
709
713
 
710
- if type_util.is_pandas_styler(data):
714
+ if dataframe_util.is_pandas_styler(data):
711
715
  # default_uuid is a string only if the data is a `Styler`,
712
716
  # and `None` otherwise.
713
717
  assert isinstance(
@@ -716,7 +720,7 @@ def marshall(proto: ArrowProto, data: Data, default_uuid: str | None = None) ->
716
720
  marshall_styler(proto, data, default_uuid)
717
721
 
718
722
  if isinstance(data, pa.Table):
719
- proto.data = type_util.pyarrow_table_to_bytes(data)
723
+ proto.data = dataframe_util.pyarrow_table_to_bytes(data)
720
724
  else:
721
- df = type_util.convert_anything_to_df(data)
722
- proto.data = type_util.data_frame_to_bytes(df)
725
+ df = dataframe_util.convert_anything_to_pandas_df(data)
726
+ proto.data = dataframe_util.data_frame_to_bytes(df)
@@ -25,12 +25,15 @@ from typing import (
25
25
  Collection,
26
26
  Final,
27
27
  Hashable,
28
+ Literal,
28
29
  Sequence,
29
30
  TypedDict,
30
31
  cast,
31
32
  )
32
33
 
33
- from streamlit import type_util
34
+ from typing_extensions import TypeAlias
35
+
36
+ from streamlit import dataframe_util, type_util
34
37
  from streamlit.color_util import (
35
38
  Color,
36
39
  is_color_like,
@@ -44,8 +47,11 @@ if TYPE_CHECKING:
44
47
  import altair as alt
45
48
  import pandas as pd
46
49
 
50
+ from streamlit.dataframe_util import DataFrameCompatible
47
51
  from streamlit.elements.arrow import Data
48
- from streamlit.type_util import ChartStackType, DataFrameCompatible
52
+
53
+ VegaLiteType: TypeAlias = Literal["quantitative", "ordinal", "temporal", "nominal"]
54
+ ChartStackType: TypeAlias = Literal["normalize", "center", "layered"]
49
55
 
50
56
 
51
57
  class PrepDataColumns(TypedDict):
@@ -129,7 +135,7 @@ def generate_chart(
129
135
  """Function to use the chart's type, data columns and indices to figure out the chart's spec."""
130
136
  import altair as alt
131
137
 
132
- df = type_util.convert_anything_to_df(data, ensure_copy=True)
138
+ df = dataframe_util.convert_anything_to_pandas_df(data, ensure_copy=True)
133
139
 
134
140
  # From now on, use "df" instead of "data". Deleting "data" to guarantee we follow this.
135
141
  del data
@@ -248,7 +254,7 @@ def prep_chart_data_for_add_rows(
248
254
  """
249
255
  import pandas as pd
250
256
 
251
- df = cast(pd.DataFrame, type_util.convert_anything_to_df(data))
257
+ df = cast(pd.DataFrame, dataframe_util.convert_anything_to_pandas_df(data))
252
258
 
253
259
  # Make range indices start at last_index.
254
260
  if isinstance(df.index, pd.RangeIndex):
@@ -273,6 +279,66 @@ def prep_chart_data_for_add_rows(
273
279
  return out_data, add_rows_metadata
274
280
 
275
281
 
282
+ def _infer_vegalite_type(
283
+ data: pd.Series[Any],
284
+ ) -> VegaLiteType:
285
+ """
286
+ From an array-like input, infer the correct vega typecode
287
+ ('ordinal', 'nominal', 'quantitative', or 'temporal')
288
+
289
+ Parameters
290
+ ----------
291
+ data: Numpy array or Pandas Series
292
+ """
293
+ # The code below is copied from Altair, and slightly modified.
294
+ # We copy this code here so we don't depend on private Altair functions.
295
+ # Source: https://github.com/altair-viz/altair/blob/62ca5e37776f5cecb27e83c1fbd5d685a173095d/altair/utils/core.py#L193
296
+
297
+ from pandas.api.types import infer_dtype
298
+
299
+ # STREAMLIT MOD: I'm using infer_dtype directly here, rather than using Altair's wrapper. Their
300
+ # wrapper is only there to support Pandas < 0.20, but Streamlit requires Pandas 1.3.
301
+ typ = infer_dtype(data)
302
+
303
+ if typ in [
304
+ "floating",
305
+ "mixed-integer-float",
306
+ "integer",
307
+ "mixed-integer",
308
+ "complex",
309
+ ]:
310
+ return "quantitative"
311
+
312
+ elif typ == "categorical" and data.cat.ordered:
313
+ # STREAMLIT MOD: The original code returns a tuple here:
314
+ # return ("ordinal", data.cat.categories.tolist())
315
+ # But returning the tuple here isn't compatible with our
316
+ # built-in chart implementation. And it also doesn't seem to be necessary.
317
+ # Altair already extracts the correct sort order somewhere else.
318
+ # More info about the issue here: https://github.com/streamlit/streamlit/issues/7776
319
+ return "ordinal"
320
+ elif typ in ["string", "bytes", "categorical", "boolean", "mixed", "unicode"]:
321
+ return "nominal"
322
+ elif typ in [
323
+ "datetime",
324
+ "datetime64",
325
+ "timedelta",
326
+ "timedelta64",
327
+ "date",
328
+ "time",
329
+ "period",
330
+ ]:
331
+ return "temporal"
332
+ else:
333
+ # STREAMLIT MOD: I commented this out since Streamlit doesn't have a warnings object.
334
+ # warnings.warn(
335
+ # "I don't know how to infer vegalite type from '{}'. "
336
+ # "Defaulting to nominal.".format(typ),
337
+ # stacklevel=1,
338
+ # )
339
+ return "nominal"
340
+
341
+
276
342
  def _get_pandas_index_attr(
277
343
  data: pd.DataFrame | pd.Series,
278
344
  attr: str,
@@ -327,8 +393,8 @@ def _prep_data(
327
393
  def _last_index_for_melted_dataframes(
328
394
  data: DataFrameCompatible | Any,
329
395
  ) -> Hashable | None:
330
- if type_util.is_dataframe_compatible(data):
331
- data = type_util.convert_anything_to_df(data)
396
+ if dataframe_util.is_dataframe_compatible(data):
397
+ data = dataframe_util.convert_anything_to_pandas_df(data)
332
398
 
333
399
  if data.index.size > 0:
334
400
  return cast(Hashable, data.index[-1])
@@ -434,7 +500,7 @@ def _melt_data(
434
500
 
435
501
  # Arrow has problems with object types after melting two different dtypes
436
502
  # pyarrow.lib.ArrowTypeError: "Expected a <TYPE> object, got a object"
437
- fixed_df = type_util.fix_arrow_incompatible_column_types(
503
+ fixed_df = dataframe_util.fix_arrow_incompatible_column_types(
438
504
  melted_df,
439
505
  selected_columns=[
440
506
  *columns_to_leave_alone,
@@ -862,7 +928,7 @@ def _get_color_encoding(
862
928
  if color_column == _MELTED_COLOR_COLUMN_NAME:
863
929
  column_type = "nominal"
864
930
  else:
865
- column_type = type_util.infer_vegalite_type(df[color_column])
931
+ column_type = _infer_vegalite_type(df[color_column])
866
932
 
867
933
  color_enc = alt.Color(
868
934
  field=color_column, legend=_COLOR_LEGEND_SETTINGS, type=column_type
@@ -982,7 +1048,7 @@ def _get_tooltip_encoding(
982
1048
 
983
1049
  def _get_x_encoding_type(
984
1050
  df: pd.DataFrame, chart_type: ChartType, x_column: str | None
985
- ) -> type_util.VegaLiteType:
1051
+ ) -> VegaLiteType:
986
1052
  if x_column is None:
987
1053
  return "quantitative" # Anything. If None, Vega-Lite may hide the axis.
988
1054
 
@@ -991,18 +1057,18 @@ def _get_x_encoding_type(
991
1057
  if chart_type == ChartType.VERTICAL_BAR and not _is_date_column(df, x_column):
992
1058
  return "ordinal"
993
1059
 
994
- return type_util.infer_vegalite_type(df[x_column])
1060
+ return _infer_vegalite_type(df[x_column])
995
1061
 
996
1062
 
997
1063
  def _get_y_encoding_type(
998
1064
  df: pd.DataFrame, chart_type: ChartType, y_column: str | None
999
- ) -> type_util.VegaLiteType:
1065
+ ) -> VegaLiteType:
1000
1066
  # Horizontal bar charts should have a discrete (ordinal) y-axis, UNLESS type is date/time
1001
1067
  if chart_type == ChartType.HORIZONTAL_BAR and not _is_date_column(df, y_column):
1002
1068
  return "ordinal"
1003
1069
 
1004
1070
  if y_column:
1005
- return type_util.infer_vegalite_type(df[y_column])
1071
+ return _infer_vegalite_type(df[y_column])
1006
1072
 
1007
1073
  return "quantitative" # Pick anything. If undefined, Vega-Lite may hide the axis.
1008
1074
 
@@ -21,10 +21,10 @@ from typing import TYPE_CHECKING, Dict, Final, Literal, Mapping, Union
21
21
 
22
22
  from typing_extensions import TypeAlias
23
23
 
24
+ from streamlit.dataframe_util import DataFormat, is_colum_type_arrow_incompatible
24
25
  from streamlit.elements.lib.column_types import ColumnConfig, ColumnType
25
26
  from streamlit.elements.lib.dicttools import remove_none_values
26
27
  from streamlit.errors import StreamlitAPIException
27
- from streamlit.type_util import DataFormat, is_colum_type_arrow_incompatible
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  import pyarrow as pa
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  from typing import TYPE_CHECKING, Any, Mapping, TypeVar
18
18
 
19
- from streamlit import type_util
19
+ from streamlit import dataframe_util
20
20
  from streamlit.errors import StreamlitAPIException
21
21
 
22
22
  if TYPE_CHECKING:
@@ -236,7 +236,7 @@ def _marshall_display_values(
236
236
 
237
237
  """
238
238
  new_df = _use_display_values(df, styles)
239
- proto.styler.display_values = type_util.data_frame_to_bytes(new_df)
239
+ proto.styler.display_values = dataframe_util.data_frame_to_bytes(new_df)
240
240
 
241
241
 
242
242
  def _use_display_values(df: DataFrame, styles: Mapping[str, Any]) -> DataFrame:
@@ -14,9 +14,9 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import TYPE_CHECKING, Any
17
+ from typing import TYPE_CHECKING, Any, Final
18
18
 
19
- from streamlit import config, runtime
19
+ from streamlit import config, errors, logger, runtime
20
20
  from streamlit.elements.form import is_in_form
21
21
  from streamlit.errors import StreamlitAPIException, StreamlitAPIWarning
22
22
  from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx
@@ -26,6 +26,9 @@ if TYPE_CHECKING:
26
26
  from streamlit.delta_generator import DeltaGenerator
27
27
 
28
28
 
29
+ _LOGGER: Final = logger.get_logger(__name__)
30
+
31
+
29
32
  def check_callback_rules(dg: DeltaGenerator, on_change: WidgetCallback | None) -> None:
30
33
  """Ensures that widgets other than `st.form_submit` within a form don't have an on_change callback set.
31
34
 
@@ -143,3 +146,18 @@ def check_fragment_path_policy(dg: DeltaGenerator):
143
146
  for index, path_index in enumerate(current_fragment_delta_path):
144
147
  if current_cursor_delta_path[index] != path_index:
145
148
  raise StreamlitAPIException(_fragment_writes_widget_to_outside_error)
149
+
150
+
151
+ def maybe_raise_label_warnings(label: str | None, label_visibility: str | None):
152
+ if not label:
153
+ _LOGGER.warning(
154
+ "`label` got an empty value. This is discouraged for accessibility "
155
+ "reasons and may be disallowed in the future by raising an exception. "
156
+ "Please provide a non-empty label and hide it with label_visibility "
157
+ "if needed."
158
+ )
159
+ if label_visibility not in ("visible", "hidden", "collapsed"):
160
+ raise errors.StreamlitAPIException(
161
+ f"Unsupported label_visibility option '{label_visibility}'. "
162
+ f"Valid values are 'visible', 'hidden' or 'collapsed'."
163
+ )
@@ -15,9 +15,21 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from enum import Enum, EnumMeta
18
- from typing import TYPE_CHECKING, Any, Iterable, Sequence, overload
19
-
20
- from streamlit import type_util
18
+ from typing import (
19
+ TYPE_CHECKING,
20
+ Any,
21
+ Final,
22
+ Iterable,
23
+ Literal,
24
+ Sequence,
25
+ TypeVar,
26
+ Union,
27
+ overload,
28
+ )
29
+
30
+ from typing_extensions import TypeAlias
31
+
32
+ from streamlit import config, dataframe_util, errors, logger
21
33
  from streamlit.proto.LabelVisibilityMessage_pb2 import LabelVisibilityMessage
22
34
  from streamlit.runtime.state.common import RegisterWidgetResult
23
35
 
@@ -25,8 +37,15 @@ if TYPE_CHECKING:
25
37
  from streamlit.type_util import T
26
38
 
27
39
 
40
+ _LOGGER: Final = logger.get_logger(__name__)
41
+
42
+ Key: TypeAlias = Union[str, int]
43
+
44
+ LabelVisibility: TypeAlias = Literal["visible", "hidden", "collapsed"]
45
+
46
+
28
47
  def get_label_visibility_proto_value(
29
- label_visibility_string: type_util.LabelVisibility,
48
+ label_visibility_string: LabelVisibility,
30
49
  ) -> LabelVisibilityMessage.LabelVisibilityOptions.ValueType:
31
50
  """Returns one of LabelVisibilityMessage enum constants.py based on string value."""
32
51
 
@@ -40,6 +59,78 @@ def get_label_visibility_proto_value(
40
59
  raise ValueError(f"Unknown label visibility value: {label_visibility_string}")
41
60
 
42
61
 
62
+ @overload
63
+ def to_key(key: None) -> None: ...
64
+
65
+
66
+ @overload
67
+ def to_key(key: Key) -> str: ...
68
+
69
+
70
+ def to_key(key: Key | None) -> str | None:
71
+ return None if key is None else str(key)
72
+
73
+
74
+ E1 = TypeVar("E1", bound=Enum)
75
+ E2 = TypeVar("E2", bound=Enum)
76
+
77
+ _ALLOWED_ENUM_COERCION_CONFIG_SETTINGS = ("off", "nameOnly", "nameAndValue")
78
+
79
+
80
+ def _coerce_enum(from_enum_value: E1, to_enum_class: type[E2]) -> E1 | E2:
81
+ """Attempt to coerce an Enum value to another EnumMeta.
82
+
83
+ An Enum value of EnumMeta E1 is considered coercable to EnumType E2
84
+ if the EnumMeta __qualname__ match and the names of their members
85
+ match as well. (This is configurable in streamlist configs)
86
+ """
87
+ if not isinstance(from_enum_value, Enum):
88
+ raise ValueError(
89
+ f"Expected an Enum in the first argument. Got {type(from_enum_value)}"
90
+ )
91
+ if not isinstance(to_enum_class, EnumMeta):
92
+ raise ValueError(
93
+ f"Expected an EnumMeta/Type in the second argument. Got {type(to_enum_class)}"
94
+ )
95
+ if isinstance(from_enum_value, to_enum_class):
96
+ return from_enum_value # Enum is already a member, no coersion necessary
97
+
98
+ coercion_type = config.get_option("runner.enumCoercion")
99
+ if coercion_type not in _ALLOWED_ENUM_COERCION_CONFIG_SETTINGS:
100
+ raise errors.StreamlitAPIException(
101
+ "Invalid value for config option runner.enumCoercion. "
102
+ f"Expected one of {_ALLOWED_ENUM_COERCION_CONFIG_SETTINGS}, "
103
+ f"but got '{coercion_type}'."
104
+ )
105
+ if coercion_type == "off":
106
+ return from_enum_value # do not attempt to coerce
107
+
108
+ # We now know this is an Enum AND the user has configured coercion enabled.
109
+ # Check if we do NOT meet the required conditions and log a failure message
110
+ # if that is the case.
111
+ from_enum_class = from_enum_value.__class__
112
+ if (
113
+ from_enum_class.__qualname__ != to_enum_class.__qualname__
114
+ or (
115
+ coercion_type == "nameOnly"
116
+ and set(to_enum_class._member_names_) != set(from_enum_class._member_names_)
117
+ )
118
+ or (
119
+ coercion_type == "nameAndValue"
120
+ and set(to_enum_class._value2member_map_)
121
+ != set(from_enum_class._value2member_map_)
122
+ )
123
+ ):
124
+ _LOGGER.debug("Failed to coerce %s to class %s", from_enum_value, to_enum_class)
125
+ return from_enum_value # do not attempt to coerce
126
+
127
+ # At this point we think the Enum is coercable, and we know
128
+ # E1 and E2 have the same member names. We convert from E1 to E2 using _name_
129
+ # (since user Enum subclasses can override the .name property in 3.11)
130
+ _LOGGER.debug("Coerced %s to class %s", from_enum_value, to_enum_class)
131
+ return to_enum_class[from_enum_value._name_]
132
+
133
+
43
134
  @overload
44
135
  def maybe_coerce_enum(
45
136
  register_widget_result: RegisterWidgetResult[Enum],
@@ -51,7 +142,7 @@ def maybe_coerce_enum(
51
142
  @overload
52
143
  def maybe_coerce_enum(
53
144
  register_widget_result: RegisterWidgetResult[T],
54
- options: type_util.OptionSequence[T],
145
+ options: dataframe_util.OptionSequence[T],
55
146
  opt_sequence: Sequence[T],
56
147
  ) -> RegisterWidgetResult[T]: ...
57
148
 
@@ -74,7 +165,7 @@ def maybe_coerce_enum(register_widget_result, options, opt_sequence):
74
165
  return register_widget_result
75
166
 
76
167
  return RegisterWidgetResult(
77
- type_util.coerce_enum(register_widget_result.value, coerce_class),
168
+ _coerce_enum(register_widget_result.value, coerce_class),
78
169
  register_widget_result.value_changed,
79
170
  )
80
171
 
@@ -84,7 +175,7 @@ def maybe_coerce_enum(register_widget_result, options, opt_sequence):
84
175
  @overload
85
176
  def maybe_coerce_enum_sequence(
86
177
  register_widget_result: RegisterWidgetResult[list[T]],
87
- options: type_util.OptionSequence[T],
178
+ options: dataframe_util.OptionSequence[T],
88
179
  opt_sequence: Sequence[T],
89
180
  ) -> RegisterWidgetResult[list[T]]: ...
90
181
 
@@ -92,7 +183,7 @@ def maybe_coerce_enum_sequence(
92
183
  @overload
93
184
  def maybe_coerce_enum_sequence(
94
185
  register_widget_result: RegisterWidgetResult[tuple[T, T]],
95
- options: type_util.OptionSequence[T],
186
+ options: dataframe_util.OptionSequence[T],
96
187
  opt_sequence: Sequence[T],
97
188
  ) -> RegisterWidgetResult[tuple[T, T]]: ...
98
189
 
@@ -118,8 +209,7 @@ def maybe_coerce_enum_sequence(register_widget_result, options, opt_sequence):
118
209
  # Return a new RegisterWidgetResult with the coerced enum values sequence
119
210
  return RegisterWidgetResult(
120
211
  type(register_widget_result.value)(
121
- type_util.coerce_enum(val, coerce_class)
122
- for val in register_widget_result.value
212
+ _coerce_enum(val, coerce_class) for val in register_widget_result.value
123
213
  ),
124
214
  register_widget_result.value_changed,
125
215
  )
streamlit/elements/map.py CHANGED
@@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Any, Collection, Dict, Final, Iterable, Union,
24
24
  from typing_extensions import TypeAlias
25
25
 
26
26
  import streamlit.elements.deck_gl_json_chart as deck_gl_json_chart
27
- from streamlit import config, type_util
27
+ from streamlit import config, dataframe_util
28
28
  from streamlit.color_util import Color, IntColorTuple, is_color_like, to_int_color_tuple
29
29
  from streamlit.errors import StreamlitAPIException
30
30
  from streamlit.proto.DeckGlJsonChart_pb2 import DeckGlJsonChart as DeckGlJsonChartProto
@@ -263,7 +263,7 @@ def to_deckgl_json(
263
263
  if hasattr(data, "empty") and data.empty:
264
264
  return json.dumps(_DEFAULT_MAP)
265
265
 
266
- df = type_util.convert_anything_to_df(data)
266
+ df = dataframe_util.convert_anything_to_pandas_df(data)
267
267
 
268
268
  lat_col_name = _get_lat_or_lon_col_name(df, "latitude", lat, _DEFAULT_LAT_COL_NAMES)
269
269
  lon_col_name = _get_lat_or_lon_col_name(
@@ -20,12 +20,15 @@ from typing import TYPE_CHECKING, Literal, Union, cast
20
20
 
21
21
  from typing_extensions import TypeAlias
22
22
 
23
- from streamlit.elements.lib.utils import get_label_visibility_proto_value
23
+ from streamlit.elements.lib.policies import maybe_raise_label_warnings
24
+ from streamlit.elements.lib.utils import (
25
+ LabelVisibility,
26
+ get_label_visibility_proto_value,
27
+ )
24
28
  from streamlit.errors import StreamlitAPIException
25
29
  from streamlit.proto.Metric_pb2 import Metric as MetricProto
26
30
  from streamlit.runtime.metrics_util import gather_metrics
27
31
  from streamlit.string_util import clean_text
28
- from streamlit.type_util import LabelVisibility, maybe_raise_label_warnings
29
32
 
30
33
  if TYPE_CHECKING:
31
34
  import numpy as np
@@ -47,13 +47,13 @@ from streamlit.elements.lib.policies import (
47
47
  from streamlit.elements.lib.streamlit_plotly_theme import (
48
48
  configure_streamlit_plotly_theme,
49
49
  )
50
+ from streamlit.elements.lib.utils import Key, to_key
50
51
  from streamlit.errors import StreamlitAPIException
51
52
  from streamlit.proto.PlotlyChart_pb2 import PlotlyChart as PlotlyChartProto
52
53
  from streamlit.runtime.metrics_util import gather_metrics
53
54
  from streamlit.runtime.scriptrunner import get_script_run_ctx
54
55
  from streamlit.runtime.state import WidgetCallback, register_widget
55
56
  from streamlit.runtime.state.common import compute_widget_id
56
- from streamlit.type_util import Key, to_key
57
57
 
58
58
  if TYPE_CHECKING:
59
59
  import matplotlib
@@ -36,9 +36,10 @@ from typing import (
36
36
  from typing_extensions import TypeAlias
37
37
 
38
38
  import streamlit.elements.lib.dicttools as dicttools
39
- from streamlit import type_util
39
+ from streamlit import dataframe_util, type_util
40
40
  from streamlit.elements.lib.built_in_chart_utils import (
41
41
  AddRowsMetadata,
42
+ ChartStackType,
42
43
  ChartType,
43
44
  generate_chart,
44
45
  )
@@ -49,6 +50,7 @@ from streamlit.elements.lib.policies import (
49
50
  check_fragment_path_policy,
50
51
  check_session_state_rules,
51
52
  )
53
+ from streamlit.elements.lib.utils import Key, to_key
52
54
  from streamlit.errors import StreamlitAPIException
53
55
  from streamlit.proto.ArrowVegaLiteChart_pb2 import (
54
56
  ArrowVegaLiteChart as ArrowVegaLiteChartProto,
@@ -57,7 +59,6 @@ from streamlit.runtime.metrics_util import gather_metrics
57
59
  from streamlit.runtime.scriptrunner import get_script_run_ctx
58
60
  from streamlit.runtime.state import register_widget
59
61
  from streamlit.runtime.state.common import compute_widget_id
60
- from streamlit.type_util import ChartStackType, Key, to_key
61
62
  from streamlit.util import HASHLIB_KWARGS
62
63
 
63
64
  if TYPE_CHECKING:
@@ -279,10 +280,10 @@ def _serialize_data(data: Any) -> bytes:
279
280
  import pyarrow as pa
280
281
 
281
282
  if isinstance(data, pa.Table):
282
- return type_util.pyarrow_table_to_bytes(data)
283
+ return dataframe_util.pyarrow_table_to_bytes(data)
283
284
 
284
- df = type_util.convert_anything_to_df(data)
285
- return type_util.data_frame_to_bytes(df)
285
+ df = dataframe_util.convert_anything_to_pandas_df(data)
286
+ return dataframe_util.data_frame_to_bytes(df)
286
287
 
287
288
 
288
289
  def _marshall_chart_data(
@@ -30,6 +30,7 @@ from streamlit.elements.lib.policies import (
30
30
  check_fragment_path_policy,
31
31
  check_session_state_rules,
32
32
  )
33
+ from streamlit.elements.lib.utils import Key, to_key
33
34
  from streamlit.errors import StreamlitAPIException
34
35
  from streamlit.file_util import get_main_script_directory, normalize_path_join
35
36
  from streamlit.navigation.page import StreamlitPage
@@ -47,7 +48,6 @@ from streamlit.runtime.state import (
47
48
  )
48
49
  from streamlit.runtime.state.common import compute_widget_id, save_for_app_testing
49
50
  from streamlit.string_util import validate_icon_or_emoji
50
- from streamlit.type_util import Key, to_key
51
51
  from streamlit.url_util import is_url
52
52
 
53
53
  if TYPE_CHECKING:
@@ -26,8 +26,14 @@ from streamlit.elements.lib.policies import (
26
26
  check_callback_rules,
27
27
  check_fragment_path_policy,
28
28
  check_session_state_rules,
29
+ maybe_raise_label_warnings,
30
+ )
31
+ from streamlit.elements.lib.utils import (
32
+ Key,
33
+ LabelVisibility,
34
+ get_label_visibility_proto_value,
35
+ to_key,
29
36
  )
30
- from streamlit.elements.lib.utils import get_label_visibility_proto_value
31
37
  from streamlit.elements.widgets.file_uploader import _get_upload_files
32
38
  from streamlit.proto.CameraInput_pb2 import CameraInput as CameraInputProto
33
39
  from streamlit.proto.Common_pb2 import FileUploaderState as FileUploaderStateProto
@@ -42,7 +48,6 @@ from streamlit.runtime.state import (
42
48
  )
43
49
  from streamlit.runtime.state.common import compute_widget_id
44
50
  from streamlit.runtime.uploaded_file_manager import DeletedFile, UploadedFile
45
- from streamlit.type_util import Key, LabelVisibility, maybe_raise_label_warnings, to_key
46
51
 
47
52
  if TYPE_CHECKING:
48
53
  from streamlit.delta_generator import DeltaGenerator