streamlit 1.48.1__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/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/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.DjObtx4K.js → ErrorOutline.esm.u9XvzxL8.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Bz9nxNC5.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.DEoLCfOE.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.BmvSaPd2.js → base-input.egUI4LjJ.js} +4 -4
- streamlit/static/static/js/{checkbox.Cgxgc0et.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.M6jQeNDf.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.CbdWnLqS.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.BXDq9dj4.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.CgZDfhN4.js → index.Cb9gN2T2.js} +2 -2
- streamlit/static/static/js/{index.tsvTLdio.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.Cqa4gqqN.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.D1EayrNh.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.D1jHqUJq.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.DZd6EQlV.js → input.CbP5ZuQ7.js} +2 -2
- streamlit/static/static/js/{memory.ptkfuI71.js → memory.BuacVo2L.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.BZb9zRl_.js +9 -0
- streamlit/static/static/js/{possibleConstructorReturn.Bd4ImlQ9.js → possibleConstructorReturn.DSM84rOS.js} +1 -1
- streamlit/static/static/js/{sandbox.DsH8LuID.js → sandbox.C480llMG.js} +1 -1
- streamlit/static/static/js/{timepicker.QVekV78C.js → timepicker.BunxCVp7.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.BJvaP8gb.js → toConsumableArray.B4o8rEx1.js} +3 -3
- streamlit/static/static/js/uniqueId.tii0yosY.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.DB3vMS9V.js → useBasicWidgetState.Bnm4FD6K.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.CBkGkaRt.js → useTextInputAutoExpand.Dgtwc1m0.js} +2 -2
- 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 +3 -1
- streamlit/web/server/browser_websocket_handler.py +15 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/METADATA +4 -2
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/RECORD +153 -156
- streamlit/static/static/css/index.CQt5TjGB.css +0 -1
- streamlit/static/static/js/FileHelper.BrQvUXVD.js +0 -5
- streamlit/static/static/js/FormClearHelper.DF4gFAOO.js +0 -1
- streamlit/static/static/js/InputInstructions.D8zoMog9.js +0 -1
- streamlit/static/static/js/Particles.CCFySwdL.js +0 -1
- streamlit/static/static/js/ProgressBar.COK9j1l0.js +0 -2
- streamlit/static/static/js/Toolbar.Dt4jIKlY.js +0 -1
- streamlit/static/static/js/createSuper.siQeagI2.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +0 -1
- streamlit/static/static/js/es6.CMaUdEZ5.js +0 -2
- streamlit/static/static/js/iframeResizer.contentWindow.C33BryyP.js +0 -1
- streamlit/static/static/js/index.8GJD0eeD.js +0 -1
- streamlit/static/static/js/index.8QEYHMQD.js +0 -1
- streamlit/static/static/js/index.Ay41Wnu9.js +0 -1
- streamlit/static/static/js/index.BLiKiJ7_.js +0 -1
- streamlit/static/static/js/index.BT78cJmU.js +0 -1
- streamlit/static/static/js/index.BdGvnhlM.js +0 -1
- streamlit/static/static/js/index.BfasrT0d.js +0 -1
- streamlit/static/static/js/index.CCdtFMFG.js +0 -1
- streamlit/static/static/js/index.CFRGZDz1.js +0 -1
- streamlit/static/static/js/index.CFSFYiPA.js +0 -5366
- streamlit/static/static/js/index.CeiIiXap.js +0 -1
- streamlit/static/static/js/index.CzX2xpyc.js +0 -1
- streamlit/static/static/js/index.D1ErX5go.js +0 -2
- streamlit/static/static/js/index.D5gweoL5.js +0 -7
- streamlit/static/static/js/index.DByVKZgq.js +0 -1
- streamlit/static/static/js/index.DEND45D1.js +0 -3
- streamlit/static/static/js/index.DKN5MVff.js +0 -781
- streamlit/static/static/js/index.DfoxW1gP.js +0 -3855
- streamlit/static/static/js/index.Dtf1Ac0x.js +0 -1
- streamlit/static/static/js/index.DxrLhpeO.js +0 -1
- streamlit/static/static/js/index.J7o-_HIh.js +0 -1
- streamlit/static/static/js/index.LU8juINp.js +0 -197
- streamlit/static/static/js/index.L_N2iylt.js +0 -1
- streamlit/static/static/js/index.PZUX2kRz.js +0 -3
- streamlit/static/static/js/index.ROjU6K0k.js +0 -1
- streamlit/static/static/js/index.WSNLkF94.js +0 -1
- streamlit/static/static/js/index.X5W3gJLn.js +0 -1
- streamlit/static/static/js/index.k9LYqfSL.js +0 -1
- streamlit/static/static/js/index.pnHtHv_c.js +0 -203
- streamlit/static/static/js/index.tPUXqsfW.js +0 -1
- streamlit/static/static/js/mergeWith.GRNk8iwv.js +0 -1
- streamlit/static/static/js/number-overlay-editor.DXS2qb1U.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.D_5M8Dgf.js +0 -1
- streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +0 -1
- streamlit/static/static/js/value.CgPGBV_l.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
- {streamlit-1.48.1.data → streamlit-1.49.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/WHEEL +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/top_level.txt +0 -0
|
@@ -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(
|
|
@@ -328,7 +328,6 @@ class TextWidgetsMixin:
|
|
|
328
328
|
element_id = compute_and_register_element_id(
|
|
329
329
|
"text_input",
|
|
330
330
|
user_key=key,
|
|
331
|
-
form_id=current_form_id(self.dg),
|
|
332
331
|
dg=self.dg,
|
|
333
332
|
label=label,
|
|
334
333
|
value=value,
|
|
@@ -643,7 +642,6 @@ class TextWidgetsMixin:
|
|
|
643
642
|
element_id = compute_and_register_element_id(
|
|
644
643
|
"text_area",
|
|
645
644
|
user_key=key,
|
|
646
|
-
form_id=current_form_id(self.dg),
|
|
647
645
|
dg=self.dg,
|
|
648
646
|
label=label,
|
|
649
647
|
value=value,
|
|
@@ -529,7 +529,6 @@ class TimeWidgetsMixin:
|
|
|
529
529
|
element_id = compute_and_register_element_id(
|
|
530
530
|
"time_input",
|
|
531
531
|
user_key=key,
|
|
532
|
-
form_id=current_form_id(self.dg),
|
|
533
532
|
dg=self.dg,
|
|
534
533
|
label=label,
|
|
535
534
|
value=parsed_time if isinstance(value, (datetime, time)) else value,
|
|
@@ -912,7 +911,6 @@ class TimeWidgetsMixin:
|
|
|
912
911
|
element_id = compute_and_register_element_id(
|
|
913
912
|
"date_input",
|
|
914
913
|
user_key=key,
|
|
915
|
-
form_id=current_form_id(self.dg),
|
|
916
914
|
dg=self.dg,
|
|
917
915
|
label=label,
|
|
918
916
|
value=parsed,
|
streamlit/errors.py
CHANGED
|
@@ -517,3 +517,14 @@ class StreamlitInvalidHeightError(LocalizableStreamlitException):
|
|
|
517
517
|
height=repr(height),
|
|
518
518
|
valid_values=valid_values,
|
|
519
519
|
)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
class StreamlitValueError(LocalizableStreamlitException):
|
|
523
|
+
"""Exception raised when a value is not valid for a parameter."""
|
|
524
|
+
|
|
525
|
+
def __init__(self, parameter: str, valid_values: list[str]) -> None:
|
|
526
|
+
super().__init__(
|
|
527
|
+
"Invalid `{parameter}` value. Supported values: {valid_values}.",
|
|
528
|
+
parameter=parameter,
|
|
529
|
+
valid_values=", ".join(valid_values),
|
|
530
|
+
)
|