streamlit-nightly 1.44.2.dev20250427__py3-none-any.whl → 1.45.1.dev20250429__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 (146) hide show
  1. streamlit/auth_util.py +1 -1
  2. streamlit/commands/experimental_query_params.py +1 -1
  3. streamlit/components/v1/custom_component.py +1 -1
  4. streamlit/config.py +18 -4
  5. streamlit/delta_generator.py +0 -3
  6. streamlit/deprecation_util.py +1 -1
  7. streamlit/elements/arrow.py +6 -6
  8. streamlit/elements/code.py +15 -0
  9. streamlit/elements/deck_gl_json_chart.py +4 -4
  10. streamlit/elements/dialog_decorator.py +0 -1
  11. streamlit/elements/doc_string.py +18 -26
  12. streamlit/elements/image.py +8 -9
  13. streamlit/elements/lib/built_in_chart_utils.py +8 -8
  14. streamlit/elements/lib/column_config_utils.py +1 -1
  15. streamlit/elements/lib/column_types.py +3 -0
  16. streamlit/elements/lib/image_utils.py +25 -26
  17. streamlit/elements/lib/pandas_styler_utils.py +7 -7
  18. streamlit/elements/map.py +2 -2
  19. streamlit/elements/plotly_chart.py +5 -5
  20. streamlit/elements/vega_charts.py +8 -8
  21. streamlit/elements/widgets/audio_input.py +1 -1
  22. streamlit/elements/widgets/button.py +7 -6
  23. streamlit/elements/widgets/button_group.py +5 -11
  24. streamlit/elements/widgets/camera_input.py +1 -1
  25. streamlit/elements/widgets/chat.py +1 -3
  26. streamlit/elements/widgets/checkbox.py +1 -1
  27. streamlit/elements/widgets/color_picker.py +1 -1
  28. streamlit/elements/widgets/data_editor.py +1 -1
  29. streamlit/elements/widgets/file_uploader.py +6 -7
  30. streamlit/elements/widgets/multiselect.py +1 -5
  31. streamlit/elements/widgets/number_input.py +10 -13
  32. streamlit/elements/widgets/radio.py +1 -5
  33. streamlit/elements/widgets/select_slider.py +3 -7
  34. streamlit/elements/widgets/selectbox.py +1 -5
  35. streamlit/elements/widgets/slider.py +2 -2
  36. streamlit/elements/widgets/text_widgets.py +2 -2
  37. streamlit/elements/widgets/time_widgets.py +2 -6
  38. streamlit/error_util.py +1 -1
  39. streamlit/external/langchain/streamlit_callback_handler.py +4 -0
  40. streamlit/git_util.py +2 -2
  41. streamlit/hello/dataframe_demo.py +2 -2
  42. streamlit/logger.py +5 -5
  43. streamlit/navigation/page.py +1 -1
  44. streamlit/proto/Code_pb2.py +4 -3
  45. streamlit/proto/Code_pb2.pyi +9 -1
  46. streamlit/runtime/app_session.py +9 -9
  47. streamlit/runtime/caching/cached_message_replay.py +1 -1
  48. streamlit/runtime/caching/hashing.py +3 -4
  49. streamlit/runtime/caching/legacy_cache_api.py +1 -1
  50. streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
  51. streamlit/runtime/caching/storage/local_disk_cache_storage.py +2 -2
  52. streamlit/runtime/connection_factory.py +8 -8
  53. streamlit/runtime/context.py +1 -1
  54. streamlit/runtime/forward_msg_queue.py +10 -10
  55. streamlit/runtime/metrics_util.py +2 -2
  56. streamlit/runtime/pages_manager.py +1 -3
  57. streamlit/runtime/runtime_util.py +1 -1
  58. streamlit/runtime/scriptrunner/exec_code.py +1 -1
  59. streamlit/runtime/scriptrunner/magic.py +3 -4
  60. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  61. streamlit/runtime/state/common.py +2 -2
  62. streamlit/runtime/state/session_state.py +2 -2
  63. streamlit/static/index.html +1 -1
  64. streamlit/static/static/js/{ErrorOutline.esm.BGxEEkBO.js → ErrorOutline.esm.BJh3F07v.js} +1 -1
  65. streamlit/static/static/js/{FileDownload.esm.BIvOCWXm.js → FileDownload.esm.BpUJskrZ.js} +1 -1
  66. streamlit/static/static/js/{FileHelper.CJg2rGQf.js → FileHelper.DKXMFthp.js} +1 -1
  67. streamlit/static/static/js/{FormClearHelper.BKO5MjJ1.js → FormClearHelper.CcbGU8qM.js} +1 -1
  68. streamlit/static/static/js/{Hooks.Ch4fyM-d.js → Hooks.CyZIh6nK.js} +1 -1
  69. streamlit/static/static/js/{InputInstructions.BVG0uTsn.js → InputInstructions.nbkV1h_d.js} +1 -1
  70. streamlit/static/static/js/{ProgressBar.qtOeZiGm.js → ProgressBar.DeCaMWV9.js} +1 -1
  71. streamlit/static/static/js/{RenderInPortalIfExists.BNrfjgR-.js → RenderInPortalIfExists.D_SwWwav.js} +1 -1
  72. streamlit/static/static/js/{Toolbar.DLYoM1Wd.js → Toolbar.BAN-49vk.js} +1 -1
  73. streamlit/static/static/js/{base-input.CMZL3Njp.js → base-input.BGFZMByD.js} +1 -1
  74. streamlit/static/static/js/{checkbox.Bg2c6brb.js → checkbox.B_-BK4qi.js} +1 -1
  75. streamlit/static/static/js/{createSuper.feapqlxC.js → createSuper.BxyEvip2.js} +1 -1
  76. streamlit/static/static/js/{data-grid-overlay-editor.CPfW2LFj.js → data-grid-overlay-editor.DmJscfNY.js} +1 -1
  77. streamlit/static/static/js/{downloader.DzXny7Ld.js → downloader.Cv_h08Sg.js} +1 -1
  78. streamlit/static/static/js/{es6.0m8Dphx5.js → es6.BEoJ6t5B.js} +2 -2
  79. streamlit/static/static/js/{iframeResizer.contentWindow.cmKtyqx-.js → iframeResizer.contentWindow.DnBVl60m.js} +1 -1
  80. streamlit/static/static/js/{index.BOLpjodc.js → index.0QGnttRw.js} +1 -1
  81. streamlit/static/static/js/{index.cslPh4fD.js → index.7LZxcVw4.js} +1 -1
  82. streamlit/static/static/js/{index.C-FM6HWK.js → index.BBlDwZ3d.js} +5 -5
  83. streamlit/static/static/js/{index.CrKlAaBP.js → index.BCUsUBov.js} +1 -1
  84. streamlit/static/static/js/{index.GK7AGRO0.js → index.BDoHOUEu.js} +1 -1
  85. streamlit/static/static/js/{index.NE3kJsno.js → index.BJrY61fW.js} +1 -1
  86. streamlit/static/static/js/{index.9ahYhn9L.js → index.Bk2dieuB.js} +1 -1
  87. streamlit/static/static/js/{index.CPBpuLNa.js → index.BlpcPmc8.js} +1 -1
  88. streamlit/static/static/js/{index.DFJR7tFk.js → index.Bnv2GQ1f.js} +1 -1
  89. streamlit/static/static/js/{index.CeVeyA9j.js → index.BooesbgI.js} +1 -1
  90. streamlit/static/static/js/{index.D75DmXmJ.js → index.Bp2P-ne7.js} +1 -1
  91. streamlit/static/static/js/{index.Dj9pydGj.js → index.BpqJCHW4.js} +1 -1
  92. streamlit/static/static/js/{index.qG6NX4j3.js → index.BsajPDiD.js} +1 -1
  93. streamlit/static/static/js/{index.T6zTT7so.js → index.BzbL2a8R.js} +1 -1
  94. streamlit/static/static/js/{index.B1SRlRQI.js → index.C7tk-BaI.js} +1 -1
  95. streamlit/static/static/js/{index.Cz-wSZKK.js → index.CA2NGDaW.js} +1 -1
  96. streamlit/static/static/js/{index.CoEs3Tyr.js → index.CRdGuqu3.js} +1 -1
  97. streamlit/static/static/js/{index.DXwLRPNi.js → index.CT0nwqsw.js} +1 -1
  98. streamlit/static/static/js/{index.l2ZjmqZa.js → index.CWwqcOXB.js} +1 -1
  99. streamlit/static/static/js/{index.C9SZjgyE.js → index.CeEGQX9i.js} +1 -1
  100. streamlit/static/static/js/{index.BvuI_MOQ.js → index.CmBGzoYB.js} +1 -1
  101. streamlit/static/static/js/{index.CaDlXCxB.js → index.CzaH4EJh.js} +1 -1
  102. streamlit/static/static/js/{index.C51U-ytW.js → index.D39reA1n.js} +1 -1
  103. streamlit/static/static/js/{index.BQdNrQcI.js → index.DKS3g4Ws.js} +1 -1
  104. streamlit/static/static/js/{index.DYNcgXHh.js → index.D_Z8_2ei.js} +1 -1
  105. streamlit/static/static/js/{index.Dc-nqnmm.js → index.DbVBJOze.js} +1 -1
  106. streamlit/static/static/js/{index.BkUl8Uwz.js → index.DewKSDBK.js} +39 -39
  107. streamlit/static/static/js/{index.Bml5MH48.js → index.DipBpxzK.js} +1 -1
  108. streamlit/static/static/js/{index.lC8LhcmX.js → index.DoNPe-YW.js} +1 -1
  109. streamlit/static/static/js/{index.C4ApZ9VX.js → index.DwTevPv_.js} +1 -1
  110. streamlit/static/static/js/{index.8zBbwiSq.js → index.Dw_iEQ1s.js} +1 -1
  111. streamlit/static/static/js/{index.CaUiwEHb.js → index.Dz3G_3mZ.js} +1 -1
  112. streamlit/static/static/js/{index.45HlJMvy.js → index.WP3FKPhV.js} +1 -1
  113. streamlit/static/static/js/{index.lmhSYtGE.js → index.iV6t3ri-.js} +1 -1
  114. streamlit/static/static/js/{index.DZEEja3T.js → index.t3xwOrU9.js} +1 -1
  115. streamlit/static/static/js/{index.Cz5dPfTR.js → index.tbMYLMrS.js} +1 -1
  116. streamlit/static/static/js/index.xsH4HHeE.js +6 -0
  117. streamlit/static/static/js/{index.Br4Vls5z.js → index.z-3XVs6d.js} +1 -1
  118. streamlit/static/static/js/{input.AzemsQR7.js → input.B2MDikVk.js} +1 -1
  119. streamlit/static/static/js/{memory.BNnDm5qx.js → memory.BCb625DQ.js} +1 -1
  120. streamlit/static/static/js/{mergeWith.CnAe-pY8.js → mergeWith.COIRyAFl.js} +1 -1
  121. streamlit/static/static/js/{number-overlay-editor.CoO3Xzpl.js → number-overlay-editor.2CkzyF3w.js} +1 -1
  122. streamlit/static/static/js/{possibleConstructorReturn.-4k2karl.js → possibleConstructorReturn.3T2FklLD.js} +1 -1
  123. streamlit/static/static/js/{sandbox.B_lhrPSt.js → sandbox.Cc6yBPvx.js} +1 -1
  124. streamlit/static/static/js/{textarea.BXroYkeL.js → textarea.C7jOKez6.js} +1 -1
  125. streamlit/static/static/js/{timepicker.mhMg0du0.js → timepicker.BjMKxgZK.js} +1 -1
  126. streamlit/static/static/js/{toConsumableArray.xDE9XBoI.js → toConsumableArray.BQ7m3eYw.js} +1 -1
  127. streamlit/static/static/js/{uniqueId.DPZFapqq.js → uniqueId.CJ7dn8nU.js} +1 -1
  128. streamlit/static/static/js/{useBasicWidgetState.DWXpUITX.js → useBasicWidgetState.QdMR1Kj8.js} +1 -1
  129. streamlit/static/static/js/{useOnInputChange.FMGxl8Ty.js → useOnInputChange.DppkR64F.js} +1 -1
  130. streamlit/static/static/js/{withFullScreenWrapper.cCJx5Did.js → withFullScreenWrapper.C2Ah-iZc.js} +1 -1
  131. streamlit/testing/v1/app_test.py +2 -2
  132. streamlit/testing/v1/element_tree.py +7 -7
  133. streamlit/type_util.py +2 -2
  134. streamlit/user_info.py +3 -3
  135. streamlit/watcher/event_based_path_watcher.py +14 -0
  136. streamlit/watcher/local_sources_watcher.py +43 -7
  137. streamlit/web/bootstrap.py +3 -3
  138. streamlit/web/cli.py +7 -7
  139. streamlit/web/server/media_file_handler.py +2 -2
  140. {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/METADATA +1 -1
  141. {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/RECORD +145 -145
  142. {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/WHEEL +1 -1
  143. streamlit/static/static/js/index.t--hEgTQ.js +0 -6
  144. {streamlit_nightly-1.44.2.dev20250427.data → streamlit_nightly-1.45.1.dev20250429.data}/scripts/streamlit.cmd +0 -0
  145. {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/entry_points.txt +0 -0
  146. {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/top_level.txt +0 -0
@@ -107,11 +107,7 @@ class _MultiSelectSerde(Generic[T]):
107
107
  indices = check_and_convert_to_indices(self.options, value)
108
108
  return indices if indices is not None else []
109
109
 
110
- def deserialize(
111
- self,
112
- ui_value: list[int] | None,
113
- widget_id: str = "",
114
- ) -> list[T]:
110
+ def deserialize(self, ui_value: list[int] | None) -> list[T]:
115
111
  current_value: list[int] = (
116
112
  ui_value if ui_value is not None else self.default_value
117
113
  )
@@ -145,8 +141,8 @@ class _SingleSelectSerde(Generic[T]):
145
141
  _value = [value] if value is not None else []
146
142
  return self.multiselect_serde.serialize(_value)
147
143
 
148
- def deserialize(self, ui_value: list[int] | None, widget_id: str = "") -> T | None:
149
- deserialized = self.multiselect_serde.deserialize(ui_value, widget_id)
144
+ def deserialize(self, ui_value: list[int] | None) -> T | None:
145
+ deserialized = self.multiselect_serde.deserialize(ui_value)
150
146
 
151
147
  if len(deserialized) == 0:
152
148
  return None
@@ -182,10 +178,8 @@ class ButtonGroupSerde(Generic[T]):
182
178
  def serialize(self, value: T | list[T] | None) -> list[int]:
183
179
  return self.serde.serialize(cast("Any", value))
184
180
 
185
- def deserialize(
186
- self, ui_value: list[int] | None, widget_id: str = ""
187
- ) -> list[T] | T | None:
188
- return self.serde.deserialize(ui_value, widget_id)
181
+ def deserialize(self, ui_value: list[int] | None) -> list[T] | T | None:
182
+ return self.serde.deserialize(ui_value)
189
183
 
190
184
 
191
185
  def get_mapped_options(
@@ -73,7 +73,7 @@ class CameraInputSerde:
73
73
  return state_proto
74
74
 
75
75
  def deserialize(
76
- self, ui_value: FileUploaderStateProto | None, widget_id: str
76
+ self, ui_value: FileUploaderStateProto | None
77
77
  ) -> SomeUploadedSnapshotFile:
78
78
  upload_files = _get_upload_files(ui_value)
79
79
  if len(upload_files) == 0:
@@ -196,9 +196,7 @@ class ChatInputSerde:
196
196
  allowed_types: Sequence[str] | None = None
197
197
 
198
198
  def deserialize(
199
- self,
200
- ui_value: ChatInputValueProto | None,
201
- widget_id: str = "",
199
+ self, ui_value: ChatInputValueProto | None
202
200
  ) -> str | ChatInputValue | None:
203
201
  if ui_value is None or not ui_value.HasField("data"):
204
202
  return None
@@ -51,7 +51,7 @@ class CheckboxSerde:
51
51
  def serialize(self, v: bool) -> bool:
52
52
  return bool(v)
53
53
 
54
- def deserialize(self, ui_value: bool | None, widget_id: str = "") -> bool:
54
+ def deserialize(self, ui_value: bool | None) -> bool:
55
55
  return bool(ui_value if ui_value is not None else self.value)
56
56
 
57
57
 
@@ -53,7 +53,7 @@ class ColorPickerSerde:
53
53
  def serialize(self, v: str) -> str:
54
54
  return str(v)
55
55
 
56
- def deserialize(self, ui_value: str | None, widget_id: str = "") -> str:
56
+ def deserialize(self, ui_value: str | None) -> str:
57
57
  return str(ui_value if ui_value is not None else self.value)
58
58
 
59
59
 
@@ -137,7 +137,7 @@ class EditingState(TypedDict, total=False):
137
137
  class DataEditorSerde:
138
138
  """DataEditorSerde is used to serialize and deserialize the data editor state."""
139
139
 
140
- def deserialize(self, ui_value: str | None, widget_id: str = "") -> EditingState:
140
+ def deserialize(self, ui_value: str | None) -> EditingState:
141
141
  data_editor_state: EditingState = (
142
142
  {
143
143
  "edited_rows": {},
@@ -102,9 +102,7 @@ class FileUploaderSerde:
102
102
  accept_multiple_files: bool
103
103
  allowed_types: Sequence[str] | None = None
104
104
 
105
- def deserialize(
106
- self, ui_value: FileUploaderStateProto | None, widget_id: str
107
- ) -> SomeUploadedFiles:
105
+ def deserialize(self, ui_value: FileUploaderStateProto | None) -> SomeUploadedFiles:
108
106
  upload_files = _get_upload_files(ui_value)
109
107
 
110
108
  for file in upload_files:
@@ -435,13 +433,14 @@ class FileUploaderMixin:
435
433
  help=help,
436
434
  )
437
435
 
438
- if type:
439
- type = normalize_upload_file_type(type)
436
+ normalized_type = normalize_upload_file_type(type) if type else None
440
437
 
441
438
  file_uploader_proto = FileUploaderProto()
442
439
  file_uploader_proto.id = element_id
443
440
  file_uploader_proto.label = label
444
- file_uploader_proto.type[:] = type if type is not None else []
441
+ file_uploader_proto.type[:] = (
442
+ normalized_type if normalized_type is not None else []
443
+ )
445
444
  file_uploader_proto.max_upload_size_mb = config.get_option(
446
445
  "server.maxUploadSize"
447
446
  )
@@ -455,7 +454,7 @@ class FileUploaderMixin:
455
454
  if help is not None:
456
455
  file_uploader_proto.help = dedent(help)
457
456
 
458
- serde = FileUploaderSerde(accept_multiple_files, allowed_types=type)
457
+ serde = FileUploaderSerde(accept_multiple_files, allowed_types=normalized_type)
459
458
 
460
459
  # FileUploader's widget value is a list of file IDs
461
460
  # representing the current set of files that this uploader should
@@ -116,11 +116,7 @@ class MultiSelectSerde(Generic[T]):
116
116
  values.append(cast("str", v))
117
117
  return values
118
118
 
119
- def deserialize(
120
- self,
121
- ui_value: list[str] | None,
122
- widget_id: str = "",
123
- ) -> list[T | str] | list[T]:
119
+ def deserialize(self, ui_value: list[str] | None) -> list[T | str] | list[T]:
124
120
  if ui_value is None:
125
121
  return [self.options[i] for i in self.default_options_indices]
126
122
 
@@ -70,9 +70,7 @@ class NumberInputSerde:
70
70
  def serialize(self, v: Number | None) -> Number | None:
71
71
  return v
72
72
 
73
- def deserialize(
74
- self, ui_value: Number | None, widget_id: str = ""
75
- ) -> Number | None:
73
+ def deserialize(self, ui_value: Number | None) -> Number | None:
76
74
  val: Number | None = ui_value if ui_value is not None else self.value
77
75
 
78
76
  if val is not None and self.data_type == NumberInputProto.INT:
@@ -445,32 +443,32 @@ class NumberInputMixin:
445
443
  # Otherwise, defaults to float:
446
444
  float_value = True
447
445
 
448
- if format is None:
449
- format = "%d" if int_value else "%0.2f"
446
+ # Use default format depending on value type if format was not provided:
447
+ number_format = ("%d" if int_value else "%0.2f") if format is None else format
450
448
 
451
449
  # Warn user if they format an int type as a float or vice versa.
452
- if format in ["%d", "%u", "%i"] and float_value:
450
+ if number_format in ["%d", "%u", "%i"] and float_value:
453
451
  import streamlit as st
454
452
 
455
453
  st.warning(
456
454
  "Warning: NumberInput value below has type float,"
457
- f" but format {format} displays as integer."
455
+ f" but format {number_format} displays as integer."
458
456
  )
459
- elif format[-1] == "f" and int_value:
457
+ elif number_format[-1] == "f" and int_value:
460
458
  import streamlit as st
461
459
 
462
460
  st.warning(
463
461
  "Warning: NumberInput value below has type int so is"
464
- f" displayed as int despite format string {format}."
462
+ f" displayed as int despite format string {number_format}."
465
463
  )
466
464
 
467
465
  if step is None:
468
466
  step = 1 if int_value else 0.01
469
467
 
470
468
  try:
471
- float(format % 2)
469
+ float(number_format % 2)
472
470
  except (TypeError, ValueError):
473
- raise StreamlitInvalidNumberFormatError(format)
471
+ raise StreamlitInvalidNumberFormatError(number_format)
474
472
 
475
473
 
476
474
  # Ensure that the value matches arguments' types.
@@ -549,8 +547,7 @@ class NumberInputMixin:
549
547
  if step is not None:
550
548
  number_input_proto.step = step
551
549
 
552
- if format is not None:
553
- number_input_proto.format = format
550
+ number_input_proto.format = number_format
554
551
 
555
552
  if icon is not None:
556
553
  number_input_proto.icon = validate_icon_or_emoji(icon)
@@ -66,11 +66,7 @@ class RadioSerde(Generic[T]):
66
66
 
67
67
  return 0 if len(self.options) == 0 else index_(self.options, v)
68
68
 
69
- def deserialize(
70
- self,
71
- ui_value: int | None,
72
- widget_id: str = "",
73
- ) -> T | None:
69
+ def deserialize(self, ui_value: int | None) -> T | None:
74
70
  idx = ui_value if ui_value is not None else self.index
75
71
 
76
72
  return (
@@ -78,11 +78,7 @@ class SelectSliderSerde(Generic[T]):
78
78
  def serialize(self, v: object) -> list[int]:
79
79
  return self._as_index_list(v)
80
80
 
81
- def deserialize(
82
- self,
83
- ui_value: list[int] | None,
84
- widget_id: str = "",
85
- ) -> T | tuple[T, T]:
81
+ def deserialize(self, ui_value: list[int] | None) -> T | tuple[T, T]:
86
82
  if not ui_value:
87
83
  # Widget has not been used; fallback to the original value,
88
84
  ui_value = self.value
@@ -128,8 +124,8 @@ class SelectSliderMixin:
128
124
  # The overload-overlap error given by mypy here stems from
129
125
  # the fact that
130
126
  #
131
- # opt:List[object] = [1, 2, "3"]
132
- # select_slider("foo", options=opt, value=[1, 2])
127
+ # > opt:List[object] = [1, 2, "3"]
128
+ # > select_slider("foo", options=opt, value=[1, 2])
133
129
  #
134
130
  # matches both overloads; "opt" matches
135
131
  # OptionsSequence[T] in each case, binding T to object.
@@ -115,11 +115,7 @@ class SelectboxSerde(Generic[T]):
115
115
  # options
116
116
  return cast("str", v)
117
117
 
118
- def deserialize(
119
- self,
120
- ui_value: str | None,
121
- widget_id: str = "",
122
- ) -> T | str | None:
118
+ def deserialize(self, ui_value: str | None) -> T | str | None:
123
119
  # check if the option is pointing to a generic option type T,
124
120
  # otherwise return the option itself
125
121
  if ui_value is None:
@@ -174,7 +174,7 @@ class SliderSerde:
174
174
  )
175
175
  return value
176
176
 
177
- def deserialize(self, ui_value: list[float] | None, widget_id: str = ""):
177
+ def deserialize(self, ui_value: list[float] | None):
178
178
  if ui_value is not None:
179
179
  val = ui_value
180
180
  else:
@@ -705,7 +705,7 @@ class SliderMixin:
705
705
  ) and max_value - min_value < timedelta(days=1):
706
706
  step = timedelta(minutes=15)
707
707
  if format is None:
708
- format = cast("str", DEFAULTS[data_type]["format"])
708
+ format = cast("str", DEFAULTS[data_type]["format"]) # noqa: A001
709
709
 
710
710
  if step == 0:
711
711
  raise StreamlitAPIException(
@@ -54,7 +54,7 @@ if TYPE_CHECKING:
54
54
  class TextInputSerde:
55
55
  value: str | None
56
56
 
57
- def deserialize(self, ui_value: str | None, widget_id: str = "") -> str | None:
57
+ def deserialize(self, ui_value: str | None) -> str | None:
58
58
  return ui_value if ui_value is not None else self.value
59
59
 
60
60
  def serialize(self, v: str | None) -> str | None:
@@ -65,7 +65,7 @@ class TextInputSerde:
65
65
  class TextAreaSerde:
66
66
  value: str | None
67
67
 
68
- def deserialize(self, ui_value: str | None, widget_id: str = "") -> str | None:
68
+ def deserialize(self, ui_value: str | None) -> str | None:
69
69
  return ui_value if ui_value is not None else self.value
70
70
 
71
71
  def serialize(self, v: str | None) -> str | None:
@@ -263,7 +263,7 @@ class _DateInputValues:
263
263
  class TimeInputSerde:
264
264
  value: time | None
265
265
 
266
- def deserialize(self, ui_value: str | None, widget_id: Any = "") -> time | None:
266
+ def deserialize(self, ui_value: str | None) -> time | None:
267
267
  return (
268
268
  datetime.strptime(ui_value, "%H:%M").time()
269
269
  if ui_value is not None
@@ -282,11 +282,7 @@ class TimeInputSerde:
282
282
  class DateInputSerde:
283
283
  value: _DateInputValues
284
284
 
285
- def deserialize(
286
- self,
287
- ui_value: Any,
288
- widget_id: str = "",
289
- ) -> DateWidgetReturn:
285
+ def deserialize(self, ui_value: Any) -> DateWidgetReturn:
290
286
  return_value: Sequence[date] | None
291
287
  if ui_value is not None:
292
288
  return_value = tuple(
streamlit/error_util.py CHANGED
@@ -17,9 +17,9 @@ from __future__ import annotations
17
17
  from typing import Final
18
18
 
19
19
  import streamlit
20
- import streamlit.elements.exception as exception
21
20
  from streamlit import config
22
21
  from streamlit.delta_generator_singletons import get_dg_singleton_instance
22
+ from streamlit.elements import exception
23
23
  from streamlit.logger import get_logger
24
24
 
25
25
  _LOGGER: Final = get_logger(__name__)
@@ -36,6 +36,10 @@ This module is lazy-loaded.
36
36
  # by default.
37
37
  # mypy: disable-error-code="import-not-found, unused-ignore, misc"
38
38
 
39
+ # Deactivate unused argument errors for this file since we need lots of
40
+ # unused arguments to comply with the LangChain callback interface.
41
+ # ruff: noqa: ARG002
42
+
39
43
  from __future__ import annotations
40
44
 
41
45
  import time
streamlit/git_util.py CHANGED
@@ -32,8 +32,8 @@ MIN_GIT_VERSION = (2, 7, 0)
32
32
 
33
33
  class GitRepo:
34
34
  def __init__(self, path):
35
- # If we have a valid repo, git_version will be a tuple of 3+ ints:
36
- # (major, minor, patch, possible_additional_patch_number)
35
+ # If we have a valid repo, git_version will be a tuple
36
+ # of 3+ ints: (major, minor, patch, possible_additional_patch_number)
37
37
  self.git_version: tuple[int, ...] | None = None
38
38
 
39
39
  try:
@@ -23,13 +23,13 @@ from streamlit.hello.utils import show_code
23
23
 
24
24
  def data_frame_demo():
25
25
  @st.cache_data
26
- def get_UN_data():
26
+ def get_un_data():
27
27
  AWS_BUCKET_URL = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
28
28
  df = pd.read_csv(AWS_BUCKET_URL + "/agri.csv.gz")
29
29
  return df.set_index("Region")
30
30
 
31
31
  try:
32
- df = get_UN_data()
32
+ df = get_un_data()
33
33
  countries = st.multiselect(
34
34
  "Choose countries", list(df.index), ["China", "United States of America"]
35
35
  )
streamlit/logger.py CHANGED
@@ -35,15 +35,15 @@ def set_log_level(level: str | int) -> None:
35
35
 
36
36
  if isinstance(level, str):
37
37
  level = level.upper()
38
- if level == "CRITICAL" or level == logging.CRITICAL:
38
+ if level in {"CRITICAL", logging.CRITICAL}:
39
39
  log_level = logging.CRITICAL
40
- elif level == "ERROR" or level == logging.ERROR:
40
+ elif level in {"ERROR", logging.ERROR}:
41
41
  log_level = logging.ERROR
42
- elif level == "WARNING" or level == logging.WARNING:
42
+ elif level in {"WARNING", logging.WARNING}:
43
43
  log_level = logging.WARNING
44
- elif level == "INFO" or level == logging.INFO:
44
+ elif level in {"INFO", logging.INFO}:
45
45
  log_level = logging.INFO
46
- elif level == "DEBUG" or level == logging.DEBUG:
46
+ elif level in {"DEBUG", logging.DEBUG}:
47
47
  log_level = logging.DEBUG
48
48
  else:
49
49
  msg = 'undefined log level "%s"' % level
@@ -27,7 +27,7 @@ from streamlit.util import calc_md5
27
27
 
28
28
 
29
29
  @gather_metrics("Page")
30
- def Page(
30
+ def Page( # noqa: N802
31
31
  page: str | Path | Callable[[], None],
32
32
  *,
33
33
  title: str | None = None,
@@ -12,9 +12,10 @@ from google.protobuf.internal import builder as _builder
12
12
  _sym_db = _symbol_database.Default()
13
13
 
14
14
 
15
+ from streamlit.proto import WidthConfig_pb2 as streamlit_dot_proto_dot_WidthConfig__pb2
15
16
 
16
17
 
17
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1astreamlit/proto/Code.proto\"j\n\x04\x43ode\x12\x11\n\tcode_text\x18\x01 \x01(\t\x12\x10\n\x08language\x18\x02 \x01(\t\x12\x19\n\x11show_line_numbers\x18\x03 \x01(\x08\x12\x12\n\nwrap_lines\x18\x04 \x01(\x08\x12\x0e\n\x06height\x18\x05 \x01(\rB)\n\x1c\x63om.snowflake.apps.streamlitB\tCodeProtob\x06proto3')
18
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1astreamlit/proto/Code.proto\x1a!streamlit/proto/WidthConfig.proto\"\x98\x01\n\x04\x43ode\x12\x11\n\tcode_text\x18\x01 \x01(\t\x12\x10\n\x08language\x18\x02 \x01(\t\x12\x19\n\x11show_line_numbers\x18\x03 \x01(\x08\x12\x12\n\nwrap_lines\x18\x04 \x01(\x08\x12\x0e\n\x06height\x18\x05 \x01(\r\x12,\n\x0cwidth_config\x18\x06 \x01(\x0b\x32\x16.streamlit.WidthConfigB)\n\x1c\x63om.snowflake.apps.streamlitB\tCodeProtob\x06proto3')
18
19
 
19
20
  _globals = globals()
20
21
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,6 +23,6 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.Code_pb2',
22
23
  if not _descriptor._USE_C_DESCRIPTORS:
23
24
  _globals['DESCRIPTOR']._loaded_options = None
24
25
  _globals['DESCRIPTOR']._serialized_options = b'\n\034com.snowflake.apps.streamlitB\tCodeProto'
25
- _globals['_CODE']._serialized_start=30
26
- _globals['_CODE']._serialized_end=136
26
+ _globals['_CODE']._serialized_start=66
27
+ _globals['_CODE']._serialized_end=218
27
28
  # @@protoc_insertion_point(module_scope)
@@ -20,6 +20,7 @@ limitations under the License.
20
20
  import builtins
21
21
  import google.protobuf.descriptor
22
22
  import google.protobuf.message
23
+ import streamlit.proto.WidthConfig_pb2
23
24
  import typing
24
25
 
25
26
  DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@@ -35,12 +36,17 @@ class Code(google.protobuf.message.Message):
35
36
  SHOW_LINE_NUMBERS_FIELD_NUMBER: builtins.int
36
37
  WRAP_LINES_FIELD_NUMBER: builtins.int
37
38
  HEIGHT_FIELD_NUMBER: builtins.int
39
+ WIDTH_CONFIG_FIELD_NUMBER: builtins.int
38
40
  code_text: builtins.str
39
41
  """Content to display."""
40
42
  language: builtins.str
41
43
  show_line_numbers: builtins.bool
42
44
  wrap_lines: builtins.bool
43
45
  height: builtins.int
46
+ @property
47
+ def width_config(self) -> streamlit.proto.WidthConfig_pb2.WidthConfig:
48
+ """Width configuration"""
49
+
44
50
  def __init__(
45
51
  self,
46
52
  *,
@@ -49,7 +55,9 @@ class Code(google.protobuf.message.Message):
49
55
  show_line_numbers: builtins.bool = ...,
50
56
  wrap_lines: builtins.bool = ...,
51
57
  height: builtins.int = ...,
58
+ width_config: streamlit.proto.WidthConfig_pb2.WidthConfig | None = ...,
52
59
  ) -> None: ...
53
- def ClearField(self, field_name: typing.Literal["code_text", b"code_text", "height", b"height", "language", b"language", "show_line_numbers", b"show_line_numbers", "wrap_lines", b"wrap_lines"]) -> None: ...
60
+ def HasField(self, field_name: typing.Literal["width_config", b"width_config"]) -> builtins.bool: ...
61
+ def ClearField(self, field_name: typing.Literal["code_text", b"code_text", "height", b"height", "language", b"language", "show_line_numbers", b"show_line_numbers", "width_config", b"width_config", "wrap_lines", b"wrap_lines"]) -> None: ...
54
62
 
55
63
  global___Code = Code
@@ -615,11 +615,11 @@ class AppSession:
615
615
 
616
616
  self._enqueue_forward_msg(msg)
617
617
 
618
- elif (
619
- event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
620
- or event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR
621
- or event == ScriptRunnerEvent.FRAGMENT_STOPPED_WITH_SUCCESS
622
- ):
618
+ elif event in {
619
+ ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS,
620
+ ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR,
621
+ ScriptRunnerEvent.FRAGMENT_STOPPED_WITH_SUCCESS,
622
+ }:
623
623
  if self._state != AppSessionState.SHUTDOWN_REQUESTED:
624
624
  self._state = AppSessionState.APP_NOT_RUNNING
625
625
 
@@ -633,10 +633,10 @@ class AppSession:
633
633
  self._enqueue_forward_msg(self._create_script_finished_message(status))
634
634
  self._debug_last_backmsg_id = None
635
635
 
636
- if (
637
- event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
638
- or event == ScriptRunnerEvent.FRAGMENT_STOPPED_WITH_SUCCESS
639
- ):
636
+ if event in {
637
+ ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS,
638
+ ScriptRunnerEvent.FRAGMENT_STOPPED_WITH_SUCCESS,
639
+ }:
640
640
  # The script completed successfully: update our
641
641
  # LocalSourcesWatcher to account for any source code changes
642
642
  # that change which modules should be watched.
@@ -132,7 +132,7 @@ class CachedMessageReplayContext(threading.local):
132
132
  return util.repr_(self)
133
133
 
134
134
  @contextlib.contextmanager
135
- def calling_cached_function(self, func: FunctionType) -> Iterator[None]:
135
+ def calling_cached_function(self, func: FunctionType) -> Iterator[None]: # noqa: ARG002
136
136
  """Context manager that should wrap the invocation of a cached function.
137
137
  It allows us to track any `st.foo` messages that are generated from inside the
138
138
  function for playback during cache retrieval.
@@ -117,11 +117,10 @@ If you think this is actually a Streamlit bug, please
117
117
 
118
118
  if hash_source is None:
119
119
  object_desc = "something"
120
+ elif hasattr(hash_source, "__name__"):
121
+ object_desc = f"`{hash_source.__name__}()`"
120
122
  else:
121
- if hasattr(hash_source, "__name__"):
122
- object_desc = f"`{hash_source.__name__}()`"
123
- else:
124
- object_desc = "a function"
123
+ object_desc = "a function"
125
124
 
126
125
  decorator_name = ""
127
126
  if self.cache_type is CacheType.RESOURCE:
@@ -36,7 +36,7 @@ def cache(
36
36
  persist: bool = False,
37
37
  allow_output_mutation: bool = False,
38
38
  show_spinner: bool = True,
39
- suppress_st_warning: bool = False,
39
+ suppress_st_warning: bool = False, # noqa: ARG001
40
40
  hash_funcs: HashFuncsDict | None = None,
41
41
  max_entries: int | None = None,
42
42
  ttl: float | None = None,
@@ -40,7 +40,7 @@ class MemoryCacheStorageManager(CacheStorageManager):
40
40
 
41
41
 
42
42
  class DummyCacheStorage(CacheStorage):
43
- def get(self, key: str) -> bytes:
43
+ def get(self, key: str) -> bytes: # noqa: ARG002
44
44
  """
45
45
  Dummy gets the value for a given key,
46
46
  always raises an CacheStorageKeyNotFoundError.
@@ -143,8 +143,8 @@ class LocalDiskCacheStorage(CacheStorage):
143
143
  if self.persist == "disk":
144
144
  path = self._get_cache_file_path(key)
145
145
  try:
146
- with streamlit_read(path, binary=True) as input:
147
- value = input.read()
146
+ with streamlit_read(path, binary=True) as file:
147
+ value = file.read()
148
148
  _LOGGER.debug("Disk cache HIT: %s", key)
149
149
  return bytes(value)
150
150
  except FileNotFoundError:
@@ -374,11 +374,16 @@ def connection_factory(
374
374
  envvar_name = name[len(USE_ENV_PREFIX) :]
375
375
  name = os.environ[envvar_name]
376
376
 
377
- if type is None:
377
+ # type is a nice kwarg name for the st.connection user but is annoying to work with
378
+ # since it conflicts with the builtin function name and thus gets syntax
379
+ # highlighted.
380
+ connection_class = type
381
+
382
+ if connection_class is None:
378
383
  if name in FIRST_PARTY_CONNECTIONS:
379
384
  # We allow users to simply write `st.connection("sql")` instead of
380
385
  # `st.connection("sql", type="sql")`.
381
- type = _get_first_party_connection(name)
386
+ connection_class = _get_first_party_connection(name)
382
387
  else:
383
388
  # The user didn't specify a type, so we try to pull it out from their
384
389
  # secrets.toml file. NOTE: we're okay with any of the dict lookups below
@@ -386,12 +391,7 @@ def connection_factory(
386
391
  # it must be the case that it's defined in secrets.toml and should raise an
387
392
  # Exception otherwise.
388
393
  secrets_singleton.load_if_toml_exists()
389
- type = secrets_singleton["connections"][name]["type"]
390
-
391
- # type is a nice kwarg name for the st.connection user but is annoying to work with
392
- # since it conflicts with the builtin function name and thus gets syntax
393
- # highlighted.
394
- connection_class = type
394
+ connection_class = secrets_singleton["connections"][name]["type"]
395
395
 
396
396
  if isinstance(connection_class, str):
397
397
  # We assume that a connection_class specified via string is either the fully
@@ -367,7 +367,7 @@ class ContextProxy:
367
367
  session_client_request = _get_request()
368
368
  if session_client_request is not None:
369
369
  remote_ip = session_client_request.remote_ip
370
- if remote_ip == "::1" or remote_ip == "127.0.0.1":
370
+ if remote_ip in {"::1", "127.0.0.1"}:
371
371
  return None
372
372
  return remote_ip
373
373
  return None
@@ -82,13 +82,13 @@ class ForwardMsgQueue:
82
82
  # since the queue can be flushed to the browser at any time.
83
83
  # For example:
84
84
  # queue 1:
85
- # empty [0, 0] <- skipped
86
- # markdown [0, 0]
87
- # empty [1, 0] <- send to frontend
85
+ # > empty [0, 0] <- skipped
86
+ # > markdown [0, 0]
87
+ # > empty [1, 0] <- send to frontend
88
88
  #
89
89
  # queue 2:
90
- # markdown [1, 0]
91
- # ...
90
+ # > markdown [1, 0]
91
+ # > ...
92
92
 
93
93
  delta_key = tuple(msg.metadata.delta_path)
94
94
  if delta_key in self._delta_index_map:
@@ -184,7 +184,7 @@ def _is_composable_message(msg: ForwardMsg) -> bool:
184
184
  # operation can raise errors, and we don't have a good way of handling
185
185
  # those errors in the message queue.
186
186
  delta_type = msg.delta.WhichOneof("type")
187
- return delta_type != "add_rows" and delta_type != "arrow_add_rows"
187
+ return delta_type not in {"add_rows", "arrow_add_rows"}
188
188
 
189
189
 
190
190
  def _maybe_compose_delta_msgs(
@@ -204,9 +204,9 @@ def _maybe_compose_delta_msgs(
204
204
  # We never replace add_block deltas, because blocks can have
205
205
  # other dependent deltas later in the queue. For example:
206
206
  #
207
- # placeholder = st.empty()
208
- # placeholder.columns(1)
209
- # placeholder.empty()
207
+ # > placeholder = st.empty()
208
+ # > placeholder.columns(1)
209
+ # > placeholder.empty()
210
210
  #
211
211
  # The call to "placeholder.columns(1)" creates two blocks, a parent
212
212
  # container with delta_path (0, 0), and a column child with
@@ -222,7 +222,7 @@ def _maybe_compose_delta_msgs(
222
222
  return new_msg
223
223
 
224
224
  new_delta_type = new_msg.delta.WhichOneof("type")
225
- if new_delta_type == "new_element" or new_delta_type == "add_block":
225
+ if new_delta_type in {"new_element", "add_block"}:
226
226
  return new_msg
227
227
 
228
228
  return None