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.
- streamlit/auth_util.py +1 -1
- streamlit/commands/experimental_query_params.py +1 -1
- streamlit/components/v1/custom_component.py +1 -1
- streamlit/config.py +18 -4
- streamlit/delta_generator.py +0 -3
- streamlit/deprecation_util.py +1 -1
- streamlit/elements/arrow.py +6 -6
- streamlit/elements/code.py +15 -0
- streamlit/elements/deck_gl_json_chart.py +4 -4
- streamlit/elements/dialog_decorator.py +0 -1
- streamlit/elements/doc_string.py +18 -26
- streamlit/elements/image.py +8 -9
- streamlit/elements/lib/built_in_chart_utils.py +8 -8
- streamlit/elements/lib/column_config_utils.py +1 -1
- streamlit/elements/lib/column_types.py +3 -0
- streamlit/elements/lib/image_utils.py +25 -26
- streamlit/elements/lib/pandas_styler_utils.py +7 -7
- streamlit/elements/map.py +2 -2
- streamlit/elements/plotly_chart.py +5 -5
- streamlit/elements/vega_charts.py +8 -8
- streamlit/elements/widgets/audio_input.py +1 -1
- streamlit/elements/widgets/button.py +7 -6
- streamlit/elements/widgets/button_group.py +5 -11
- streamlit/elements/widgets/camera_input.py +1 -1
- streamlit/elements/widgets/chat.py +1 -3
- streamlit/elements/widgets/checkbox.py +1 -1
- streamlit/elements/widgets/color_picker.py +1 -1
- streamlit/elements/widgets/data_editor.py +1 -1
- streamlit/elements/widgets/file_uploader.py +6 -7
- streamlit/elements/widgets/multiselect.py +1 -5
- streamlit/elements/widgets/number_input.py +10 -13
- streamlit/elements/widgets/radio.py +1 -5
- streamlit/elements/widgets/select_slider.py +3 -7
- streamlit/elements/widgets/selectbox.py +1 -5
- streamlit/elements/widgets/slider.py +2 -2
- streamlit/elements/widgets/text_widgets.py +2 -2
- streamlit/elements/widgets/time_widgets.py +2 -6
- streamlit/error_util.py +1 -1
- streamlit/external/langchain/streamlit_callback_handler.py +4 -0
- streamlit/git_util.py +2 -2
- streamlit/hello/dataframe_demo.py +2 -2
- streamlit/logger.py +5 -5
- streamlit/navigation/page.py +1 -1
- streamlit/proto/Code_pb2.py +4 -3
- streamlit/proto/Code_pb2.pyi +9 -1
- streamlit/runtime/app_session.py +9 -9
- streamlit/runtime/caching/cached_message_replay.py +1 -1
- streamlit/runtime/caching/hashing.py +3 -4
- streamlit/runtime/caching/legacy_cache_api.py +1 -1
- streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +2 -2
- streamlit/runtime/connection_factory.py +8 -8
- streamlit/runtime/context.py +1 -1
- streamlit/runtime/forward_msg_queue.py +10 -10
- streamlit/runtime/metrics_util.py +2 -2
- streamlit/runtime/pages_manager.py +1 -3
- streamlit/runtime/runtime_util.py +1 -1
- streamlit/runtime/scriptrunner/exec_code.py +1 -1
- streamlit/runtime/scriptrunner/magic.py +3 -4
- streamlit/runtime/scriptrunner/script_runner.py +2 -2
- streamlit/runtime/state/common.py +2 -2
- streamlit/runtime/state/session_state.py +2 -2
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.BGxEEkBO.js → ErrorOutline.esm.BJh3F07v.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.BIvOCWXm.js → FileDownload.esm.BpUJskrZ.js} +1 -1
- streamlit/static/static/js/{FileHelper.CJg2rGQf.js → FileHelper.DKXMFthp.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.BKO5MjJ1.js → FormClearHelper.CcbGU8qM.js} +1 -1
- streamlit/static/static/js/{Hooks.Ch4fyM-d.js → Hooks.CyZIh6nK.js} +1 -1
- streamlit/static/static/js/{InputInstructions.BVG0uTsn.js → InputInstructions.nbkV1h_d.js} +1 -1
- streamlit/static/static/js/{ProgressBar.qtOeZiGm.js → ProgressBar.DeCaMWV9.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.BNrfjgR-.js → RenderInPortalIfExists.D_SwWwav.js} +1 -1
- streamlit/static/static/js/{Toolbar.DLYoM1Wd.js → Toolbar.BAN-49vk.js} +1 -1
- streamlit/static/static/js/{base-input.CMZL3Njp.js → base-input.BGFZMByD.js} +1 -1
- streamlit/static/static/js/{checkbox.Bg2c6brb.js → checkbox.B_-BK4qi.js} +1 -1
- streamlit/static/static/js/{createSuper.feapqlxC.js → createSuper.BxyEvip2.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.CPfW2LFj.js → data-grid-overlay-editor.DmJscfNY.js} +1 -1
- streamlit/static/static/js/{downloader.DzXny7Ld.js → downloader.Cv_h08Sg.js} +1 -1
- streamlit/static/static/js/{es6.0m8Dphx5.js → es6.BEoJ6t5B.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.cmKtyqx-.js → iframeResizer.contentWindow.DnBVl60m.js} +1 -1
- streamlit/static/static/js/{index.BOLpjodc.js → index.0QGnttRw.js} +1 -1
- streamlit/static/static/js/{index.cslPh4fD.js → index.7LZxcVw4.js} +1 -1
- streamlit/static/static/js/{index.C-FM6HWK.js → index.BBlDwZ3d.js} +5 -5
- streamlit/static/static/js/{index.CrKlAaBP.js → index.BCUsUBov.js} +1 -1
- streamlit/static/static/js/{index.GK7AGRO0.js → index.BDoHOUEu.js} +1 -1
- streamlit/static/static/js/{index.NE3kJsno.js → index.BJrY61fW.js} +1 -1
- streamlit/static/static/js/{index.9ahYhn9L.js → index.Bk2dieuB.js} +1 -1
- streamlit/static/static/js/{index.CPBpuLNa.js → index.BlpcPmc8.js} +1 -1
- streamlit/static/static/js/{index.DFJR7tFk.js → index.Bnv2GQ1f.js} +1 -1
- streamlit/static/static/js/{index.CeVeyA9j.js → index.BooesbgI.js} +1 -1
- streamlit/static/static/js/{index.D75DmXmJ.js → index.Bp2P-ne7.js} +1 -1
- streamlit/static/static/js/{index.Dj9pydGj.js → index.BpqJCHW4.js} +1 -1
- streamlit/static/static/js/{index.qG6NX4j3.js → index.BsajPDiD.js} +1 -1
- streamlit/static/static/js/{index.T6zTT7so.js → index.BzbL2a8R.js} +1 -1
- streamlit/static/static/js/{index.B1SRlRQI.js → index.C7tk-BaI.js} +1 -1
- streamlit/static/static/js/{index.Cz-wSZKK.js → index.CA2NGDaW.js} +1 -1
- streamlit/static/static/js/{index.CoEs3Tyr.js → index.CRdGuqu3.js} +1 -1
- streamlit/static/static/js/{index.DXwLRPNi.js → index.CT0nwqsw.js} +1 -1
- streamlit/static/static/js/{index.l2ZjmqZa.js → index.CWwqcOXB.js} +1 -1
- streamlit/static/static/js/{index.C9SZjgyE.js → index.CeEGQX9i.js} +1 -1
- streamlit/static/static/js/{index.BvuI_MOQ.js → index.CmBGzoYB.js} +1 -1
- streamlit/static/static/js/{index.CaDlXCxB.js → index.CzaH4EJh.js} +1 -1
- streamlit/static/static/js/{index.C51U-ytW.js → index.D39reA1n.js} +1 -1
- streamlit/static/static/js/{index.BQdNrQcI.js → index.DKS3g4Ws.js} +1 -1
- streamlit/static/static/js/{index.DYNcgXHh.js → index.D_Z8_2ei.js} +1 -1
- streamlit/static/static/js/{index.Dc-nqnmm.js → index.DbVBJOze.js} +1 -1
- streamlit/static/static/js/{index.BkUl8Uwz.js → index.DewKSDBK.js} +39 -39
- streamlit/static/static/js/{index.Bml5MH48.js → index.DipBpxzK.js} +1 -1
- streamlit/static/static/js/{index.lC8LhcmX.js → index.DoNPe-YW.js} +1 -1
- streamlit/static/static/js/{index.C4ApZ9VX.js → index.DwTevPv_.js} +1 -1
- streamlit/static/static/js/{index.8zBbwiSq.js → index.Dw_iEQ1s.js} +1 -1
- streamlit/static/static/js/{index.CaUiwEHb.js → index.Dz3G_3mZ.js} +1 -1
- streamlit/static/static/js/{index.45HlJMvy.js → index.WP3FKPhV.js} +1 -1
- streamlit/static/static/js/{index.lmhSYtGE.js → index.iV6t3ri-.js} +1 -1
- streamlit/static/static/js/{index.DZEEja3T.js → index.t3xwOrU9.js} +1 -1
- streamlit/static/static/js/{index.Cz5dPfTR.js → index.tbMYLMrS.js} +1 -1
- streamlit/static/static/js/index.xsH4HHeE.js +6 -0
- streamlit/static/static/js/{index.Br4Vls5z.js → index.z-3XVs6d.js} +1 -1
- streamlit/static/static/js/{input.AzemsQR7.js → input.B2MDikVk.js} +1 -1
- streamlit/static/static/js/{memory.BNnDm5qx.js → memory.BCb625DQ.js} +1 -1
- streamlit/static/static/js/{mergeWith.CnAe-pY8.js → mergeWith.COIRyAFl.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.CoO3Xzpl.js → number-overlay-editor.2CkzyF3w.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.-4k2karl.js → possibleConstructorReturn.3T2FklLD.js} +1 -1
- streamlit/static/static/js/{sandbox.B_lhrPSt.js → sandbox.Cc6yBPvx.js} +1 -1
- streamlit/static/static/js/{textarea.BXroYkeL.js → textarea.C7jOKez6.js} +1 -1
- streamlit/static/static/js/{timepicker.mhMg0du0.js → timepicker.BjMKxgZK.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.xDE9XBoI.js → toConsumableArray.BQ7m3eYw.js} +1 -1
- streamlit/static/static/js/{uniqueId.DPZFapqq.js → uniqueId.CJ7dn8nU.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.DWXpUITX.js → useBasicWidgetState.QdMR1Kj8.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.FMGxl8Ty.js → useOnInputChange.DppkR64F.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.cCJx5Did.js → withFullScreenWrapper.C2Ah-iZc.js} +1 -1
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +7 -7
- streamlit/type_util.py +2 -2
- streamlit/user_info.py +3 -3
- streamlit/watcher/event_based_path_watcher.py +14 -0
- streamlit/watcher/local_sources_watcher.py +43 -7
- streamlit/web/bootstrap.py +3 -3
- streamlit/web/cli.py +7 -7
- streamlit/web/server/media_file_handler.py +2 -2
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/RECORD +145 -145
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/WHEEL +1 -1
- streamlit/static/static/js/index.t--hEgTQ.js +0 -6
- {streamlit_nightly-1.44.2.dev20250427.data → streamlit_nightly-1.45.1.dev20250429.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/entry_points.txt +0 -0
- {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
|
149
|
-
deserialized = self.multiselect_serde.deserialize(ui_value
|
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
|
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
|
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
|
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
|
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
|
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[:] =
|
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=
|
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
|
449
|
-
|
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
|
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 {
|
455
|
+
f" but format {number_format} displays as integer."
|
458
456
|
)
|
459
|
-
elif
|
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 {
|
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(
|
469
|
+
float(number_format % 2)
|
472
470
|
except (TypeError, ValueError):
|
473
|
-
raise StreamlitInvalidNumberFormatError(
|
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
|
-
|
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
|
-
#
|
132
|
-
#
|
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
|
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
|
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
|
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
|
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
|
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
|
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 =
|
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
|
38
|
+
if level in {"CRITICAL", logging.CRITICAL}:
|
39
39
|
log_level = logging.CRITICAL
|
40
|
-
elif level
|
40
|
+
elif level in {"ERROR", logging.ERROR}:
|
41
41
|
log_level = logging.ERROR
|
42
|
-
elif level
|
42
|
+
elif level in {"WARNING", logging.WARNING}:
|
43
43
|
log_level = logging.WARNING
|
44
|
-
elif level
|
44
|
+
elif level in {"INFO", logging.INFO}:
|
45
45
|
log_level = logging.INFO
|
46
|
-
elif level
|
46
|
+
elif level in {"DEBUG", logging.DEBUG}:
|
47
47
|
log_level = logging.DEBUG
|
48
48
|
else:
|
49
49
|
msg = 'undefined log level "%s"' % level
|
streamlit/navigation/page.py
CHANGED
streamlit/proto/Code_pb2.py
CHANGED
@@ -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\"
|
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=
|
26
|
-
_globals['_CODE']._serialized_end=
|
26
|
+
_globals['_CODE']._serialized_start=66
|
27
|
+
_globals['_CODE']._serialized_end=218
|
27
28
|
# @@protoc_insertion_point(module_scope)
|
streamlit/proto/Code_pb2.pyi
CHANGED
@@ -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
|
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
|
streamlit/runtime/app_session.py
CHANGED
@@ -615,11 +615,11 @@ class AppSession:
|
|
615
615
|
|
616
616
|
self._enqueue_forward_msg(msg)
|
617
617
|
|
618
|
-
elif
|
619
|
-
|
620
|
-
|
621
|
-
|
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
|
-
|
638
|
-
|
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
|
-
|
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
|
147
|
-
value =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
streamlit/runtime/context.py
CHANGED
@@ -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
|
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
|
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
|
-
#
|
208
|
-
#
|
209
|
-
#
|
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
|
225
|
+
if new_delta_type in {"new_element", "add_block"}:
|
226
226
|
return new_msg
|
227
227
|
|
228
228
|
return None
|