streamlit-nightly 1.53.1.dev20260115__py3-none-any.whl → 1.53.1.dev20260116__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 (73) hide show
  1. streamlit/auth_util.py +90 -1
  2. streamlit/cli_util.py +2 -1
  3. streamlit/commands/echo.py +2 -2
  4. streamlit/commands/execution_control.py +1 -1
  5. streamlit/commands/navigation.py +1 -1
  6. streamlit/components/types/base_custom_component.py +0 -2
  7. streamlit/components/v1/custom_component.py +0 -2
  8. streamlit/components/v2/component_path_utils.py +1 -1
  9. streamlit/components/v2/manifest_scanner.py +8 -3
  10. streamlit/components/v2/presentation.py +1 -1
  11. streamlit/config.py +15 -13
  12. streamlit/config_util.py +5 -5
  13. streamlit/dataframe_util.py +5 -5
  14. streamlit/elements/arrow.py +11 -6
  15. streamlit/elements/deck_gl_json_chart.py +1 -1
  16. streamlit/elements/exception.py +4 -2
  17. streamlit/elements/form.py +1 -1
  18. streamlit/elements/layouts.py +1 -1
  19. streamlit/elements/lib/built_in_chart_utils.py +7 -7
  20. streamlit/elements/lib/column_config_utils.py +6 -6
  21. streamlit/elements/lib/dialog.py +1 -1
  22. streamlit/elements/lib/image_utils.py +4 -4
  23. streamlit/elements/lib/layout_utils.py +1 -1
  24. streamlit/elements/lib/policies.py +1 -1
  25. streamlit/elements/lib/utils.py +1 -1
  26. streamlit/elements/map.py +6 -6
  27. streamlit/elements/plotly_chart.py +2 -2
  28. streamlit/elements/toast.py +1 -1
  29. streamlit/elements/vega_charts.py +2 -2
  30. streamlit/elements/widgets/button.py +3 -3
  31. streamlit/elements/widgets/button_group.py +3 -3
  32. streamlit/elements/widgets/chat.py +1 -1
  33. streamlit/elements/widgets/data_editor.py +6 -6
  34. streamlit/elements/widgets/number_input.py +1 -1
  35. streamlit/elements/widgets/slider.py +5 -5
  36. streamlit/elements/widgets/time_widgets.py +91 -10
  37. streamlit/elements/write.py +1 -1
  38. streamlit/env_util.py +1 -1
  39. streamlit/errors.py +0 -14
  40. streamlit/runtime/app_session.py +0 -1
  41. streamlit/runtime/caching/cache_data_api.py +3 -3
  42. streamlit/runtime/caching/cache_errors.py +0 -2
  43. streamlit/runtime/caching/cache_resource_api.py +1 -1
  44. streamlit/runtime/caching/cache_utils.py +2 -2
  45. streamlit/runtime/caching/hashing.py +1 -3
  46. streamlit/runtime/caching/storage/cache_storage_protocol.py +0 -3
  47. streamlit/runtime/connection_factory.py +1 -1
  48. streamlit/runtime/runtime.py +6 -6
  49. streamlit/runtime/scriptrunner_utils/exceptions.py +0 -4
  50. streamlit/runtime/secrets.py +2 -3
  51. streamlit/runtime/state/session_state.py +1 -1
  52. streamlit/runtime/stats.py +0 -7
  53. streamlit/string_util.py +2 -2
  54. streamlit/testing/v1/element_tree.py +8 -10
  55. streamlit/type_util.py +2 -2
  56. streamlit/url_util.py +2 -2
  57. streamlit/user_info.py +2 -2
  58. streamlit/util.py +1 -1
  59. streamlit/watcher/path_watcher.py +1 -1
  60. streamlit/web/cli.py +1 -4
  61. streamlit/web/server/app_discovery.py +2 -1
  62. streamlit/web/server/oauth_authlib_routes.py +14 -42
  63. streamlit/web/server/server.py +1 -1
  64. streamlit/web/server/server_util.py +1 -1
  65. streamlit/web/server/starlette/starlette_auth_routes.py +94 -16
  66. streamlit/web/server/starlette/starlette_routes.py +9 -3
  67. streamlit/web/server/starlette/starlette_server.py +2 -2
  68. {streamlit_nightly-1.53.1.dev20260115.dist-info → streamlit_nightly-1.53.1.dev20260116.dist-info}/METADATA +1 -1
  69. {streamlit_nightly-1.53.1.dev20260115.dist-info → streamlit_nightly-1.53.1.dev20260116.dist-info}/RECORD +73 -73
  70. {streamlit_nightly-1.53.1.dev20260115.data → streamlit_nightly-1.53.1.dev20260116.data}/scripts/streamlit.cmd +0 -0
  71. {streamlit_nightly-1.53.1.dev20260115.dist-info → streamlit_nightly-1.53.1.dev20260116.dist-info}/WHEEL +0 -0
  72. {streamlit_nightly-1.53.1.dev20260115.dist-info → streamlit_nightly-1.53.1.dev20260116.dist-info}/entry_points.txt +0 -0
  73. {streamlit_nightly-1.53.1.dev20260115.dist-info → streamlit_nightly-1.53.1.dev20260116.dist-info}/top_level.txt +0 -0
streamlit/elements/map.py CHANGED
@@ -93,8 +93,8 @@ class MapMixin:
93
93
  *,
94
94
  latitude: str | None = None,
95
95
  longitude: str | None = None,
96
- color: None | str | Color = None,
97
- size: None | str | float = None,
96
+ color: str | Color | None = None,
97
+ size: str | float | None = None,
98
98
  zoom: int | None = None,
99
99
  width: WidthWithoutContent = "stretch",
100
100
  height: HeightWithoutContent = 500,
@@ -296,8 +296,8 @@ def to_deckgl_json(
296
296
  data: Data,
297
297
  lat: str | None,
298
298
  lon: str | None,
299
- size: None | str | float,
300
- color: None | str | Collection[float],
299
+ size: str | float | None,
300
+ color: str | Collection[float] | None,
301
301
  zoom: int | None,
302
302
  ) -> str:
303
303
  if data is None:
@@ -432,7 +432,7 @@ def _convert_color_arg_or_column(
432
432
  data: DataFrame,
433
433
  color_arg: str,
434
434
  color_col_name: str | None,
435
- ) -> None | str | IntColorTuple:
435
+ ) -> str | IntColorTuple | None:
436
436
  """Converts color to a format accepted by PyDeck.
437
437
 
438
438
  For example:
@@ -443,7 +443,7 @@ def _convert_color_arg_or_column(
443
443
  NOTE: This function mutates the data argument.
444
444
  """
445
445
 
446
- color_arg_out: None | str | IntColorTuple = None
446
+ color_arg_out: str | IntColorTuple | None = None
447
447
 
448
448
  if color_col_name is not None:
449
449
  # Convert color column to the right format.
@@ -677,14 +677,14 @@ class PlotlyMixin:
677
677
  "options."
678
678
  )
679
679
 
680
- if theme not in ["streamlit", None]:
680
+ if theme not in {"streamlit", None}:
681
681
  raise StreamlitAPIException(
682
682
  f'You set theme="{theme}" while Streamlit charts only support '
683
683
  "theme=”streamlit” or theme=None to fallback to the default "
684
684
  "library theme."
685
685
  )
686
686
 
687
- if on_select not in ["ignore", "rerun"] and not callable(on_select):
687
+ if on_select not in {"ignore", "rerun"} and not callable(on_select):
688
688
  raise StreamlitAPIException(
689
689
  f"You have passed {on_select} to `on_select`. But only 'ignore', "
690
690
  "'rerun', or a callable is supported."
@@ -151,7 +151,7 @@ class ToastMixin:
151
151
  toast_proto.body = clean_text(validate_text(body))
152
152
  toast_proto.icon = validate_icon_or_emoji(icon)
153
153
 
154
- if duration in ["short", "long", "infinite"] or (
154
+ if duration in {"short", "long", "infinite"} or (
155
155
  isinstance(duration, int) and duration > 0
156
156
  ):
157
157
  if duration == "short":
@@ -2282,14 +2282,14 @@ class VegaChartsMixin:
2282
2282
 
2283
2283
  See the `vega_lite_chart` method docstring for more information.
2284
2284
  """
2285
- if theme not in ["streamlit", None]:
2285
+ if theme not in {"streamlit", None}:
2286
2286
  raise StreamlitAPIException(
2287
2287
  f'You set theme="{theme}" while Streamlit charts only support '
2288
2288
  "theme=”streamlit” or theme=None to fallback to the default "
2289
2289
  "library theme."
2290
2290
  )
2291
2291
 
2292
- if on_select not in ["ignore", "rerun"] and not callable(on_select):
2292
+ if on_select not in {"ignore", "rerun"} and not callable(on_select):
2293
2293
  raise StreamlitAPIException(
2294
2294
  f"You have passed {on_select} to `on_select`. But only 'ignore', "
2295
2295
  "'rerun', or a callable is supported."
@@ -356,7 +356,7 @@ class ButtonMixin:
356
356
  width = "stretch" if use_container_width else "content"
357
357
 
358
358
  # Checks whether the entered button type is one of the allowed options
359
- if type not in ["primary", "secondary", "tertiary"]:
359
+ if type not in {"primary", "secondary", "tertiary"}:
360
360
  raise StreamlitAPIException(
361
361
  'The type argument to st.button must be "primary", "secondary", or "tertiary". '
362
362
  f'\nThe argument passed was "{type}".'
@@ -736,7 +736,7 @@ class ButtonMixin:
736
736
  if use_container_width is not None:
737
737
  width = "stretch" if use_container_width else "content"
738
738
 
739
- if type not in ["primary", "secondary", "tertiary"]:
739
+ if type not in {"primary", "secondary", "tertiary"}:
740
740
  raise StreamlitAPIException(
741
741
  'The type argument to st.download_button must be "primary", "secondary", or "tertiary". \n'
742
742
  f'The argument passed was "{type}".'
@@ -915,7 +915,7 @@ class ButtonMixin:
915
915
 
916
916
  """
917
917
  # Checks whether the entered button type is one of the allowed options - either "primary" or "secondary"
918
- if type not in ["primary", "secondary", "tertiary"]:
918
+ if type not in {"primary", "secondary", "tertiary"}:
919
919
  raise StreamlitAPIException(
920
920
  'The type argument to st.link_button must be "primary", "secondary", or "tertiary". '
921
921
  f'\nThe argument passed was "{type}".'
@@ -255,7 +255,7 @@ def _build_proto(
255
255
 
256
256
  def _maybe_raise_selection_mode_warning(selection_mode: SelectionMode) -> None:
257
257
  """Check if the selection_mode value is valid or raise exception otherwise."""
258
- if selection_mode not in ["single", "multi"]:
258
+ if selection_mode not in {"single", "multi"}:
259
259
  raise StreamlitAPIException(
260
260
  "The selection_mode argument must be one of ['single', 'multi']. "
261
261
  f"The argument passed was '{selection_mode}'."
@@ -410,7 +410,7 @@ class ButtonGroupMixin:
410
410
 
411
411
  """
412
412
 
413
- if options not in ["thumbs", "faces", "stars"]:
413
+ if options not in {"thumbs", "faces", "stars"}:
414
414
  raise StreamlitAPIException(
415
415
  "The options argument to st.feedback must be one of "
416
416
  "['thumbs', 'faces', 'stars']. "
@@ -1062,7 +1062,7 @@ class ButtonGroupMixin:
1062
1062
  "`selection_mode='single'`."
1063
1063
  )
1064
1064
 
1065
- if style not in ["borderless", "pills", "segmented_control"]:
1065
+ if style not in {"borderless", "pills", "segmented_control"}:
1066
1066
  raise StreamlitAPIException(
1067
1067
  "The style argument must be one of ['borderless', 'pills', 'segmented_control']. "
1068
1068
  f"The argument passed was '{style}'."
@@ -223,7 +223,7 @@ def _process_avatar_input(
223
223
  AvatarType.ICON,
224
224
  (
225
225
  "assistant"
226
- if avatar in [PresetNames.AI, PresetNames.ASSISTANT]
226
+ if avatar in {PresetNames.AI, PresetNames.ASSISTANT}
227
227
  else "user"
228
228
  ),
229
229
  )
@@ -238,11 +238,11 @@ def _parse_value(
238
238
  if column_data_kind == ColumnDataKind.TIMEDELTA:
239
239
  return pd.Timedelta(value)
240
240
 
241
- if column_data_kind in [
241
+ if column_data_kind in {
242
242
  ColumnDataKind.DATETIME,
243
243
  ColumnDataKind.DATE,
244
244
  ColumnDataKind.TIME,
245
- ]:
245
+ }:
246
246
  datetime_value = pd.Timestamp(value)
247
247
 
248
248
  if pd.isna(datetime_value):
@@ -481,7 +481,7 @@ def _is_supported_index(df_index: pd.Index[Any]) -> bool:
481
481
 
482
482
  return (
483
483
  type(df_index)
484
- in [
484
+ in {
485
485
  pd.RangeIndex,
486
486
  pd.Index,
487
487
  pd.DatetimeIndex,
@@ -490,7 +490,7 @@ def _is_supported_index(df_index: pd.Index[Any]) -> bool:
490
490
  # pd.IntervalIndex,
491
491
  # Period type isn't editable currently:
492
492
  # pd.PeriodIndex,
493
- ]
493
+ }
494
494
  # We need to check these index types without importing, since they are
495
495
  # deprecated and planned to be removed soon.
496
496
  or is_type(df_index, "pandas.core.indexes.numeric.Int64Index")
@@ -1029,7 +1029,7 @@ class DataEditorMixin:
1029
1029
  update_column_config(
1030
1030
  column_config_mapping, INDEX_IDENTIFIER, {"required": True}
1031
1031
  )
1032
- if num_rows in ("dynamic", "add") and hide_index is True:
1032
+ if num_rows in {"dynamic", "add"} and hide_index is True:
1033
1033
  _LOGGER.warning(
1034
1034
  "Setting `hide_index=True` in data editor with a non-range index will not have any effect "
1035
1035
  "when `num_rows` is '%s'. It is required for the user to fill in index values for "
@@ -1038,7 +1038,7 @@ class DataEditorMixin:
1038
1038
  num_rows,
1039
1039
  )
1040
1040
 
1041
- if hide_index is None and has_range_index and num_rows in ("dynamic", "add"):
1041
+ if hide_index is None and has_range_index and num_rows in {"dynamic", "add"}:
1042
1042
  # Temporary workaround:
1043
1043
  # We hide range indices if num_rows allows adding rows.
1044
1044
  # since the current way of handling this index during editing is a
@@ -512,7 +512,7 @@ class NumberInputMixin:
512
512
  number_format = ("%d" if int_value else "%0.2f") if format is None else format
513
513
 
514
514
  # Warn user if they format an int type as a float or vice versa.
515
- if number_format in ["%d", "%u", "%i"] and float_value:
515
+ if number_format in {"%d", "%u", "%i"} and float_value:
516
516
  import streamlit as st
517
517
 
518
518
  st.warning(
@@ -739,7 +739,7 @@ class SliderMixin:
739
739
 
740
740
  # Ensure that the value is either a single value or a range of values.
741
741
  single_value = isinstance(value, tuple(SUPPORTED_TYPES.keys()))
742
- range_value = isinstance(value, (list, tuple)) and len(value) in (0, 1, 2)
742
+ range_value = isinstance(value, (list, tuple)) and len(value) in {0, 1, 2}
743
743
  if not single_value and not range_value:
744
744
  raise StreamlitAPIException(
745
745
  "Slider value should either be an int/float/datetime or a list/tuple of "
@@ -778,7 +778,7 @@ class SliderMixin:
778
778
 
779
779
  datetime_min = time.min.replace(tzinfo=prepared_value[0].tzinfo)
780
780
  datetime_max = time.max.replace(tzinfo=prepared_value[0].tzinfo)
781
- if data_type in (SliderProto.DATETIME, SliderProto.DATE):
781
+ if data_type in {SliderProto.DATETIME, SliderProto.DATE}:
782
782
  prepared_value = cast("Sequence[datetime]", prepared_value)
783
783
 
784
784
  datetime_min = prepared_value[0] - timedelta(days=14)
@@ -823,10 +823,10 @@ class SliderMixin:
823
823
  max_value = defaults[data_type]["max_value"]
824
824
  if step is None:
825
825
  step = defaults[data_type]["step"]
826
- if data_type in (
826
+ if data_type in {
827
827
  SliderProto.DATETIME,
828
828
  SliderProto.DATE,
829
- ) and max_value - min_value < timedelta(days=1):
829
+ } and max_value - min_value < timedelta(days=1):
830
830
  step = timedelta(minutes=15)
831
831
  if format is None:
832
832
  format = cast("str", defaults[data_type]["format"]) # noqa: A001
@@ -945,7 +945,7 @@ class SliderMixin:
945
945
  # Restore times/datetimes to original timezone (dates are always naive)
946
946
  orig_tz = (
947
947
  prepared_value[0].tzinfo
948
- if data_type in (SliderProto.TIME, SliderProto.DATETIME)
948
+ if data_type in {SliderProto.TIME, SliderProto.DATETIME}
949
949
  else None
950
950
  )
951
951
 
@@ -472,6 +472,73 @@ class TimeInputSerde:
472
472
  return time.strftime(v, "%H:%M")
473
473
 
474
474
 
475
+ def _validate_date_value(
476
+ current_value: DateWidgetReturn,
477
+ parsed_values: _DateInputValues,
478
+ has_explicit_bounds: bool,
479
+ ) -> tuple[DateWidgetReturn, bool]:
480
+ """Validate current value against min/max bounds and reset if needed.
481
+
482
+ Only validates when has_explicit_bounds is True (user provided min_value or max_value).
483
+ This avoids incorrectly resetting values against computed default bounds.
484
+
485
+ Parameters
486
+ ----------
487
+ current_value : DateWidgetReturn
488
+ The current value of the date input widget. Can be a single date, a tuple of
489
+ dates (for range mode), or None.
490
+ parsed_values : _DateInputValues
491
+ Parsed configuration containing min, max, default value, and whether the widget
492
+ is in range mode.
493
+ has_explicit_bounds : bool
494
+ Whether the user explicitly provided min_value or max_value. If False, validation
495
+ is skipped to avoid resetting against computed default bounds.
496
+
497
+ Returns
498
+ -------
499
+ tuple[DateWidgetReturn, bool]
500
+ A tuple of (validated_value, was_reset) where validated_value is either the
501
+ original value (if valid) or the default value (if reset was needed), and
502
+ was_reset indicates whether a reset occurred.
503
+ """
504
+ value_needs_reset = False
505
+
506
+ if current_value is None or not has_explicit_bounds:
507
+ return current_value, value_needs_reset
508
+
509
+ # For range inputs, current_value is a tuple; for single inputs, it's a date
510
+ if (
511
+ parsed_values.is_range
512
+ and isinstance(current_value, tuple)
513
+ and len(current_value) > 0
514
+ ):
515
+ # For range mode, check if any date in the tuple is outside bounds.
516
+ # Cast to tuple[date, ...] to satisfy the type checker after the length check.
517
+ non_empty_value = cast("tuple[date, ...]", current_value)
518
+ start_date = non_empty_value[0]
519
+ end_date = non_empty_value[-1] if len(non_empty_value) > 1 else start_date
520
+ if start_date < parsed_values.min or end_date > parsed_values.max:
521
+ value_needs_reset = True
522
+ elif not parsed_values.is_range and isinstance(current_value, date):
523
+ # For single date mode
524
+ if current_value < parsed_values.min or current_value > parsed_values.max:
525
+ value_needs_reset = True
526
+ else:
527
+ # Type mismatch: widget mode doesn't match current value type (e.g., range mode
528
+ # with a single date value or single mode with a tuple). Reset to match the mode.
529
+ value_needs_reset = True
530
+
531
+ if not value_needs_reset:
532
+ return current_value, value_needs_reset
533
+
534
+ # Reset to the default value from parsed_values
535
+ if parsed_values.value is None or len(parsed_values.value) == 0:
536
+ return (() if parsed_values.is_range else None), True
537
+ if not parsed_values.is_range:
538
+ return parsed_values.value[0], True
539
+ return cast("DateWidgetReturn", tuple(parsed_values.value)), True
540
+
541
+
475
542
  @dataclass
476
543
  class DateInputSerde:
477
544
  value: _DateInputValues
@@ -1467,7 +1534,7 @@ class TimeWidgetsMixin:
1467
1534
  parsed_min_date = parse_date_deterministic_for_id(min_value)
1468
1535
  parsed_max_date = parse_date_deterministic_for_id(max_value)
1469
1536
 
1470
- parsed: str | None | list[str | None]
1537
+ parsed: str | list[str | None] | None
1471
1538
  if value == "today":
1472
1539
  parsed = None
1473
1540
  elif isinstance(value, Sequence):
@@ -1480,12 +1547,10 @@ class TimeWidgetsMixin:
1480
1547
  element_id = compute_and_register_element_id(
1481
1548
  "date_input",
1482
1549
  user_key=key,
1483
- # Ensure stable ID when key is provided; explicitly whitelist parameters
1484
- # that might invalidate the current widget state.
1485
- # format should be supported. However, there is a bug in baseweb where
1486
- # changing the format dynamically leads to a wrongly formatted date.
1487
- # So, we whitelist it for now until we migrate this away from baseweb.
1488
- key_as_main_identity={"min_value", "max_value", "format"},
1550
+ # Ensure stable ID when key is provided. Only format is whitelisted because
1551
+ # there is a bug in baseweb where changing the format dynamically leads to
1552
+ # a wrongly formatted date. min_value and max_value support dynamic changes.
1553
+ key_as_main_identity={"format"},
1489
1554
  dg=self.dg,
1490
1555
  label=label,
1491
1556
  value=parsed,
@@ -1508,6 +1573,9 @@ class TimeWidgetsMixin:
1508
1573
  max_value=max_value,
1509
1574
  )
1510
1575
 
1576
+ # Track if user explicitly set bounds (before del)
1577
+ has_explicit_bounds = min_value is not None or max_value is not None
1578
+
1511
1579
  if value == "today":
1512
1580
  # We need to know if this is a single or range date_input, but don't have
1513
1581
  # a default value, so we check if session_state can tell us.
@@ -1564,15 +1632,28 @@ class TimeWidgetsMixin:
1564
1632
  value_type="string_array_value",
1565
1633
  )
1566
1634
 
1567
- if widget_state.value_changed:
1568
- date_input_proto.value[:] = serde.serialize(widget_state.value)
1635
+ # Validate the current value against the new min/max bounds.
1636
+ # Only validate when user explicitly provided min_value or max_value.
1637
+ current_value, value_needs_reset = _validate_date_value(
1638
+ widget_state.value, parsed_values, has_explicit_bounds
1639
+ )
1640
+
1641
+ # Reset if needed.
1642
+ if value_needs_reset and key is not None:
1643
+ # Update session_state so subsequent accesses in this run
1644
+ # return the corrected value. Use reset_state_value to avoid
1645
+ # the "cannot be modified after widget instantiated" error.
1646
+ get_session_state().reset_state_value(key, current_value)
1647
+
1648
+ if value_needs_reset or widget_state.value_changed:
1649
+ date_input_proto.value[:] = serde.serialize(current_value)
1569
1650
  date_input_proto.set_value = True
1570
1651
 
1571
1652
  validate_width(width)
1572
1653
  layout_config = LayoutConfig(width=width)
1573
1654
 
1574
1655
  self.dg._enqueue("date_input", date_input_proto, layout_config=layout_config)
1575
- return widget_state.value
1656
+ return current_value
1576
1657
 
1577
1658
  @property
1578
1659
  def dg(self) -> DeltaGenerator:
@@ -56,7 +56,7 @@ HELP_TYPES: Final[tuple[type[Any], ...]] = (
56
56
  )
57
57
 
58
58
 
59
- class StreamingOutput(list[Any]):
59
+ class StreamingOutput(list[Any]): # noqa: FURB189
60
60
  pass
61
61
 
62
62
 
streamlit/env_util.py CHANGED
@@ -46,7 +46,7 @@ def is_repl() -> bool:
46
46
 
47
47
  # <stdin> is what the basic Python REPL calls the root frame's
48
48
  # filename, and <string> is what iPython sometimes calls it.
49
- return filename in ("<stdin>", "<string>")
49
+ return filename in {"<stdin>", "<string>"}
50
50
 
51
51
 
52
52
  def is_executable_in_path(name: str) -> bool:
streamlit/errors.py CHANGED
@@ -34,14 +34,10 @@ class Error(Exception):
34
34
  code.
35
35
  """
36
36
 
37
- pass
38
-
39
37
 
40
38
  class CustomComponentError(Error):
41
39
  """Exceptions thrown in the custom components code path."""
42
40
 
43
- pass
44
-
45
41
 
46
42
  class StreamlitComponentRegistryError(Error):
47
43
  """Exceptions raised while discovering or registering Streamlit components.
@@ -51,8 +47,6 @@ class StreamlitComponentRegistryError(Error):
51
47
  registry.
52
48
  """
53
49
 
54
- pass
55
-
56
50
 
57
51
  class DeprecationError(Error):
58
52
  pass
@@ -63,16 +57,12 @@ class FragmentStorageKeyError(Error, KeyError):
63
57
  operation.
64
58
  """
65
59
 
66
- pass
67
-
68
60
 
69
61
  class FragmentHandledException(Exception): # noqa: N818
70
62
  """An exception that is raised by the fragment
71
63
  when it has handled the exception itself.
72
64
  """
73
65
 
74
- pass
75
-
76
66
 
77
67
  class NoStaticFiles(Error): # noqa: N818
78
68
  pass
@@ -89,14 +79,10 @@ class MarkdownFormattedException(Error): # noqa: N818
89
79
  nicely formatted on the frontend.
90
80
  """
91
81
 
92
- pass
93
-
94
82
 
95
83
  class StreamlitMaxRetriesError(Error):
96
84
  """An exception raised when a file or folder cannot be accessed after multiple retries."""
97
85
 
98
- pass
99
-
100
86
 
101
87
  class StreamlitAPIException(MarkdownFormattedException):
102
88
  """Base class for Streamlit API exceptions.
@@ -911,7 +911,6 @@ class AppSession:
911
911
  The actual handler here is a noop
912
912
 
913
913
  """
914
- pass
915
914
 
916
915
  def _handle_set_run_on_save_request(self, new_value: bool) -> None:
917
916
  """Change our run_on_save flag to the given value.
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- import pickle
19
+ import pickle # noqa: S403
20
20
  import threading
21
21
  from typing import (
22
22
  TYPE_CHECKING,
@@ -654,13 +654,13 @@ class CacheDataAPI:
654
654
  else:
655
655
  persist_string = persist
656
656
 
657
- if persist_string not in (None, "disk"):
657
+ if persist_string not in {None, "disk"}:
658
658
  # We'll eventually have more persist options.
659
659
  raise StreamlitAPIException(
660
660
  f"Unsupported persist option '{persist}'. Valid values are 'disk' or None."
661
661
  )
662
662
 
663
- if scope not in ("global", "session"):
663
+ if scope not in {"global", "session"}:
664
664
  raise StreamlitAPIException(
665
665
  f"Unsupported scope option '{scope}'. Valid values are 'global' or 'session'."
666
666
  )
@@ -141,5 +141,3 @@ class UnserializableReturnValueError(MarkdownFormattedException, Generic[R]):
141
141
 
142
142
  class UnevaluatedDataFrameError(StreamlitAPIException):
143
143
  """Used to display a message about uncollected dataframe being used."""
144
-
145
- pass
@@ -592,7 +592,7 @@ class CacheResourceAPI:
592
592
 
593
593
  """
594
594
 
595
- if scope not in ("global", "session"):
595
+ if scope not in {"global", "session"}:
596
596
  raise StreamlitAPIException(
597
597
  f"Unsupported scope option '{scope}'. Valid values are 'global' or 'session'."
598
598
  )
@@ -592,10 +592,10 @@ def _get_positional_arg_name(func: Callable[..., Any], arg_index: int) -> str |
592
592
  if arg_index >= len(params):
593
593
  return None
594
594
 
595
- if params[arg_index].kind in (
595
+ if params[arg_index].kind in {
596
596
  inspect.Parameter.POSITIONAL_OR_KEYWORD,
597
597
  inspect.Parameter.POSITIONAL_ONLY,
598
- ):
598
+ }:
599
599
  return params[arg_index].name
600
600
 
601
601
  return None
@@ -25,7 +25,7 @@ import hashlib
25
25
  import inspect
26
26
  import io
27
27
  import os
28
- import pickle
28
+ import pickle # noqa: S403
29
29
  import sys
30
30
  import tempfile
31
31
  import threading
@@ -653,5 +653,3 @@ class _CacheFuncHasher:
653
653
 
654
654
  class NoResult:
655
655
  """Placeholder class for return values when None is meaningful."""
656
-
657
- pass
@@ -156,7 +156,6 @@ class CacheStorage(Protocol):
156
156
  to close open resources, before we delete the storage instance.
157
157
  e.g. close the database connection etc.
158
158
  """
159
- pass
160
159
 
161
160
 
162
161
  class CacheStorageManager(Protocol):
@@ -235,5 +234,3 @@ class CacheStorageManager(Protocol):
235
234
  -----
236
235
  Threading: Should be safe to call from any thread.
237
236
  """
238
-
239
- pass
@@ -99,7 +99,7 @@ def _create_connection(
99
99
  )
100
100
 
101
101
  scope = connection_class.scope()
102
- if scope not in ("global", "session"):
102
+ if scope not in {"global", "session"}:
103
103
  raise StreamlitAPIException(
104
104
  f"Connection class {connection_class} has scope '{scope}'. Valid values "
105
105
  "are 'global' or 'session'."
@@ -345,7 +345,7 @@ class Runtime:
345
345
  async_objs = self._get_async_objs()
346
346
 
347
347
  def stop_on_eventloop() -> None:
348
- if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
348
+ if self._state in {RuntimeState.STOPPING, RuntimeState.STOPPED}:
349
349
  return
350
350
 
351
351
  _LOGGER.debug("Runtime stopping...")
@@ -411,7 +411,7 @@ class Runtime:
411
411
  "This should never happen."
412
412
  )
413
413
 
414
- if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
414
+ if self._state in {RuntimeState.STOPPING, RuntimeState.STOPPED}:
415
415
  raise RuntimeStoppedError(f"Can't connect_session (state={self._state})")
416
416
 
417
417
  session_id = self._session_mgr.connect_session(
@@ -510,7 +510,7 @@ class Runtime:
510
510
  -----
511
511
  Threading: UNSAFE. Must be called on the eventloop thread.
512
512
  """
513
- if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
513
+ if self._state in {RuntimeState.STOPPING, RuntimeState.STOPPED}:
514
514
  raise RuntimeStoppedError(f"Can't handle_backmsg (state={self._state})")
515
515
 
516
516
  session_info = self._session_mgr.get_active_session_info(session_id)
@@ -538,7 +538,7 @@ class Runtime:
538
538
  -----
539
539
  Threading: UNSAFE. Must be called on the eventloop thread.
540
540
  """
541
- if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
541
+ if self._state in {RuntimeState.STOPPING, RuntimeState.STOPPED}:
542
542
  raise RuntimeStoppedError(
543
543
  f"Can't handle_backmsg_deserialization_exception (state={self._state})"
544
544
  )
@@ -555,11 +555,11 @@ class Runtime:
555
555
 
556
556
  @property
557
557
  async def is_ready_for_browser_connection(self) -> tuple[bool, str]:
558
- if self._state not in (
558
+ if self._state not in {
559
559
  RuntimeState.INITIAL,
560
560
  RuntimeState.STOPPING,
561
561
  RuntimeState.STOPPED,
562
- ):
562
+ }:
563
563
  return True, "ok"
564
564
 
565
565
  return False, "unavailable"
@@ -22,14 +22,10 @@ from streamlit.util import repr_
22
22
  class ScriptControlException(BaseException): # NOSONAR
23
23
  """Base exception for ScriptRunner."""
24
24
 
25
- pass
26
-
27
25
 
28
26
  class StopException(ScriptControlException):
29
27
  """Silently stop the execution of the user's script."""
30
28
 
31
- pass
32
-
33
29
 
34
30
  class RerunException(ScriptControlException):
35
31
  """Silently stop and rerun the user's script."""