streamlit 1.48.0__py3-none-any.whl → 1.49.0__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/__init__.py +3 -10
- streamlit/commands/logo.py +4 -3
- streamlit/commands/navigation.py +1 -1
- streamlit/commands/page_config.py +4 -1
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/config.py +82 -1
- streamlit/connections/snowflake_connection.py +3 -1
- streamlit/delta_generator.py +3 -0
- streamlit/elements/arrow.py +155 -70
- streamlit/elements/bokeh_chart.py +13 -3
- streamlit/elements/deck_gl_json_chart.py +0 -1
- streamlit/elements/dialog_decorator.py +7 -59
- streamlit/elements/form.py +10 -1
- streamlit/elements/graphviz_chart.py +57 -6
- streamlit/elements/heading.py +17 -16
- streamlit/elements/iframe.py +13 -22
- streamlit/elements/image.py +64 -37
- streamlit/elements/layouts.py +2 -2
- streamlit/elements/lib/built_in_chart_utils.py +2 -5
- streamlit/elements/lib/column_config_utils.py +18 -4
- streamlit/elements/lib/column_types.py +75 -30
- streamlit/elements/lib/dialog.py +3 -3
- streamlit/elements/lib/image_utils.py +19 -11
- streamlit/elements/lib/layout_utils.py +15 -2
- streamlit/elements/lib/utils.py +20 -41
- streamlit/elements/markdown.py +7 -6
- streamlit/elements/media.py +6 -13
- streamlit/elements/metric.py +78 -1
- streamlit/elements/pdf.py +192 -0
- streamlit/elements/plotly_chart.py +3 -2
- streamlit/elements/pyplot.py +53 -11
- streamlit/elements/toast.py +81 -5
- streamlit/elements/vega_charts.py +3 -8
- streamlit/elements/widgets/audio_input.py +0 -1
- streamlit/elements/widgets/button.py +0 -4
- streamlit/elements/widgets/button_group.py +5 -4
- streamlit/elements/widgets/camera_input.py +0 -1
- streamlit/elements/widgets/chat.py +11 -13
- streamlit/elements/widgets/checkbox.py +0 -1
- streamlit/elements/widgets/color_picker.py +0 -1
- streamlit/elements/widgets/data_editor.py +142 -62
- streamlit/elements/widgets/file_uploader.py +74 -37
- streamlit/elements/widgets/multiselect.py +0 -1
- streamlit/elements/widgets/number_input.py +0 -1
- streamlit/elements/widgets/radio.py +0 -1
- streamlit/elements/widgets/select_slider.py +0 -1
- streamlit/elements/widgets/selectbox.py +0 -1
- streamlit/elements/widgets/slider.py +0 -1
- streamlit/elements/widgets/text_widgets.py +0 -2
- streamlit/elements/widgets/time_widgets.py +0 -2
- streamlit/errors.py +11 -0
- streamlit/material_icon_names.py +1 -1
- streamlit/proto/Arrow_pb2.py +14 -8
- streamlit/proto/Arrow_pb2.pyi +11 -3
- streamlit/proto/Block_pb2.py +16 -16
- streamlit/proto/Block_pb2.pyi +2 -0
- streamlit/proto/ChatInput_pb2.py +3 -3
- streamlit/proto/ChatInput_pb2.pyi +2 -0
- streamlit/proto/FileUploader_pb2.py +2 -2
- streamlit/proto/FileUploader_pb2.pyi +5 -1
- streamlit/proto/GraphVizChart_pb2.py +4 -2
- streamlit/proto/GraphVizChart_pb2.pyi +1 -1
- streamlit/proto/IFrame_pb2.py +8 -2
- streamlit/proto/IFrame_pb2.pyi +3 -0
- streamlit/proto/Image_pb2.py +4 -2
- streamlit/proto/Image_pb2.pyi +1 -10
- streamlit/proto/Metric_pb2.py +8 -6
- streamlit/proto/Metric_pb2.pyi +34 -10
- streamlit/proto/Toast_pb2.py +2 -2
- streamlit/proto/Toast_pb2.pyi +10 -1
- streamlit/runtime/caching/__init__.py +14 -2
- streamlit/runtime/caching/cache_data_api.py +0 -17
- streamlit/runtime/caching/cache_resource_api.py +0 -16
- streamlit/runtime/caching/cached_message_replay.py +8 -20
- streamlit/runtime/caching/hashing.py +31 -1
- streamlit/runtime/credentials.py +4 -4
- streamlit/runtime/fragment.py +0 -42
- streamlit/runtime/websocket_session_manager.py +1 -1
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +224 -252
- streamlit/static/static/css/{index.CJVRHjQZ.css → index.C8X8rNzw.css} +1 -1
- streamlit/static/static/css/index.COe1010n.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.D_4oFNKB.js → ErrorOutline.esm.u9XvzxL8.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.NPgaLlUE.js → FileDownload.esm.CaRyZ-b2.js} +1 -1
- streamlit/static/static/js/FileHelper.Dk2SwIi3.js +5 -0
- streamlit/static/static/js/FormClearHelper.l_UPPvkg.js +1 -0
- streamlit/static/static/js/{Hooks.BGm9sd4U.js → Hooks.BxrVEftw.js} +1 -1
- streamlit/static/static/js/InputInstructions.C254RU9X.js +1 -0
- streamlit/static/static/js/Particles.DkY6FDnc.js +1 -0
- streamlit/static/static/js/ProgressBar.BPtSM82n.js +2 -0
- streamlit/static/static/js/Toolbar.BO_3WBaS.js +1 -0
- streamlit/static/static/js/{base-input.DeBqm5mN.js → base-input.egUI4LjJ.js} +4 -4
- streamlit/static/static/js/{checkbox.C0odQfKb.js → checkbox.ButpszcE.js} +2 -2
- streamlit/static/static/js/createSuper.DYJA5xa6.js +1 -0
- streamlit/static/static/js/data-grid-overlay-editor.C9gQLEnU.js +1 -0
- streamlit/static/static/js/{downloader.Bx1D0jhz.js → downloader.B3TjsSPZ.js} +1 -1
- streamlit/static/static/js/es6.BYSNuG4D.js +2 -0
- streamlit/static/static/js/iframeResizer.contentWindow.CNPHJsF2.js +1 -0
- streamlit/static/static/js/index.0tDq1WXk.js +1 -0
- streamlit/static/static/js/index.BBnWuh07.js +976 -0
- streamlit/static/static/js/index.BDZorv41.js +1 -0
- streamlit/static/static/js/{index.DwaoC4Zp.js → index.BH79B25f.js} +3 -3
- streamlit/static/static/js/index.BeTC4Yl-.js +197 -0
- streamlit/static/static/js/index.BnOd05Ko.js +2 -0
- streamlit/static/static/js/index.BoJaJReB.js +1 -0
- streamlit/static/static/js/index.Bp1Of6L8.js +1 -0
- streamlit/static/static/js/index.Bpe4-O2W.js +1 -0
- streamlit/static/static/js/index.BrD9sbpx.js +1 -0
- streamlit/static/static/js/index.C1qCS-sd.js +1 -0
- streamlit/static/static/js/index.C3EXAI-u.js +1 -0
- streamlit/static/static/js/index.C77g9sAQ.js +3 -0
- streamlit/static/static/js/{index.PyIqRRSR.js → index.CFePF7s4.js} +1 -1
- streamlit/static/static/js/index.CFjU0x00.js +1 -0
- streamlit/static/static/js/index.Ca3y4ztK.js +1 -0
- streamlit/static/static/js/{index.ClRTsv8m.js → index.Cb9gN2T2.js} +2 -2
- streamlit/static/static/js/{index.wDYef4mQ.js → index.CbwuUwu4.js} +9 -9
- streamlit/static/static/js/index.CeXLlclc.js +1 -0
- streamlit/static/static/js/index.CfiZGqj3.js +3 -0
- streamlit/static/static/js/index.CjQnYKID.js +1 -0
- streamlit/static/static/js/index.Cl_966eE.js +3858 -0
- streamlit/static/static/js/{index.DCpyIFTV.js → index.CqSRo6zQ.js} +1 -1
- streamlit/static/static/js/index.CuEFSQ-o.js +1 -0
- streamlit/static/static/js/index.D4jR1m1z.js +1 -0
- streamlit/static/static/js/index.DGcW849X.js +1 -0
- streamlit/static/static/js/index.DKb-BAE2.js +1 -0
- streamlit/static/static/js/index.DP1rDFP0.js +1 -0
- streamlit/static/static/js/{index.HeVbRh9H.js → index.DStzYLqM.js} +2 -2
- streamlit/static/static/js/index.DVKQKDLu.js +1 -0
- streamlit/static/static/js/index.DWedOrkQ.js +1 -0
- streamlit/static/static/js/index.DYbRPmVF.js +1 -0
- streamlit/static/static/js/index.DgpIMUsr.js +1 -0
- streamlit/static/static/js/index.DtwkPJs5.js +5367 -0
- streamlit/static/static/js/{index.CnfWsQzS.js → index.MQLQLR5Z.js} +1 -1
- streamlit/static/static/js/index.uInpwWAP.js +1 -0
- streamlit/static/static/js/index.z992t-BQ.js +7 -0
- streamlit/static/static/js/{input.BL2buuce.js → input.CbP5ZuQ7.js} +2 -2
- streamlit/static/static/js/{memory.CUxjUWS7.js → memory.BuacVo2L.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.BZb9zRl_.js +9 -0
- streamlit/static/static/js/{possibleConstructorReturn.DbvQboK3.js → possibleConstructorReturn.DSM84rOS.js} +1 -1
- streamlit/static/static/js/{sandbox.6lnFVWhX.js → sandbox.C480llMG.js} +1 -1
- streamlit/static/static/js/{timepicker.Bg4xAK95.js → timepicker.BunxCVp7.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.D9x7Ktv4.js → toConsumableArray.B4o8rEx1.js} +3 -3
- streamlit/static/static/js/uniqueId.tii0yosY.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.CUSYQZpm.js → useBasicWidgetState.Bnm4FD6K.js} +1 -1
- streamlit/static/static/js/useTextInputAutoExpand.Dgtwc1m0.js +2 -0
- streamlit/static/static/js/useUpdateUiValue.DjXdMFGw.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.0cy2pVf5.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
- streamlit/user_info.py +16 -13
- streamlit/web/server/browser_websocket_handler.py +15 -0
- streamlit/web/server/oauth_authlib_routes.py +3 -59
- {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/METADATA +4 -2
- {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/RECORD +157 -160
- streamlit/static/static/css/index.CQt5TjGB.css +0 -1
- streamlit/static/static/js/FileHelper.B2t9ikoS.js +0 -5
- streamlit/static/static/js/FormClearHelper.BLEIUk6L.js +0 -1
- streamlit/static/static/js/InputInstructions.DtUxCBS8.js +0 -1
- streamlit/static/static/js/Particles.BDRPO7r3.js +0 -1
- streamlit/static/static/js/ProgressBar.B64DUUqp.js +0 -2
- streamlit/static/static/js/Toolbar.B3FquPk5.js +0 -1
- streamlit/static/static/js/createSuper.DqQ5L3XG.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.DbNsQa8Y.js +0 -1
- streamlit/static/static/js/es6.CbPK4m0H.js +0 -2
- streamlit/static/static/js/iframeResizer.contentWindow.CfLKrptA.js +0 -1
- streamlit/static/static/js/index.0XDwe9RV.js +0 -203
- streamlit/static/static/js/index.4lI9TuZm.js +0 -3
- streamlit/static/static/js/index.6s0nVIis.js +0 -3855
- streamlit/static/static/js/index.9E7bRUBU.js +0 -1
- streamlit/static/static/js/index.B9PgeLrZ.js +0 -1
- streamlit/static/static/js/index.B9vzGbOt.js +0 -1
- streamlit/static/static/js/index.BDrQKMCm.js +0 -1
- streamlit/static/static/js/index.BPsoiGgP.js +0 -1
- streamlit/static/static/js/index.CJzdLAun.js +0 -1
- streamlit/static/static/js/index.CNNlC1NL.js +0 -1
- streamlit/static/static/js/index.CO1sClzJ.js +0 -2
- streamlit/static/static/js/index.CZnagxXD.js +0 -1
- streamlit/static/static/js/index.Cb0xSF7V.js +0 -5366
- streamlit/static/static/js/index.CgUt3tz_.js +0 -1
- streamlit/static/static/js/index.CjImmcsV.js +0 -1
- streamlit/static/static/js/index.CrJ1XD_V.js +0 -1
- streamlit/static/static/js/index.CtiKsjSC.js +0 -1
- streamlit/static/static/js/index.CwAuytgV.js +0 -1
- streamlit/static/static/js/index.D7GB-kly.js +0 -1
- streamlit/static/static/js/index.DA5wU0mQ.js +0 -1
- streamlit/static/static/js/index.DE9wNOje.js +0 -1
- streamlit/static/static/js/index.DHnB-C8A.js +0 -1
- streamlit/static/static/js/index.DRTn9zvD.js +0 -1
- streamlit/static/static/js/index.DjMjyJl9.js +0 -7
- streamlit/static/static/js/index.DvRPFfw6.js +0 -781
- streamlit/static/static/js/index.F9tSej94.js +0 -1
- streamlit/static/static/js/index.J2D_m7LY.js +0 -197
- streamlit/static/static/js/index.dfivzJNz.js +0 -1
- streamlit/static/static/js/index.mRztGO69.js +0 -3
- streamlit/static/static/js/index.tB1kn_7z.js +0 -1
- streamlit/static/static/js/mergeWith.C1kp1zIi.js +0 -1
- streamlit/static/static/js/number-overlay-editor.WpheGpmR.js +0 -9
- streamlit/static/static/js/threshold.DjX0wlsa.js +0 -1
- streamlit/static/static/js/timer.CAwTRJ_g.js +0 -1
- streamlit/static/static/js/uniqueId.Bm8FHN92.js +0 -1
- streamlit/static/static/js/useTextInputAutoExpand.Bf2egQOG.js +0 -2
- streamlit/static/static/js/useUpdateUiValue.lE5xnYWF.js +0 -1
- streamlit/static/static/js/value.CgPGBV_l.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.CCOXR7N6.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
- {streamlit-1.48.0.data → streamlit-1.49.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/WHEEL +0 -0
- {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/top_level.txt +0 -0
|
@@ -33,6 +33,10 @@ from typing_extensions import TypeAlias
|
|
|
33
33
|
|
|
34
34
|
from streamlit import dataframe_util
|
|
35
35
|
from streamlit import logger as _logger
|
|
36
|
+
from streamlit.deprecation_util import (
|
|
37
|
+
make_deprecated_name_warning,
|
|
38
|
+
show_deprecation_warning,
|
|
39
|
+
)
|
|
36
40
|
from streamlit.elements.lib.column_config_utils import (
|
|
37
41
|
INDEX_IDENTIFIER,
|
|
38
42
|
ColumnConfigMapping,
|
|
@@ -47,6 +51,12 @@ from streamlit.elements.lib.column_config_utils import (
|
|
|
47
51
|
update_column_config,
|
|
48
52
|
)
|
|
49
53
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
54
|
+
from streamlit.elements.lib.layout_utils import (
|
|
55
|
+
LayoutConfig,
|
|
56
|
+
Width,
|
|
57
|
+
validate_height,
|
|
58
|
+
validate_width,
|
|
59
|
+
)
|
|
50
60
|
from streamlit.elements.lib.pandas_styler_utils import marshall_styler
|
|
51
61
|
from streamlit.elements.lib.policies import check_widget_policies
|
|
52
62
|
from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
|
|
@@ -60,7 +70,7 @@ from streamlit.runtime.state import (
|
|
|
60
70
|
WidgetKwargs,
|
|
61
71
|
register_widget,
|
|
62
72
|
)
|
|
63
|
-
from streamlit.type_util import is_type
|
|
73
|
+
from streamlit.type_util import is_list_like, is_type
|
|
64
74
|
from streamlit.util import calc_md5
|
|
65
75
|
|
|
66
76
|
if TYPE_CHECKING:
|
|
@@ -170,14 +180,14 @@ class DataEditorSerde:
|
|
|
170
180
|
|
|
171
181
|
|
|
172
182
|
def _parse_value(
|
|
173
|
-
value: str | int | float | bool | None,
|
|
183
|
+
value: str | int | float | bool | list[str] | None,
|
|
174
184
|
column_data_kind: ColumnDataKind,
|
|
175
185
|
) -> Any:
|
|
176
186
|
"""Convert a value to the correct type.
|
|
177
187
|
|
|
178
188
|
Parameters
|
|
179
189
|
----------
|
|
180
|
-
value : str | int | float | bool | None
|
|
190
|
+
value : str | int | float | bool | list[str] | None
|
|
181
191
|
The value to convert.
|
|
182
192
|
|
|
183
193
|
column_data_kind : ColumnDataKind
|
|
@@ -194,9 +204,20 @@ def _parse_value(
|
|
|
194
204
|
import pandas as pd
|
|
195
205
|
|
|
196
206
|
try:
|
|
207
|
+
if column_data_kind == ColumnDataKind.LIST:
|
|
208
|
+
return list(value) if is_list_like(value) else [value] # ty: ignore
|
|
209
|
+
|
|
197
210
|
if column_data_kind == ColumnDataKind.STRING:
|
|
198
211
|
return str(value)
|
|
199
212
|
|
|
213
|
+
# List values aren't supported for anything else than list column data kind.
|
|
214
|
+
# To make the type checker happy, we raise a TypeError here. However,
|
|
215
|
+
# This isn't expected to happen.
|
|
216
|
+
if isinstance(value, list):
|
|
217
|
+
raise TypeError( # noqa: TRY301
|
|
218
|
+
"List values are only supported by list and string columns."
|
|
219
|
+
)
|
|
220
|
+
|
|
200
221
|
if column_data_kind == ColumnDataKind.INTEGER:
|
|
201
222
|
return int(value)
|
|
202
223
|
|
|
@@ -234,7 +255,7 @@ def _parse_value(
|
|
|
234
255
|
if column_data_kind == ColumnDataKind.TIME:
|
|
235
256
|
return datetime_value.time()
|
|
236
257
|
|
|
237
|
-
except (ValueError, pd.errors.ParserError) as ex:
|
|
258
|
+
except (ValueError, pd.errors.ParserError, TypeError) as ex:
|
|
238
259
|
_LOGGER.warning(
|
|
239
260
|
"Failed to parse value %s as %s.",
|
|
240
261
|
value,
|
|
@@ -247,7 +268,9 @@ def _parse_value(
|
|
|
247
268
|
|
|
248
269
|
def _apply_cell_edits(
|
|
249
270
|
df: pd.DataFrame,
|
|
250
|
-
edited_rows: Mapping[
|
|
271
|
+
edited_rows: Mapping[
|
|
272
|
+
int, Mapping[str, str | int | float | bool | list[str] | None]
|
|
273
|
+
],
|
|
251
274
|
dataframe_schema: DataframeSchema,
|
|
252
275
|
) -> None:
|
|
253
276
|
"""Apply cell edits to the provided dataframe (inplace).
|
|
@@ -278,7 +301,7 @@ def _apply_cell_edits(
|
|
|
278
301
|
)
|
|
279
302
|
else:
|
|
280
303
|
col_pos = df.columns.get_loc(col_name)
|
|
281
|
-
df.
|
|
304
|
+
df.iat[row_pos, col_pos] = _parse_value(
|
|
282
305
|
value, dataframe_schema[col_name]
|
|
283
306
|
)
|
|
284
307
|
|
|
@@ -578,14 +601,14 @@ class DataEditorMixin:
|
|
|
578
601
|
self,
|
|
579
602
|
data: EditableData,
|
|
580
603
|
*,
|
|
581
|
-
width:
|
|
582
|
-
height: int |
|
|
604
|
+
width: Width = "stretch",
|
|
605
|
+
height: int | Literal["auto"] = "auto",
|
|
583
606
|
use_container_width: bool | None = None,
|
|
584
607
|
hide_index: bool | None = None,
|
|
585
608
|
column_order: Iterable[str] | None = None,
|
|
586
609
|
column_config: ColumnConfigMappingInput | None = None,
|
|
587
610
|
num_rows: Literal["fixed", "dynamic"] = "fixed",
|
|
588
|
-
disabled: bool | Iterable[str] = False,
|
|
611
|
+
disabled: bool | Iterable[str | int] = False,
|
|
589
612
|
key: Key | None = None,
|
|
590
613
|
on_change: WidgetCallback | None = None,
|
|
591
614
|
args: WidgetArgs | None = None,
|
|
@@ -599,14 +622,14 @@ class DataEditorMixin:
|
|
|
599
622
|
self,
|
|
600
623
|
data: Any,
|
|
601
624
|
*,
|
|
602
|
-
width:
|
|
603
|
-
height: int |
|
|
625
|
+
width: Width = "stretch",
|
|
626
|
+
height: int | Literal["auto"] = "auto",
|
|
604
627
|
use_container_width: bool | None = None,
|
|
605
628
|
hide_index: bool | None = None,
|
|
606
629
|
column_order: Iterable[str] | None = None,
|
|
607
630
|
column_config: ColumnConfigMappingInput | None = None,
|
|
608
631
|
num_rows: Literal["fixed", "dynamic"] = "fixed",
|
|
609
|
-
disabled: bool | Iterable[str] = False,
|
|
632
|
+
disabled: bool | Iterable[str | int] = False,
|
|
610
633
|
key: Key | None = None,
|
|
611
634
|
on_change: WidgetCallback | None = None,
|
|
612
635
|
args: WidgetArgs | None = None,
|
|
@@ -620,14 +643,14 @@ class DataEditorMixin:
|
|
|
620
643
|
self,
|
|
621
644
|
data: DataTypes,
|
|
622
645
|
*,
|
|
623
|
-
width:
|
|
624
|
-
height: int |
|
|
646
|
+
width: Width = "stretch",
|
|
647
|
+
height: int | Literal["auto"] = "auto",
|
|
625
648
|
use_container_width: bool | None = None,
|
|
626
649
|
hide_index: bool | None = None,
|
|
627
650
|
column_order: Iterable[str] | None = None,
|
|
628
651
|
column_config: ColumnConfigMappingInput | None = None,
|
|
629
652
|
num_rows: Literal["fixed", "dynamic"] = "fixed",
|
|
630
|
-
disabled: bool | Iterable[str] = False,
|
|
653
|
+
disabled: bool | Iterable[str | int] = False,
|
|
631
654
|
key: Key | None = None,
|
|
632
655
|
on_change: WidgetCallback | None = None,
|
|
633
656
|
args: WidgetArgs | None = None,
|
|
@@ -649,7 +672,7 @@ class DataEditorMixin:
|
|
|
649
672
|
precedence over text and number formatting from ``pandas.Styler``.
|
|
650
673
|
- Mixing data types within a column can make the column uneditable.
|
|
651
674
|
- Additionally, the following data types are not yet supported for editing:
|
|
652
|
-
``complex``, ``
|
|
675
|
+
``complex``, ``tuple``, ``bytes``, ``bytearray``,
|
|
653
676
|
``memoryview``, ``dict``, ``set``, ``frozenset``,
|
|
654
677
|
``fractions.Fraction``, ``pandas.Interval``, and
|
|
655
678
|
``pandas.Period``.
|
|
@@ -658,18 +681,28 @@ class DataEditorMixin:
|
|
|
658
681
|
default to uneditable, but this can be changed through column
|
|
659
682
|
configuration.
|
|
660
683
|
|
|
661
|
-
width :
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
684
|
+
width : "stretch", "content", or int
|
|
685
|
+
The width of the data editor. This can be one of the following:
|
|
686
|
+
|
|
687
|
+
- ``"stretch"`` (default): The width of the editor matches the
|
|
688
|
+
width of the parent container.
|
|
689
|
+
- ``"content"``: The width of the editor matches the width of its
|
|
690
|
+
content, but doesn't exceed the width of the parent container.
|
|
691
|
+
- An integer specifying the width in pixels: The editor has a
|
|
692
|
+
fixed width. If the specified width is greater than the width of
|
|
693
|
+
the parent container, the width of the editor matches the width
|
|
694
|
+
of the parent container.
|
|
667
695
|
|
|
668
|
-
height : int or
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
696
|
+
height : int or "auto"
|
|
697
|
+
The height of the data editor. This can be one of the following:
|
|
698
|
+
|
|
699
|
+
- ``"auto"`` (default): Streamlit sets the height to show at most
|
|
700
|
+
ten rows.
|
|
701
|
+
- An integer specifying the height in pixels: The editor has a
|
|
702
|
+
fixed height.
|
|
703
|
+
|
|
704
|
+
Vertical scrolling within the data editor is enabled when the
|
|
705
|
+
height does not accommodate all rows.
|
|
673
706
|
|
|
674
707
|
use_container_width : bool
|
|
675
708
|
Whether to override ``width`` with the width of the parent
|
|
@@ -683,28 +716,42 @@ class DataEditorMixin:
|
|
|
683
716
|
(default), the visibility of index columns is automatically
|
|
684
717
|
determined based on the data.
|
|
685
718
|
|
|
686
|
-
column_order : Iterable
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
719
|
+
column_order : Iterable[str] or None
|
|
720
|
+
The ordered list of columns to display. If this is ``None``
|
|
721
|
+
(default), Streamlit displays all columns in the order inherited
|
|
722
|
+
from the underlying data structure. If this is a list, the
|
|
723
|
+
indicated columns will display in the order they appear within the
|
|
724
|
+
list. Columns may be omitted or repeated within the list.
|
|
725
|
+
|
|
726
|
+
For example, ``column_order=("col2", "col1")`` will display
|
|
727
|
+
``"col2"`` first, followed by ``"col1"``, and will hide all other
|
|
728
|
+
non-index columns.
|
|
729
|
+
|
|
730
|
+
``column_order`` does not accept positional column indices and
|
|
731
|
+
can't move the index column(s).
|
|
691
732
|
|
|
692
733
|
column_config : dict or None
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
is one of:
|
|
734
|
+
Configuration to customize how columns are displayed. If this is
|
|
735
|
+
``None`` (default), columns are styled based on the underlying data
|
|
736
|
+
type of each column.
|
|
697
737
|
|
|
698
|
-
|
|
738
|
+
Column configuration can modify column names, visibility, type,
|
|
739
|
+
width, format, editing properties like min/max, and more. If this
|
|
740
|
+
is a dictionary, the keys are column names (strings) and/or
|
|
741
|
+
positional column indices (integers), and the values are one of the
|
|
742
|
+
following:
|
|
699
743
|
|
|
744
|
+
- ``None`` to hide the column.
|
|
700
745
|
- A string to set the display label of the column.
|
|
746
|
+
- One of the column types defined under ``st.column_config``. For
|
|
747
|
+
example, to show a column as dollar amounts, use
|
|
748
|
+
``st.column_config.NumberColumn("Dollar values", format="$ %d")``.
|
|
749
|
+
See more info on the available column types and config options
|
|
750
|
+
`here <https://docs.streamlit.io/develop/api-reference/data/st.column_config>`_.
|
|
701
751
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
and config options `here <https://docs.streamlit.io/develop/api-reference/data/st.column_config>`_.
|
|
706
|
-
|
|
707
|
-
To configure the index column(s), use ``_index`` as the column name.
|
|
752
|
+
To configure the index column(s), use ``"_index"`` as the column
|
|
753
|
+
name, or use a positional column index where ``0`` refers to the
|
|
754
|
+
first index column.
|
|
708
755
|
|
|
709
756
|
num_rows : "fixed" or "dynamic"
|
|
710
757
|
Specifies if the user can add and delete rows in the data editor.
|
|
@@ -712,11 +759,20 @@ class DataEditorMixin:
|
|
|
712
759
|
add and delete rows in the data editor, but column sorting is disabled.
|
|
713
760
|
Defaults to "fixed".
|
|
714
761
|
|
|
715
|
-
disabled : bool or Iterable
|
|
716
|
-
Controls the editing of columns.
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
762
|
+
disabled : bool or Iterable[str | int]
|
|
763
|
+
Controls the editing of columns. This can be one of the following:
|
|
764
|
+
|
|
765
|
+
- ``False`` (default): All columns that support editing are editable.
|
|
766
|
+
- ``True``: All columns are disabled for editing.
|
|
767
|
+
- An Iterable of column names and/or positional indices: The
|
|
768
|
+
specified columns are disabled for editing while the remaining
|
|
769
|
+
columns are editable where supported. For example,
|
|
770
|
+
``disabled=["col1", "col2"]`` will disable editing for the
|
|
771
|
+
columns named "col1" and "col2".
|
|
772
|
+
|
|
773
|
+
To disable editing for the index column(s), use ``"_index"`` as the
|
|
774
|
+
column name, or use a positional column index where ``0`` refers to
|
|
775
|
+
the first index column.
|
|
720
776
|
|
|
721
777
|
key : str
|
|
722
778
|
An optional string to use as the unique key for this widget. If this
|
|
@@ -737,6 +793,11 @@ class DataEditorMixin:
|
|
|
737
793
|
is ``None`` (default), Streamlit will use a default row height,
|
|
738
794
|
which fits one line of text.
|
|
739
795
|
|
|
796
|
+
.. deprecated::
|
|
797
|
+
``use_container_width`` is deprecated and will be removed in a
|
|
798
|
+
future release. For ``use_container_width=True``, use
|
|
799
|
+
``width="stretch"``.
|
|
800
|
+
|
|
740
801
|
Returns
|
|
741
802
|
-------
|
|
742
803
|
pandas.DataFrame, pandas.Series, pyarrow.Table, numpy.ndarray, list, set, tuple, or dict.
|
|
@@ -839,6 +900,14 @@ class DataEditorMixin:
|
|
|
839
900
|
|
|
840
901
|
key = to_key(key)
|
|
841
902
|
|
|
903
|
+
validate_width(width, allow_content=True)
|
|
904
|
+
validate_height(
|
|
905
|
+
height,
|
|
906
|
+
allow_content=False,
|
|
907
|
+
allow_stretch=False,
|
|
908
|
+
additional_allowed=["auto"],
|
|
909
|
+
)
|
|
910
|
+
|
|
842
911
|
check_widget_policies(
|
|
843
912
|
self.dg,
|
|
844
913
|
key,
|
|
@@ -847,6 +916,23 @@ class DataEditorMixin:
|
|
|
847
916
|
writes_allowed=False,
|
|
848
917
|
)
|
|
849
918
|
|
|
919
|
+
if use_container_width is not None:
|
|
920
|
+
show_deprecation_warning(
|
|
921
|
+
make_deprecated_name_warning(
|
|
922
|
+
"use_container_width",
|
|
923
|
+
"width",
|
|
924
|
+
"2025-12-31",
|
|
925
|
+
"For `use_container_width=True`, use `width='stretch'`. "
|
|
926
|
+
"For `use_container_width=False`, use `width='content'`.",
|
|
927
|
+
include_st_prefix=False,
|
|
928
|
+
),
|
|
929
|
+
show_in_browser=False,
|
|
930
|
+
)
|
|
931
|
+
if use_container_width:
|
|
932
|
+
width = "stretch"
|
|
933
|
+
elif not isinstance(width, int):
|
|
934
|
+
width = "content"
|
|
935
|
+
|
|
850
936
|
if column_order is not None:
|
|
851
937
|
column_order = list(column_order)
|
|
852
938
|
|
|
@@ -942,7 +1028,6 @@ class DataEditorMixin:
|
|
|
942
1028
|
element_id = compute_and_register_element_id(
|
|
943
1029
|
"data_editor",
|
|
944
1030
|
user_key=key,
|
|
945
|
-
form_id=current_form_id(self.dg),
|
|
946
1031
|
dg=self.dg,
|
|
947
1032
|
data=arrow_bytes,
|
|
948
1033
|
width=width,
|
|
@@ -957,18 +1042,6 @@ class DataEditorMixin:
|
|
|
957
1042
|
proto = ArrowProto()
|
|
958
1043
|
proto.id = element_id
|
|
959
1044
|
|
|
960
|
-
if use_container_width is None:
|
|
961
|
-
# If use_container_width was not explicitly set by the user, we set
|
|
962
|
-
# it to True if width was not set explicitly, and False otherwise.
|
|
963
|
-
use_container_width = width is None
|
|
964
|
-
|
|
965
|
-
proto.use_container_width = use_container_width
|
|
966
|
-
|
|
967
|
-
if width:
|
|
968
|
-
proto.width = width
|
|
969
|
-
if height:
|
|
970
|
-
proto.height = height
|
|
971
|
-
|
|
972
1045
|
if row_height:
|
|
973
1046
|
proto.row_height = row_height
|
|
974
1047
|
|
|
@@ -1005,6 +1078,13 @@ class DataEditorMixin:
|
|
|
1005
1078
|
|
|
1006
1079
|
marshall_column_config(proto, column_config_mapping)
|
|
1007
1080
|
|
|
1081
|
+
# Create layout configuration
|
|
1082
|
+
# For height, only include it in LayoutConfig if it's not "auto"
|
|
1083
|
+
# "auto" is the default behavior and doesn't need to be sent
|
|
1084
|
+
layout_config = LayoutConfig(
|
|
1085
|
+
width=width, height=height if height != "auto" else None
|
|
1086
|
+
)
|
|
1087
|
+
|
|
1008
1088
|
serde = DataEditorSerde()
|
|
1009
1089
|
|
|
1010
1090
|
widget_state = register_widget(
|
|
@@ -1019,7 +1099,7 @@ class DataEditorMixin:
|
|
|
1019
1099
|
)
|
|
1020
1100
|
|
|
1021
1101
|
_apply_dataframe_edits(data_df, widget_state.value, dataframe_schema)
|
|
1022
|
-
self.dg._enqueue("arrow_data_frame", proto)
|
|
1102
|
+
self.dg._enqueue("arrow_data_frame", proto, layout_config=layout_config)
|
|
1023
1103
|
return dataframe_util.convert_pandas_df_to_data_format(data_df, data_format)
|
|
1024
1104
|
|
|
1025
1105
|
@property
|
|
@@ -67,6 +67,12 @@ SomeUploadedFiles: TypeAlias = Union[
|
|
|
67
67
|
None,
|
|
68
68
|
]
|
|
69
69
|
|
|
70
|
+
# Type alias for accept_multiple_files parameter.
|
|
71
|
+
# If True, multiple files can be uploaded.
|
|
72
|
+
# If False, only a single file can be uploaded.
|
|
73
|
+
# If set to the literal "directory", users can upload an entire directory (folder) of files.
|
|
74
|
+
AcceptMultipleFiles: TypeAlias = Union[bool, Literal["directory"]]
|
|
75
|
+
|
|
70
76
|
|
|
71
77
|
def _get_upload_files(
|
|
72
78
|
widget_value: FileUploaderStateProto | None,
|
|
@@ -104,7 +110,7 @@ def _get_upload_files(
|
|
|
104
110
|
|
|
105
111
|
@dataclass
|
|
106
112
|
class FileUploaderSerde:
|
|
107
|
-
accept_multiple_files:
|
|
113
|
+
accept_multiple_files: AcceptMultipleFiles
|
|
108
114
|
allowed_types: Sequence[str] | None = None
|
|
109
115
|
|
|
110
116
|
def deserialize(self, ui_value: FileUploaderStateProto | None) -> SomeUploadedFiles:
|
|
@@ -117,12 +123,16 @@ class FileUploaderSerde:
|
|
|
117
123
|
if self.allowed_types:
|
|
118
124
|
enforce_filename_restriction(file.name, self.allowed_types)
|
|
119
125
|
|
|
126
|
+
# Directory uploads always return a list, similar to multiple files
|
|
127
|
+
is_multiple_or_directory = (
|
|
128
|
+
self.accept_multiple_files is True
|
|
129
|
+
or self.accept_multiple_files == "directory"
|
|
130
|
+
)
|
|
131
|
+
|
|
120
132
|
if len(upload_files) == 0:
|
|
121
|
-
return_value: SomeUploadedFiles = [] if
|
|
133
|
+
return_value: SomeUploadedFiles = [] if is_multiple_or_directory else None
|
|
122
134
|
else:
|
|
123
|
-
return_value =
|
|
124
|
-
upload_files if self.accept_multiple_files else upload_files[0]
|
|
125
|
-
)
|
|
135
|
+
return_value = upload_files if is_multiple_or_directory else upload_files[0]
|
|
126
136
|
return return_value
|
|
127
137
|
|
|
128
138
|
def serialize(self, files: SomeUploadedFiles) -> FileUploaderStateProto:
|
|
@@ -149,21 +159,22 @@ class FileUploaderMixin:
|
|
|
149
159
|
# Multiple overloads are defined on `file_uploader()` below to represent
|
|
150
160
|
# the different return types of `file_uploader()`.
|
|
151
161
|
# These return types differ according to the value of the `accept_multiple_files` argument.
|
|
152
|
-
# There are 2 associated variables, each with 2 options.
|
|
153
|
-
# 1. The `accept_multiple_files` argument is set as `True`,
|
|
154
|
-
# or it is set as `False` or omitted, in which case the default value `False`.
|
|
155
|
-
# 2. The `type` argument may or may not be provided as a keyword-only argument.
|
|
156
162
|
# There must be 2x2=4 overloads to cover all the possible arguments,
|
|
157
163
|
# as these overloads must be mutually exclusive for mypy.
|
|
164
|
+
# There are 3 associated variables, each with 2+ options.
|
|
165
|
+
# 1. The `accept_multiple_files` argument is set as `True` or `"directory"`,
|
|
166
|
+
# or it is set as `False` or omitted, in which case the default value `False`.
|
|
167
|
+
# 2. The `type` argument may or may not be provided as a keyword-only argument.
|
|
168
|
+
# 3. Directory uploads always return a list of UploadedFile objects.
|
|
158
169
|
|
|
159
170
|
# 1. type is given as not a keyword-only argument
|
|
160
|
-
# 2. accept_multiple_files = True
|
|
171
|
+
# 2. accept_multiple_files = True or "directory"
|
|
161
172
|
@overload
|
|
162
173
|
def file_uploader(
|
|
163
174
|
self,
|
|
164
175
|
label: str,
|
|
165
176
|
type: str | Sequence[str] | None,
|
|
166
|
-
accept_multiple_files: Literal[True],
|
|
177
|
+
accept_multiple_files: Literal[True, "directory"],
|
|
167
178
|
key: Key | None = None,
|
|
168
179
|
help: str | None = None,
|
|
169
180
|
on_change: WidgetCallback | None = None,
|
|
@@ -200,13 +211,13 @@ class FileUploaderMixin:
|
|
|
200
211
|
# for the related discussions and examples.
|
|
201
212
|
|
|
202
213
|
# 1. type is skipped or a keyword argument
|
|
203
|
-
# 2. accept_multiple_files = True
|
|
214
|
+
# 2. accept_multiple_files = True or "directory"
|
|
204
215
|
@overload
|
|
205
216
|
def file_uploader(
|
|
206
217
|
self,
|
|
207
218
|
label: str,
|
|
208
219
|
*,
|
|
209
|
-
accept_multiple_files: Literal[True],
|
|
220
|
+
accept_multiple_files: Literal[True, "directory"],
|
|
210
221
|
type: str | Sequence[str] | None = None,
|
|
211
222
|
key: Key | None = None,
|
|
212
223
|
help: str | None = None,
|
|
@@ -242,7 +253,7 @@ class FileUploaderMixin:
|
|
|
242
253
|
self,
|
|
243
254
|
label: str,
|
|
244
255
|
type: str | Sequence[str] | None = None,
|
|
245
|
-
accept_multiple_files:
|
|
256
|
+
accept_multiple_files: AcceptMultipleFiles = False,
|
|
246
257
|
key: Key | None = None,
|
|
247
258
|
help: str | None = None,
|
|
248
259
|
on_change: WidgetCallback | None = None,
|
|
@@ -285,7 +296,7 @@ class FileUploaderMixin:
|
|
|
285
296
|
.. |st.markdown| replace:: ``st.markdown``
|
|
286
297
|
.. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
|
|
287
298
|
|
|
288
|
-
type : str
|
|
299
|
+
type : str, list of str, or None
|
|
289
300
|
The allowed file extension(s) for uploaded files. This can be one
|
|
290
301
|
of the following types:
|
|
291
302
|
|
|
@@ -302,11 +313,19 @@ class FileUploaderMixin:
|
|
|
302
313
|
or type extensions. The correct handling of uploaded files is
|
|
303
314
|
part of the app developer's responsibility.
|
|
304
315
|
|
|
305
|
-
accept_multiple_files : bool
|
|
306
|
-
Whether to accept more than one file in a submission.
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
316
|
+
accept_multiple_files : bool or "directory"
|
|
317
|
+
Whether to accept more than one file in a submission. This can be one
|
|
318
|
+
of the following values:
|
|
319
|
+
|
|
320
|
+
- ``False`` (default): The user can only submit one file at a time.
|
|
321
|
+
- ``True``: The user can upload multiple files at the same time.
|
|
322
|
+
- ``"directory"``: The user can select a directory to upload all
|
|
323
|
+
files in the directory and its subdirectories. If ``type`` is
|
|
324
|
+
set, only files matching those type(s) will be uploaded.
|
|
325
|
+
|
|
326
|
+
When this is ``True`` or ``"directory"``, the return value will be
|
|
327
|
+
a list and a user can additively select files if they click the
|
|
328
|
+
browse button on the widget multiple times.
|
|
310
329
|
|
|
311
330
|
key : str or int
|
|
312
331
|
An optional string or integer to use as the unique key for the widget.
|
|
@@ -356,19 +375,19 @@ class FileUploaderMixin:
|
|
|
356
375
|
Returns
|
|
357
376
|
-------
|
|
358
377
|
None, UploadedFile, or list of UploadedFile
|
|
359
|
-
- If accept_multiple_files is False
|
|
360
|
-
an UploadedFile object.
|
|
361
|
-
- If accept_multiple_files is True
|
|
362
|
-
uploaded files as UploadedFile objects. If no
|
|
363
|
-
uploaded, returns an empty list.
|
|
378
|
+
- If accept_multiple_files is ``False``, returns either ``None`` or
|
|
379
|
+
an ``UploadedFile`` object.
|
|
380
|
+
- If accept_multiple_files is ``True`` or ``"directory"``, returns
|
|
381
|
+
a list with the uploaded files as ``UploadedFile`` objects. If no
|
|
382
|
+
files were uploaded, returns an empty list.
|
|
364
383
|
|
|
365
|
-
The UploadedFile class is a subclass of BytesIO
|
|
366
|
-
"file-like". This means you can pass an instance of it
|
|
367
|
-
file is expected.
|
|
384
|
+
The ``UploadedFile`` class is a subclass of ``BytesIO``, and
|
|
385
|
+
therefore is "file-like". This means you can pass an instance of it
|
|
386
|
+
anywhere a file is expected.
|
|
368
387
|
|
|
369
388
|
Examples
|
|
370
389
|
--------
|
|
371
|
-
|
|
390
|
+
**Example 1: Accept a single file at a time**
|
|
372
391
|
|
|
373
392
|
>>> import streamlit as st
|
|
374
393
|
>>> import pandas as pd
|
|
@@ -392,22 +411,36 @@ class FileUploaderMixin:
|
|
|
392
411
|
... dataframe = pd.read_csv(uploaded_file)
|
|
393
412
|
... st.write(dataframe)
|
|
394
413
|
|
|
395
|
-
|
|
414
|
+
**Example 2: Accept multiple files at a time**
|
|
396
415
|
|
|
416
|
+
>>> import pandas as pd
|
|
397
417
|
>>> import streamlit as st
|
|
398
418
|
>>>
|
|
399
419
|
>>> uploaded_files = st.file_uploader(
|
|
400
|
-
... "
|
|
420
|
+
... "Upload data", accept_multiple_files=True, type="csv"
|
|
401
421
|
... )
|
|
402
422
|
>>> for uploaded_file in uploaded_files:
|
|
403
|
-
...
|
|
404
|
-
... st.write(
|
|
405
|
-
... st.write(bytes_data)
|
|
423
|
+
... df = pd.read_csv(uploaded_file)
|
|
424
|
+
... st.write(df)
|
|
406
425
|
|
|
407
426
|
.. output::
|
|
408
427
|
https://doc-file-uploader.streamlit.app/
|
|
409
428
|
height: 375px
|
|
410
429
|
|
|
430
|
+
**Example 3: Accept an entire directory**
|
|
431
|
+
|
|
432
|
+
>>> import streamlit as st
|
|
433
|
+
>>>
|
|
434
|
+
>>> uploaded_files = st.file_uploader(
|
|
435
|
+
... "Upload images", accept_multiple_files="directory", type=["jpg", "png"]
|
|
436
|
+
... )
|
|
437
|
+
>>> for uploaded_file in uploaded_files:
|
|
438
|
+
... st.image(uploaded_file)
|
|
439
|
+
|
|
440
|
+
.. output::
|
|
441
|
+
https://doc-file-uploader-directory.streamlit.app/
|
|
442
|
+
height: 375px
|
|
443
|
+
|
|
411
444
|
"""
|
|
412
445
|
ctx = get_script_run_ctx()
|
|
413
446
|
return self._file_uploader(
|
|
@@ -429,7 +462,7 @@ class FileUploaderMixin:
|
|
|
429
462
|
self,
|
|
430
463
|
label: str,
|
|
431
464
|
type: str | Sequence[str] | None = None,
|
|
432
|
-
accept_multiple_files:
|
|
465
|
+
accept_multiple_files: AcceptMultipleFiles = False,
|
|
433
466
|
key: Key | None = None,
|
|
434
467
|
help: str | None = None,
|
|
435
468
|
on_change: WidgetCallback | None = None,
|
|
@@ -455,7 +488,6 @@ class FileUploaderMixin:
|
|
|
455
488
|
element_id = compute_and_register_element_id(
|
|
456
489
|
"file_uploader",
|
|
457
490
|
user_key=key,
|
|
458
|
-
form_id=current_form_id(self.dg),
|
|
459
491
|
dg=self.dg,
|
|
460
492
|
label=label,
|
|
461
493
|
type=type,
|
|
@@ -475,7 +507,12 @@ class FileUploaderMixin:
|
|
|
475
507
|
file_uploader_proto.max_upload_size_mb = config.get_option(
|
|
476
508
|
"server.maxUploadSize"
|
|
477
509
|
)
|
|
478
|
-
|
|
510
|
+
# Handle directory uploads - they should enable multiple files and set the directory flag
|
|
511
|
+
is_directory_upload = accept_multiple_files == "directory"
|
|
512
|
+
file_uploader_proto.multiple_files = (
|
|
513
|
+
accept_multiple_files is True or is_directory_upload
|
|
514
|
+
)
|
|
515
|
+
file_uploader_proto.accept_directory = is_directory_upload
|
|
479
516
|
file_uploader_proto.form_id = current_form_id(self.dg)
|
|
480
517
|
file_uploader_proto.disabled = disabled
|
|
481
518
|
file_uploader_proto.label_visibility.value = get_label_visibility_proto_value(
|