streamlit 1.47.1__py3-none-any.whl → 1.48.1__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/cli_util.py +1 -1
- streamlit/commands/echo.py +2 -2
- streamlit/commands/execution_control.py +1 -1
- streamlit/commands/page_config.py +16 -16
- streamlit/components/v1/component_arrow.py +4 -4
- streamlit/config.py +23 -5
- streamlit/connections/base_connection.py +2 -2
- streamlit/connections/snowflake_connection.py +2 -2
- streamlit/connections/sql_connection.py +4 -3
- streamlit/dataframe_util.py +1 -1
- streamlit/deprecation_util.py +20 -5
- streamlit/elements/arrow.py +105 -79
- streamlit/elements/deck_gl_json_chart.py +6 -6
- streamlit/elements/dialog_decorator.py +72 -17
- streamlit/elements/form.py +36 -7
- streamlit/elements/graphviz_chart.py +7 -0
- streamlit/elements/iframe.py +13 -22
- streamlit/elements/json.py +3 -3
- streamlit/elements/layouts.py +241 -75
- streamlit/elements/lib/built_in_chart_utils.py +11 -3
- streamlit/elements/lib/dialog.py +43 -0
- streamlit/elements/lib/file_uploader_utils.py +21 -2
- streamlit/elements/lib/layout_utils.py +88 -2
- streamlit/elements/lib/options_selector_utils.py +1 -1
- streamlit/elements/lib/utils.py +23 -3
- streamlit/elements/map.py +12 -11
- streamlit/elements/plotly_chart.py +21 -21
- streamlit/elements/pyplot.py +8 -4
- streamlit/elements/vega_charts.py +237 -143
- streamlit/elements/widgets/audio_input.py +2 -2
- streamlit/elements/widgets/button.py +147 -35
- streamlit/elements/widgets/button_group.py +9 -8
- streamlit/elements/widgets/camera_input.py +2 -2
- streamlit/elements/widgets/chat.py +8 -2
- streamlit/elements/widgets/checkbox.py +4 -4
- streamlit/elements/widgets/color_picker.py +2 -2
- streamlit/elements/widgets/data_editor.py +22 -15
- streamlit/elements/widgets/file_uploader.py +8 -2
- streamlit/elements/widgets/multiselect.py +27 -17
- streamlit/elements/widgets/number_input.py +2 -2
- streamlit/elements/widgets/radio.py +5 -4
- streamlit/elements/widgets/select_slider.py +8 -5
- streamlit/elements/widgets/selectbox.py +14 -4
- streamlit/elements/widgets/slider.py +59 -33
- streamlit/elements/widgets/text_widgets.py +4 -4
- streamlit/elements/widgets/time_widgets.py +4 -4
- streamlit/elements/write.py +9 -8
- streamlit/env_util.py +1 -1
- streamlit/errors.py +20 -4
- streamlit/file_util.py +1 -1
- streamlit/git_util.py +1 -1
- streamlit/logger.py +2 -2
- streamlit/proto/Block_pb2.py +39 -31
- streamlit/proto/Block_pb2.pyi +54 -3
- streamlit/proto/Button_pb2.py +4 -2
- streamlit/proto/Button_pb2.pyi +1 -0
- streamlit/proto/IFrame_pb2.py +8 -2
- streamlit/proto/IFrame_pb2.pyi +3 -0
- streamlit/runtime/caching/cache_data_api.py +15 -2
- streamlit/runtime/caching/cache_errors.py +1 -1
- streamlit/runtime/caching/cache_resource_api.py +24 -2
- streamlit/runtime/caching/cache_utils.py +6 -3
- streamlit/runtime/caching/hashing.py +6 -9
- streamlit/runtime/fragment.py +3 -2
- streamlit/runtime/runtime.py +19 -2
- streamlit/runtime/scriptrunner/script_runner.py +3 -3
- streamlit/runtime/state/common.py +2 -1
- streamlit/runtime/state/query_params.py +2 -1
- streamlit/runtime/state/session_state.py +1 -1
- streamlit/static/index.html +1 -1
- streamlit/static/manifest.json +231 -231
- streamlit/static/static/css/index.CQt5TjGB.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.BEZPMjuG.js → ErrorOutline.esm.DjObtx4K.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Dy1V9a2E.js → FileDownload.esm.Bz9nxNC5.js} +1 -1
- streamlit/static/static/js/{FileHelper.D0K06YBq.js → FileHelper.BrQvUXVD.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.Cdw5Y7_m.js → FormClearHelper.DF4gFAOO.js} +1 -1
- streamlit/static/static/js/{Hooks.C_qx1sSw.js → Hooks.DEoLCfOE.js} +1 -1
- streamlit/static/static/js/{InputInstructions.D3IDU-eY.js → InputInstructions.D8zoMog9.js} +1 -1
- streamlit/static/static/js/Particles.CCFySwdL.js +1 -0
- streamlit/static/static/js/ProgressBar.COK9j1l0.js +2 -0
- streamlit/static/static/js/Toolbar.Dt4jIKlY.js +1 -0
- streamlit/static/static/js/{base-input.DMlw5p7n.js → base-input.BmvSaPd2.js} +4 -4
- streamlit/static/static/js/{checkbox.C7QR6llE.js → checkbox.Cgxgc0et.js} +2 -2
- streamlit/static/static/js/createDownloadLinkElement.ZaXNnPK4.js +1 -0
- streamlit/static/static/js/{createSuper.C5k_2vfB.js → createSuper.siQeagI2.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +1 -0
- streamlit/static/static/js/{downloader.Nj6v3ioB.js → downloader.M6jQeNDf.js} +1 -1
- streamlit/static/static/js/{es6.CVz13CSz.js → es6.CMaUdEZ5.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.gZ8zjT0K.js → iframeResizer.contentWindow.C33BryyP.js} +1 -1
- streamlit/static/static/js/index.8GJD0eeD.js +1 -0
- streamlit/static/static/js/index.8QEYHMQD.js +1 -0
- streamlit/static/static/js/index.Ay41Wnu9.js +1 -0
- streamlit/static/static/js/index.BLiKiJ7_.js +1 -0
- streamlit/static/static/js/index.BT78cJmU.js +1 -0
- streamlit/static/static/js/index.BXDq9dj4.js +1 -0
- streamlit/static/static/js/index.BdGvnhlM.js +1 -0
- streamlit/static/static/js/index.BfasrT0d.js +1 -0
- streamlit/static/static/js/index.CCdtFMFG.js +1 -0
- streamlit/static/static/js/index.CFRGZDz1.js +1 -0
- streamlit/static/static/js/{index.MbqsiUV4.js → index.CFSFYiPA.js} +289 -289
- streamlit/static/static/js/{index.B2L574n6.js → index.CbdWnLqS.js} +3 -3
- streamlit/static/static/js/index.CeiIiXap.js +1 -0
- streamlit/static/static/js/index.CgZDfhN4.js +2 -0
- streamlit/static/static/js/{index.xfcNJBLM.js → index.Cqa4gqqN.js} +1 -1
- streamlit/static/static/js/index.CzX2xpyc.js +1 -0
- streamlit/static/static/js/index.D1EayrNh.js +73 -0
- streamlit/static/static/js/index.D1ErX5go.js +2 -0
- streamlit/static/static/js/{index.CTT2YqEU.js → index.D1jHqUJq.js} +1 -1
- streamlit/static/static/js/index.D5gweoL5.js +7 -0
- streamlit/static/static/js/index.DByVKZgq.js +1 -0
- streamlit/static/static/js/index.DEND45D1.js +3 -0
- streamlit/static/static/js/{index.CbQtRkVt.js → index.DKN5MVff.js} +162 -188
- streamlit/static/static/js/index.DfoxW1gP.js +3855 -0
- streamlit/static/static/js/index.Dtf1Ac0x.js +1 -0
- streamlit/static/static/js/index.DxrLhpeO.js +1 -0
- streamlit/static/static/js/{index.BSFzxMXi.js → index.J7o-_HIh.js} +1 -1
- streamlit/static/static/js/index.LU8juINp.js +197 -0
- streamlit/static/static/js/index.L_N2iylt.js +1 -0
- streamlit/static/static/js/{index.BscWuWHL.js → index.PZUX2kRz.js} +3 -3
- streamlit/static/static/js/index.ROjU6K0k.js +1 -0
- streamlit/static/static/js/index.WSNLkF94.js +1 -0
- streamlit/static/static/js/index.X5W3gJLn.js +1 -0
- streamlit/static/static/js/index.k9LYqfSL.js +1 -0
- streamlit/static/static/js/{index.D3wOJJsg.js → index.pnHtHv_c.js} +12 -12
- streamlit/static/static/js/index.tPUXqsfW.js +1 -0
- streamlit/static/static/js/index.tsvTLdio.js +12 -0
- streamlit/static/static/js/{input.D_45B0P-.js → input.DZd6EQlV.js} +2 -2
- streamlit/static/static/js/{memory.BmhrRyO2.js → memory.ptkfuI71.js} +1 -1
- streamlit/static/static/js/{mergeWith.DvOME7eH.js → mergeWith.GRNk8iwv.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.BRNxOzEZ.js → number-overlay-editor.DXS2qb1U.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.C5GiK_Ob.js → possibleConstructorReturn.Bd4ImlQ9.js} +1 -1
- streamlit/static/static/js/{sandbox.B-Q9S7vW.js → sandbox.DsH8LuID.js} +1 -1
- streamlit/static/static/js/{timepicker.DOMbfm_a.js → timepicker.QVekV78C.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CbNz0Ciu.js → toConsumableArray.BJvaP8gb.js} +1 -1
- streamlit/static/static/js/{uniqueId.-ygIU7IL.js → uniqueId.D_5M8Dgf.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.Bx3VaRHk.js → useBasicWidgetState.DB3vMS9V.js} +1 -1
- streamlit/static/static/js/useTextInputAutoExpand.CBkGkaRt.js +2 -0
- streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +1 -0
- streamlit/temporary_directory.py +5 -3
- streamlit/testing/v1/app_test.py +4 -1
- streamlit/testing/v1/element_tree.py +4 -5
- streamlit/type_util.py +10 -3
- streamlit/user_info.py +6 -1
- streamlit/util.py +11 -1
- streamlit/watcher/local_sources_watcher.py +4 -3
- streamlit/web/bootstrap.py +18 -12
- streamlit/web/cli.py +2 -1
- streamlit/web/server/server.py +72 -21
- {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/METADATA +14 -2
- {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/RECORD +155 -155
- streamlit/static/static/css/index.CsLB_Bnz.css +0 -1
- streamlit/static/static/js/ProgressBar.EhJ_lCOf.js +0 -2
- streamlit/static/static/js/RenderInPortalIfExists.D6a0mMll.js +0 -1
- streamlit/static/static/js/Toolbar.D6yqQ65-.js +0 -1
- streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.CoquyZNK.js +0 -1
- streamlit/static/static/js/index.B3n-pURl.js +0 -2
- streamlit/static/static/js/index.B9jJp9aE.js +0 -1
- streamlit/static/static/js/index.BBVtld-D.js +0 -1
- streamlit/static/static/js/index.BKHPnvYd.js +0 -1
- streamlit/static/static/js/index.B_1CXynz.js +0 -1
- streamlit/static/static/js/index.Bm1LklYO.js +0 -1
- streamlit/static/static/js/index.Byi6__iF.js +0 -1
- streamlit/static/static/js/index.BzJeMpQ-.js +0 -197
- streamlit/static/static/js/index.C4tw7-Cl.js +0 -2
- streamlit/static/static/js/index.CG0C49ex.js +0 -1
- streamlit/static/static/js/index.CMuSJPv-.js +0 -1
- streamlit/static/static/js/index.COPFcr_K.js +0 -3855
- streamlit/static/static/js/index.CU3TLDlu.js +0 -1
- streamlit/static/static/js/index.CVKKDwaf.js +0 -1
- streamlit/static/static/js/index.CWZeK3mV.js +0 -12
- streamlit/static/static/js/index.CWbiNJQl.js +0 -1
- streamlit/static/static/js/index.CWxefYP6.js +0 -73
- streamlit/static/static/js/index.DOdWa88b.js +0 -1
- streamlit/static/static/js/index.DXtnaPua.js +0 -1
- streamlit/static/static/js/index.DatDwFl3.js +0 -3
- streamlit/static/static/js/index.DeWYPvQR.js +0 -1
- streamlit/static/static/js/index.Do4vzIvK.js +0 -1
- streamlit/static/static/js/index.Dvrstlh8.js +0 -1
- streamlit/static/static/js/index.DvznfdF_.js +0 -1
- streamlit/static/static/js/index.U1vvXeGn.js +0 -1
- streamlit/static/static/js/index._WAuWRkp.js +0 -7
- streamlit/static/static/js/index.bwA9_eWC.js +0 -1
- streamlit/static/static/js/index.m1njXuKl.js +0 -1
- streamlit/static/static/js/index.mihWZKb1.js +0 -1
- streamlit/static/static/js/useOnInputChange.CDZx-L6q.js +0 -1
- streamlit/static/static/js/useTextInputAutoExpand.BuE9l5TG.js +0 -2
- streamlit/static/static/js/withFullScreenWrapper.DWXejOhQ.js +0 -1
- {streamlit-1.47.1.data → streamlit-1.48.1.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/WHEEL +0 -0
- {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/entry_points.txt +0 -0
- {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/top_level.txt +0 -0
|
@@ -296,6 +296,12 @@ class FileUploaderMixin:
|
|
|
296
296
|
example, to only accept JPG/JPEG and PNG files, use
|
|
297
297
|
``["jpg", "jpeg", "png"]``.
|
|
298
298
|
|
|
299
|
+
.. note::
|
|
300
|
+
This is a best-effort check, but doesn't provide a
|
|
301
|
+
security guarantee against users uploading files of other types
|
|
302
|
+
or type extensions. The correct handling of uploaded files is
|
|
303
|
+
part of the app developer's responsibility.
|
|
304
|
+
|
|
299
305
|
accept_multiple_files : bool
|
|
300
306
|
Whether to accept more than one file in a submission. If this is
|
|
301
307
|
``False`` (default), the user can only submit one file at a time.
|
|
@@ -320,8 +326,8 @@ class FileUploaderMixin:
|
|
|
320
326
|
An optional callback invoked when this file_uploader's value
|
|
321
327
|
changes.
|
|
322
328
|
|
|
323
|
-
args : tuple
|
|
324
|
-
An optional tuple of args to pass to the callback.
|
|
329
|
+
args : list or tuple
|
|
330
|
+
An optional list or tuple of args to pass to the callback.
|
|
325
331
|
|
|
326
332
|
kwargs : dict
|
|
327
333
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -16,7 +16,16 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from collections.abc import Sequence
|
|
18
18
|
from textwrap import dedent
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import (
|
|
20
|
+
TYPE_CHECKING,
|
|
21
|
+
Any,
|
|
22
|
+
Callable,
|
|
23
|
+
Generic,
|
|
24
|
+
Literal,
|
|
25
|
+
TypeVar,
|
|
26
|
+
cast,
|
|
27
|
+
overload,
|
|
28
|
+
)
|
|
20
29
|
|
|
21
30
|
from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
|
|
22
31
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
@@ -51,7 +60,6 @@ from streamlit.runtime.metrics_util import gather_metrics
|
|
|
51
60
|
from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
|
|
52
61
|
from streamlit.runtime.state import register_widget
|
|
53
62
|
from streamlit.type_util import (
|
|
54
|
-
T,
|
|
55
63
|
is_iterable,
|
|
56
64
|
)
|
|
57
65
|
|
|
@@ -66,6 +74,8 @@ if TYPE_CHECKING:
|
|
|
66
74
|
WidgetKwargs,
|
|
67
75
|
)
|
|
68
76
|
|
|
77
|
+
T = TypeVar("T")
|
|
78
|
+
|
|
69
79
|
|
|
70
80
|
class MultiSelectSerde(Generic[T]):
|
|
71
81
|
options: Sequence[T]
|
|
@@ -245,7 +255,7 @@ class MultiSelectMixin:
|
|
|
245
255
|
|
|
246
256
|
Parameters
|
|
247
257
|
----------
|
|
248
|
-
label: str
|
|
258
|
+
label : str
|
|
249
259
|
A short label explaining to the user what this select widget is for.
|
|
250
260
|
The label can optionally contain GitHub-flavored Markdown of the
|
|
251
261
|
following types: Bold, Italics, Strikethroughs, Inline Code, Links,
|
|
@@ -267,27 +277,27 @@ class MultiSelectMixin:
|
|
|
267
277
|
.. |st.markdown| replace:: ``st.markdown``
|
|
268
278
|
.. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
|
|
269
279
|
|
|
270
|
-
options: Iterable
|
|
280
|
+
options : Iterable
|
|
271
281
|
Labels for the select options in an ``Iterable``. This can be a
|
|
272
282
|
``list``, ``set``, or anything supported by ``st.dataframe``. If
|
|
273
283
|
``options`` is dataframe-like, the first column will be used. Each
|
|
274
284
|
label will be cast to ``str`` internally by default.
|
|
275
285
|
|
|
276
|
-
default: Iterable of V, V, or None
|
|
286
|
+
default : Iterable of V, V, or None
|
|
277
287
|
List of default values. Can also be a single value.
|
|
278
288
|
|
|
279
|
-
format_func: function
|
|
289
|
+
format_func : function
|
|
280
290
|
Function to modify the display of the options. It receives
|
|
281
291
|
the raw option as an argument and should output the label to be
|
|
282
292
|
shown for that option. This has no impact on the return value of
|
|
283
293
|
the command.
|
|
284
294
|
|
|
285
|
-
key: str or int
|
|
295
|
+
key : str or int
|
|
286
296
|
An optional string or integer to use as the unique key for the widget.
|
|
287
297
|
If this is omitted, a key will be generated for the widget
|
|
288
298
|
based on its content. No two widgets may have the same key.
|
|
289
299
|
|
|
290
|
-
help: str or None
|
|
300
|
+
help : str or None
|
|
291
301
|
A tooltip that gets displayed next to the widget label. Streamlit
|
|
292
302
|
only displays the tooltip when ``label_visibility="visible"``. If
|
|
293
303
|
this is ``None`` (default), no tooltip is displayed.
|
|
@@ -296,19 +306,19 @@ class MultiSelectMixin:
|
|
|
296
306
|
including the Markdown directives described in the ``body``
|
|
297
307
|
parameter of ``st.markdown``.
|
|
298
308
|
|
|
299
|
-
on_change: callable
|
|
309
|
+
on_change : callable
|
|
300
310
|
An optional callback invoked when this widget's value changes.
|
|
301
311
|
|
|
302
|
-
args: tuple
|
|
303
|
-
An optional tuple of args to pass to the callback.
|
|
312
|
+
args : list or tuple
|
|
313
|
+
An optional list or tuple of args to pass to the callback.
|
|
304
314
|
|
|
305
|
-
kwargs: dict
|
|
315
|
+
kwargs : dict
|
|
306
316
|
An optional dict of kwargs to pass to the callback.
|
|
307
317
|
|
|
308
|
-
max_selections: int
|
|
318
|
+
max_selections : int
|
|
309
319
|
The max selections that can be selected at a time.
|
|
310
320
|
|
|
311
|
-
placeholder: str or None
|
|
321
|
+
placeholder : str or None
|
|
312
322
|
A string to display when no options are selected.
|
|
313
323
|
If this is ``None`` (default), the widget displays placeholder text
|
|
314
324
|
based on the widget's configuration:
|
|
@@ -323,17 +333,17 @@ class MultiSelectMixin:
|
|
|
323
333
|
and ``accept_new_options=False``. The widget is also disabled in
|
|
324
334
|
this case.
|
|
325
335
|
|
|
326
|
-
disabled: bool
|
|
336
|
+
disabled : bool
|
|
327
337
|
An optional boolean that disables the multiselect widget if set
|
|
328
338
|
to ``True``. The default is ``False``.
|
|
329
339
|
|
|
330
|
-
label_visibility: "visible", "hidden", or "collapsed"
|
|
340
|
+
label_visibility : "visible", "hidden", or "collapsed"
|
|
331
341
|
The visibility of the label. The default is ``"visible"``. If this
|
|
332
342
|
is ``"hidden"``, Streamlit displays an empty spacer instead of the
|
|
333
343
|
label, which can help keep the widget aligned with other widgets.
|
|
334
344
|
If this is ``"collapsed"``, Streamlit displays no label or spacer.
|
|
335
345
|
|
|
336
|
-
accept_new_options: bool
|
|
346
|
+
accept_new_options : bool
|
|
337
347
|
Whether the user can add selections that aren't included in ``options``.
|
|
338
348
|
If this is ``False`` (default), the user can only select from the
|
|
339
349
|
items in ``options``. If this is ``True``, the user can enter new
|
|
@@ -317,8 +317,8 @@ class NumberInputMixin:
|
|
|
317
317
|
on_change : callable
|
|
318
318
|
An optional callback invoked when this number_input's value changes.
|
|
319
319
|
|
|
320
|
-
args : tuple
|
|
321
|
-
An optional tuple of args to pass to the callback.
|
|
320
|
+
args : list or tuple
|
|
321
|
+
An optional list or tuple of args to pass to the callback.
|
|
322
322
|
|
|
323
323
|
kwargs : dict
|
|
324
324
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from dataclasses import dataclass
|
|
18
18
|
from textwrap import dedent
|
|
19
|
-
from typing import TYPE_CHECKING, Any, Callable, Generic, cast, overload
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast, overload
|
|
20
20
|
|
|
21
21
|
from typing_extensions import Never
|
|
22
22
|
|
|
@@ -52,7 +52,6 @@ from streamlit.runtime.state import (
|
|
|
52
52
|
register_widget,
|
|
53
53
|
)
|
|
54
54
|
from streamlit.type_util import (
|
|
55
|
-
T,
|
|
56
55
|
check_python_comparable,
|
|
57
56
|
)
|
|
58
57
|
|
|
@@ -61,6 +60,8 @@ if TYPE_CHECKING:
|
|
|
61
60
|
|
|
62
61
|
from streamlit.delta_generator import DeltaGenerator
|
|
63
62
|
|
|
63
|
+
T = TypeVar("T")
|
|
64
|
+
|
|
64
65
|
|
|
65
66
|
@dataclass
|
|
66
67
|
class RadioSerde(Generic[T]):
|
|
@@ -228,8 +229,8 @@ class RadioMixin:
|
|
|
228
229
|
on_change : callable
|
|
229
230
|
An optional callback invoked when this radio's value changes.
|
|
230
231
|
|
|
231
|
-
args : tuple
|
|
232
|
-
An optional tuple of args to pass to the callback.
|
|
232
|
+
args : list or tuple
|
|
233
|
+
An optional list or tuple of args to pass to the callback.
|
|
233
234
|
|
|
234
235
|
kwargs : dict
|
|
235
236
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -21,6 +21,7 @@ from typing import (
|
|
|
21
21
|
Any,
|
|
22
22
|
Callable,
|
|
23
23
|
Generic,
|
|
24
|
+
TypeVar,
|
|
24
25
|
cast,
|
|
25
26
|
overload,
|
|
26
27
|
)
|
|
@@ -57,7 +58,7 @@ from streamlit.runtime.state import (
|
|
|
57
58
|
WidgetKwargs,
|
|
58
59
|
register_widget,
|
|
59
60
|
)
|
|
60
|
-
from streamlit.type_util import
|
|
61
|
+
from streamlit.type_util import check_python_comparable
|
|
61
62
|
|
|
62
63
|
if TYPE_CHECKING:
|
|
63
64
|
from collections.abc import Sequence
|
|
@@ -66,6 +67,8 @@ if TYPE_CHECKING:
|
|
|
66
67
|
from streamlit.elements.lib.layout_utils import WidthWithoutContent
|
|
67
68
|
from streamlit.runtime.state.common import RegisterWidgetResult
|
|
68
69
|
|
|
70
|
+
T = TypeVar("T")
|
|
71
|
+
|
|
69
72
|
|
|
70
73
|
def _is_range_value(value: T | Sequence[T]) -> TypeGuard[Sequence[T]]:
|
|
71
74
|
return isinstance(value, (list, tuple))
|
|
@@ -94,7 +97,7 @@ class SelectSliderSerde(Generic[T]):
|
|
|
94
97
|
# If the original value was a list/tuple, so will be the output (and vice versa)
|
|
95
98
|
return return_value if self.is_range_value else return_value[0]
|
|
96
99
|
|
|
97
|
-
def _as_index_list(self, v:
|
|
100
|
+
def _as_index_list(self, v: Any) -> list[int]:
|
|
98
101
|
if _is_range_value(v):
|
|
99
102
|
slider_value = [index_(self.options, val) for val in v]
|
|
100
103
|
start, end = slider_value
|
|
@@ -228,8 +231,8 @@ class SelectSliderMixin:
|
|
|
228
231
|
on_change : callable
|
|
229
232
|
An optional callback invoked when this select_slider's value changes.
|
|
230
233
|
|
|
231
|
-
args : tuple
|
|
232
|
-
An optional tuple of args to pass to the callback.
|
|
234
|
+
args : list or tuple
|
|
235
|
+
An optional list or tuple of args to pass to the callback.
|
|
233
236
|
|
|
234
237
|
kwargs : dict
|
|
235
238
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -352,7 +355,7 @@ class SelectSliderMixin:
|
|
|
352
355
|
if len(opt) == 0:
|
|
353
356
|
raise StreamlitAPIException("The `options` argument needs to be non-empty")
|
|
354
357
|
|
|
355
|
-
def as_index_list(v:
|
|
358
|
+
def as_index_list(v: Any) -> list[int]:
|
|
356
359
|
if _is_range_value(v):
|
|
357
360
|
slider_value = [index_(opt, val) for val in v]
|
|
358
361
|
start, end = slider_value
|
|
@@ -14,7 +14,16 @@
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
16
|
from textwrap import dedent
|
|
17
|
-
from typing import
|
|
17
|
+
from typing import (
|
|
18
|
+
TYPE_CHECKING,
|
|
19
|
+
Any,
|
|
20
|
+
Callable,
|
|
21
|
+
Generic,
|
|
22
|
+
Literal,
|
|
23
|
+
TypeVar,
|
|
24
|
+
cast,
|
|
25
|
+
overload,
|
|
26
|
+
)
|
|
18
27
|
|
|
19
28
|
from typing_extensions import Never
|
|
20
29
|
|
|
@@ -54,7 +63,6 @@ from streamlit.runtime.state import (
|
|
|
54
63
|
register_widget,
|
|
55
64
|
)
|
|
56
65
|
from streamlit.type_util import (
|
|
57
|
-
T,
|
|
58
66
|
check_python_comparable,
|
|
59
67
|
)
|
|
60
68
|
|
|
@@ -63,6 +71,8 @@ if TYPE_CHECKING:
|
|
|
63
71
|
|
|
64
72
|
from streamlit.delta_generator import DeltaGenerator
|
|
65
73
|
|
|
74
|
+
T = TypeVar("T")
|
|
75
|
+
|
|
66
76
|
|
|
67
77
|
class SelectboxSerde(Generic[T]):
|
|
68
78
|
options: Sequence[T]
|
|
@@ -336,8 +346,8 @@ class SelectboxMixin:
|
|
|
336
346
|
on_change : callable
|
|
337
347
|
An optional callback invoked when this selectbox's value changes.
|
|
338
348
|
|
|
339
|
-
args : tuple
|
|
340
|
-
An optional tuple of args to pass to the callback.
|
|
349
|
+
args : list or tuple
|
|
350
|
+
An optional list or tuple of args to pass to the callback.
|
|
341
351
|
|
|
342
352
|
kwargs : dict
|
|
343
353
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -555,8 +555,8 @@ class SliderMixin:
|
|
|
555
555
|
on_change : callable
|
|
556
556
|
An optional callback invoked when this slider's value changes.
|
|
557
557
|
|
|
558
|
-
args : tuple
|
|
559
|
-
An optional tuple of args to pass to the callback.
|
|
558
|
+
args : list or tuple
|
|
559
|
+
An optional list or tuple of args to pass to the callback.
|
|
560
560
|
|
|
561
561
|
kwargs : dict
|
|
562
562
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -723,8 +723,7 @@ class SliderMixin:
|
|
|
723
723
|
)
|
|
724
724
|
|
|
725
725
|
# Simplify future logic by always making value a list
|
|
726
|
-
if single_value:
|
|
727
|
-
value = [value]
|
|
726
|
+
prepared_value: Sequence[SliderScalar] = [value] if single_value else value # ty: ignore[invalid-assignment]
|
|
728
727
|
|
|
729
728
|
def value_to_generic_type(v: Any) -> SliderProto.DataType.ValueType:
|
|
730
729
|
if isinstance(v, Integral):
|
|
@@ -736,26 +735,32 @@ class SliderMixin:
|
|
|
736
735
|
def all_same_type(items: Any) -> bool:
|
|
737
736
|
return len(set(map(value_to_generic_type, items))) < 2
|
|
738
737
|
|
|
739
|
-
if not all_same_type(
|
|
738
|
+
if not all_same_type(prepared_value):
|
|
740
739
|
raise StreamlitAPIException(
|
|
741
740
|
"Slider tuple/list components must be of the same type.\n"
|
|
742
|
-
f"But were: {list(map(type,
|
|
741
|
+
f"But were: {list(map(type, prepared_value))}"
|
|
743
742
|
)
|
|
744
743
|
|
|
745
744
|
data_type = (
|
|
746
|
-
SliderProto.INT
|
|
745
|
+
SliderProto.INT
|
|
746
|
+
if len(prepared_value) == 0
|
|
747
|
+
else value_to_generic_type(prepared_value[0])
|
|
747
748
|
)
|
|
748
749
|
|
|
749
|
-
datetime_min = time.min
|
|
750
|
-
datetime_max = time.max
|
|
750
|
+
datetime_min: datetime | time = time.min
|
|
751
|
+
datetime_max: datetime | time = time.max
|
|
751
752
|
if data_type == SliderProto.TIME:
|
|
752
|
-
|
|
753
|
-
|
|
753
|
+
prepared_value = cast("Sequence[time]", prepared_value)
|
|
754
|
+
|
|
755
|
+
datetime_min = time.min.replace(tzinfo=prepared_value[0].tzinfo)
|
|
756
|
+
datetime_max = time.max.replace(tzinfo=prepared_value[0].tzinfo)
|
|
754
757
|
if data_type in (SliderProto.DATETIME, SliderProto.DATE):
|
|
755
|
-
|
|
756
|
-
|
|
758
|
+
prepared_value = cast("Sequence[datetime]", prepared_value)
|
|
759
|
+
|
|
760
|
+
datetime_min = prepared_value[0] - timedelta(days=14)
|
|
761
|
+
datetime_max = prepared_value[0] + timedelta(days=14)
|
|
757
762
|
|
|
758
|
-
defaults: Final = {
|
|
763
|
+
defaults: Final[dict[SliderProto.DataType.ValueType, dict[str, Any]]] = {
|
|
759
764
|
SliderProto.INT: {
|
|
760
765
|
"min_value": 0,
|
|
761
766
|
"max_value": 100,
|
|
@@ -846,20 +851,20 @@ class SliderMixin:
|
|
|
846
851
|
# Ensure that min <= value(s) <= max, adjusting the bounds as necessary.
|
|
847
852
|
min_value = min(min_value, max_value)
|
|
848
853
|
max_value = max(min_value, max_value)
|
|
849
|
-
if len(
|
|
850
|
-
min_value = min(
|
|
851
|
-
max_value = max(
|
|
852
|
-
elif len(
|
|
853
|
-
start, end =
|
|
854
|
-
if start > end:
|
|
854
|
+
if len(prepared_value) == 1:
|
|
855
|
+
min_value = min(prepared_value[0], min_value)
|
|
856
|
+
max_value = max(prepared_value[0], max_value)
|
|
857
|
+
elif len(prepared_value) == 2:
|
|
858
|
+
start, end = prepared_value
|
|
859
|
+
if start > end: # type: ignore[operator]
|
|
855
860
|
# Swap start and end, since they seem reversed
|
|
856
861
|
start, end = end, start
|
|
857
|
-
|
|
862
|
+
prepared_value = start, end
|
|
858
863
|
min_value = min(start, min_value)
|
|
859
864
|
max_value = max(end, max_value)
|
|
860
865
|
else:
|
|
861
866
|
# Empty list, so let's just use the outer bounds
|
|
862
|
-
|
|
867
|
+
prepared_value = [min_value, max_value]
|
|
863
868
|
|
|
864
869
|
# Bounds checks. JSNumber produces human-readable exceptions that
|
|
865
870
|
# we simply re-package as StreamlitAPIExceptions.
|
|
@@ -881,12 +886,20 @@ class SliderMixin:
|
|
|
881
886
|
orig_tz = None
|
|
882
887
|
# Convert dates or times into datetimes
|
|
883
888
|
if data_type == SliderProto.TIME:
|
|
884
|
-
|
|
889
|
+
prepared_value = cast("Sequence[time]", prepared_value)
|
|
890
|
+
min_value = cast("time", min_value)
|
|
891
|
+
max_value = cast("time", max_value)
|
|
892
|
+
|
|
893
|
+
prepared_value = list(map(_time_to_datetime, prepared_value))
|
|
885
894
|
min_value = _time_to_datetime(min_value)
|
|
886
895
|
max_value = _time_to_datetime(max_value)
|
|
887
896
|
|
|
888
897
|
if data_type == SliderProto.DATE:
|
|
889
|
-
|
|
898
|
+
prepared_value = cast("Sequence[date]", prepared_value)
|
|
899
|
+
min_value = cast("date", min_value)
|
|
900
|
+
max_value = cast("date", max_value)
|
|
901
|
+
|
|
902
|
+
prepared_value = list(map(_date_to_datetime, prepared_value))
|
|
890
903
|
min_value = _date_to_datetime(min_value)
|
|
891
904
|
max_value = _date_to_datetime(max_value)
|
|
892
905
|
|
|
@@ -900,17 +913,25 @@ class SliderMixin:
|
|
|
900
913
|
|
|
901
914
|
# Now, convert to microseconds (so we can serialize datetime to a long)
|
|
902
915
|
if data_type in TIMELIKE_TYPES:
|
|
916
|
+
prepared_value = cast("Sequence[datetime]", prepared_value)
|
|
917
|
+
min_value = cast("datetime", min_value)
|
|
918
|
+
max_value = cast("datetime", max_value)
|
|
919
|
+
step = cast("timedelta", step)
|
|
920
|
+
|
|
903
921
|
# Restore times/datetimes to original timezone (dates are always naive)
|
|
904
922
|
orig_tz = (
|
|
905
|
-
|
|
923
|
+
prepared_value[0].tzinfo
|
|
906
924
|
if data_type in (SliderProto.TIME, SliderProto.DATETIME)
|
|
907
925
|
else None
|
|
908
926
|
)
|
|
909
927
|
|
|
910
|
-
|
|
928
|
+
prepared_value = list(map(_datetime_to_micros, prepared_value))
|
|
911
929
|
min_value = _datetime_to_micros(min_value)
|
|
912
930
|
max_value = _datetime_to_micros(max_value)
|
|
913
|
-
step = _delta_to_micros(
|
|
931
|
+
step = _delta_to_micros(step)
|
|
932
|
+
|
|
933
|
+
# At this point, prepared_value is expected to be a list of floats:
|
|
934
|
+
prepared_value = cast("list[float]", prepared_value)
|
|
914
935
|
|
|
915
936
|
# It would be great if we could guess the number of decimal places from
|
|
916
937
|
# the `step` argument, but this would only be meaningful if step were a
|
|
@@ -922,7 +943,7 @@ class SliderMixin:
|
|
|
922
943
|
slider_proto.id = element_id
|
|
923
944
|
slider_proto.label = label
|
|
924
945
|
slider_proto.format = format
|
|
925
|
-
slider_proto.default[:] =
|
|
946
|
+
slider_proto.default[:] = prepared_value
|
|
926
947
|
slider_proto.min = min_value
|
|
927
948
|
slider_proto.max = max_value
|
|
928
949
|
slider_proto.step = cast("float", step)
|
|
@@ -937,7 +958,12 @@ class SliderMixin:
|
|
|
937
958
|
if help is not None:
|
|
938
959
|
slider_proto.help = dedent(help)
|
|
939
960
|
|
|
940
|
-
serde = SliderSerde(
|
|
961
|
+
serde = SliderSerde(
|
|
962
|
+
prepared_value,
|
|
963
|
+
data_type,
|
|
964
|
+
single_value,
|
|
965
|
+
orig_tz,
|
|
966
|
+
)
|
|
941
967
|
|
|
942
968
|
widget_state = register_widget(
|
|
943
969
|
slider_proto.id,
|
|
@@ -953,16 +979,16 @@ class SliderMixin:
|
|
|
953
979
|
if widget_state.value_changed:
|
|
954
980
|
# Min/Max bounds checks when the value is updated.
|
|
955
981
|
serialized_values = serde.serialize(widget_state.value)
|
|
956
|
-
for
|
|
982
|
+
for serialized_value in serialized_values:
|
|
957
983
|
# Use the deserialized values for more readable error messages for dates/times
|
|
958
|
-
deserialized_value = serde.deserialize_single_value(
|
|
984
|
+
deserialized_value = serde.deserialize_single_value(serialized_value)
|
|
959
985
|
|
|
960
|
-
if
|
|
986
|
+
if serialized_value < slider_proto.min:
|
|
961
987
|
raise StreamlitValueBelowMinError(
|
|
962
988
|
value=deserialized_value,
|
|
963
989
|
min_value=serde.deserialize_single_value(slider_proto.min),
|
|
964
990
|
)
|
|
965
|
-
if
|
|
991
|
+
if serialized_value > slider_proto.max:
|
|
966
992
|
raise StreamlitValueAboveMaxError(
|
|
967
993
|
value=deserialized_value,
|
|
968
994
|
max_value=serde.deserialize_single_value(slider_proto.max),
|
|
@@ -206,8 +206,8 @@ class TextWidgetsMixin:
|
|
|
206
206
|
on_change : callable
|
|
207
207
|
An optional callback invoked when this text input's value changes.
|
|
208
208
|
|
|
209
|
-
args : tuple
|
|
210
|
-
An optional tuple of args to pass to the callback.
|
|
209
|
+
args : list or tuple
|
|
210
|
+
An optional list or tuple of args to pass to the callback.
|
|
211
211
|
|
|
212
212
|
kwargs : dict
|
|
213
213
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -535,8 +535,8 @@ class TextWidgetsMixin:
|
|
|
535
535
|
on_change : callable
|
|
536
536
|
An optional callback invoked when this text_area's value changes.
|
|
537
537
|
|
|
538
|
-
args : tuple
|
|
539
|
-
An optional tuple of args to pass to the callback.
|
|
538
|
+
args : list or tuple
|
|
539
|
+
An optional list or tuple of args to pass to the callback.
|
|
540
540
|
|
|
541
541
|
kwargs : dict
|
|
542
542
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -420,8 +420,8 @@ class TimeWidgetsMixin:
|
|
|
420
420
|
on_change : callable
|
|
421
421
|
An optional callback invoked when this time_input's value changes.
|
|
422
422
|
|
|
423
|
-
args : tuple
|
|
424
|
-
An optional tuple of args to pass to the callback.
|
|
423
|
+
args : list or tuple
|
|
424
|
+
An optional list or tuple of args to pass to the callback.
|
|
425
425
|
|
|
426
426
|
kwargs : dict
|
|
427
427
|
An optional dict of kwargs to pass to the callback.
|
|
@@ -753,8 +753,8 @@ class TimeWidgetsMixin:
|
|
|
753
753
|
on_change : callable
|
|
754
754
|
An optional callback invoked when this date_input's value changes.
|
|
755
755
|
|
|
756
|
-
args : tuple
|
|
757
|
-
An optional tuple of args to pass to the callback.
|
|
756
|
+
args : list or tuple
|
|
757
|
+
An optional list or tuple of args to pass to the callback.
|
|
758
758
|
|
|
759
759
|
kwargs : dict
|
|
760
760
|
An optional dict of kwargs to pass to the callback.
|
streamlit/elements/write.py
CHANGED
|
@@ -86,7 +86,8 @@ class WriteMixin:
|
|
|
86
86
|
The generator or iterable to stream.
|
|
87
87
|
|
|
88
88
|
If you pass an async generator, Streamlit will internally convert
|
|
89
|
-
it to a sync generator.
|
|
89
|
+
it to a sync generator. If the generator depends on a cached object
|
|
90
|
+
with async references, this can raise an error.
|
|
90
91
|
|
|
91
92
|
.. note::
|
|
92
93
|
To use additional LLM libraries, you can create a wrapper to
|
|
@@ -208,7 +209,7 @@ class WriteMixin:
|
|
|
208
209
|
if type_util.is_type(chunk, "langchain_core.messages.ai.AIMessageChunk"):
|
|
209
210
|
# Try to convert LangChain message chunk to a string:
|
|
210
211
|
try:
|
|
211
|
-
chunk = chunk.content or "" # noqa: PLW2901
|
|
212
|
+
chunk = chunk.content or "" # noqa: PLW2901 # type: ignore[possibly-unbound-attribute]
|
|
212
213
|
except AttributeError as err:
|
|
213
214
|
raise StreamlitAPIException(
|
|
214
215
|
"Failed to parse the LangChain AIMessageChunk. "
|
|
@@ -380,19 +381,19 @@ class WriteMixin:
|
|
|
380
381
|
|
|
381
382
|
Oh, one more thing: ``st.write`` accepts chart objects too! For example:
|
|
382
383
|
|
|
383
|
-
>>> import streamlit as st
|
|
384
|
-
>>> import pandas as pd
|
|
385
|
-
>>> import numpy as np
|
|
386
384
|
>>> import altair as alt
|
|
385
|
+
>>> import pandas as pd
|
|
386
|
+
>>> import streamlit as st
|
|
387
|
+
>>> from numpy.random import default_rng as rng
|
|
387
388
|
>>>
|
|
388
|
-
>>> df = pd.DataFrame(
|
|
389
|
-
>>>
|
|
389
|
+
>>> df = pd.DataFrame(rng(0).standard_normal((200, 3)), columns=["a", "b", "c"])
|
|
390
|
+
>>> chart = (
|
|
390
391
|
... alt.Chart(df)
|
|
391
392
|
... .mark_circle()
|
|
392
393
|
... .encode(x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"])
|
|
393
394
|
... )
|
|
394
395
|
>>>
|
|
395
|
-
>>> st.write(
|
|
396
|
+
>>> st.write(chart)
|
|
396
397
|
|
|
397
398
|
.. output::
|
|
398
399
|
https://doc-vega-lite-chart.streamlit.app/
|
streamlit/env_util.py
CHANGED
|
@@ -19,7 +19,7 @@ import platform
|
|
|
19
19
|
import re
|
|
20
20
|
import sys
|
|
21
21
|
|
|
22
|
-
SYSTEM = platform.system().lower()
|
|
22
|
+
SYSTEM = platform.system().lower() # ty: ignore[unresolved-attribute]
|
|
23
23
|
IS_WINDOWS = SYSTEM == "windows"
|
|
24
24
|
IS_DARWIN = SYSTEM == "darwin"
|
|
25
25
|
IS_LINUX_OR_BSD = (SYSTEM == "linux") or ("bsd" in SYSTEM)
|
streamlit/errors.py
CHANGED
|
@@ -239,22 +239,38 @@ class StreamlitInvalidColumnSpecError(LocalizableStreamlitException):
|
|
|
239
239
|
class StreamlitInvalidVerticalAlignmentError(LocalizableStreamlitException):
|
|
240
240
|
"""Exception raised when an invalid value is specified for vertical_alignment."""
|
|
241
241
|
|
|
242
|
-
def __init__(self, vertical_alignment: str) -> None:
|
|
242
|
+
def __init__(self, vertical_alignment: str, element_type: str) -> None:
|
|
243
243
|
super().__init__(
|
|
244
|
-
|
|
244
|
+
"The `vertical_alignment` argument to `{element_type}` must be "
|
|
245
|
+
'`"top"`, `"center"`, `"bottom"`, or `"distribute"`. \n'
|
|
245
246
|
"The argument passed was {vertical_alignment}.",
|
|
246
247
|
vertical_alignment=vertical_alignment,
|
|
248
|
+
element_type=element_type,
|
|
247
249
|
)
|
|
248
250
|
|
|
249
251
|
|
|
250
252
|
class StreamlitInvalidColumnGapError(LocalizableStreamlitException):
|
|
251
253
|
"""Exception raised when an invalid value is specified for gap."""
|
|
252
254
|
|
|
253
|
-
def __init__(self, gap: str) -> None:
|
|
255
|
+
def __init__(self, gap: str, element_type: str) -> None:
|
|
254
256
|
super().__init__(
|
|
255
|
-
'The `gap` argument to `
|
|
257
|
+
'The `gap` argument to `{element_type}` must be `"small"`, `"medium"`, `"large"`, or `"none"`. \n'
|
|
256
258
|
"The argument passed was {gap}.",
|
|
257
259
|
gap=gap,
|
|
260
|
+
element_type=element_type,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class StreamlitInvalidHorizontalAlignmentError(LocalizableStreamlitException):
|
|
265
|
+
"""Exception raised when an invalid value is specified for horizontal_alignment."""
|
|
266
|
+
|
|
267
|
+
def __init__(self, horizontal_alignment: str, element_type: str) -> None:
|
|
268
|
+
super().__init__(
|
|
269
|
+
"The `horizontal_alignment` argument to `{element_type}` must be "
|
|
270
|
+
'`"left"`, `"center"`, `"right"`, or `"distribute"`. \n'
|
|
271
|
+
"The argument passed was {horizontal_alignment}.",
|
|
272
|
+
horizontal_alignment=horizontal_alignment,
|
|
273
|
+
element_type=element_type,
|
|
258
274
|
)
|
|
259
275
|
|
|
260
276
|
|
streamlit/file_util.py
CHANGED
|
@@ -244,7 +244,7 @@ def normalize_path_join(*args: str) -> str:
|
|
|
244
244
|
str
|
|
245
245
|
The normalized path of the joined path.
|
|
246
246
|
"""
|
|
247
|
-
return os.path.normpath(os.path.join(*args))
|
|
247
|
+
return os.path.normpath(os.path.join(*args)) # ty: ignore[no-matching-overload]
|
|
248
248
|
|
|
249
249
|
|
|
250
250
|
def get_main_script_directory(main_script: str) -> str:
|
streamlit/git_util.py
CHANGED
|
@@ -47,7 +47,7 @@ class GitRepo:
|
|
|
47
47
|
self.repo = git.Repo(path, search_parent_directories=True)
|
|
48
48
|
self.git_version = self.repo.git.version_info
|
|
49
49
|
|
|
50
|
-
if self.git_version >= MIN_GIT_VERSION:
|
|
50
|
+
if self.git_version is not None and self.git_version >= MIN_GIT_VERSION:
|
|
51
51
|
git_root = self.repo.git.rev_parse("--show-toplevel")
|
|
52
52
|
self.module = os.path.relpath(path, git_root)
|
|
53
53
|
except Exception:
|
streamlit/logger.py
CHANGED
|
@@ -18,7 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import logging
|
|
20
20
|
import sys
|
|
21
|
-
from typing import Final
|
|
21
|
+
from typing import Final, cast
|
|
22
22
|
|
|
23
23
|
DEFAULT_LOG_MESSAGE: Final = "%(asctime)s %(levelname) -7s %(name)s: %(message)s"
|
|
24
24
|
|
|
@@ -61,7 +61,7 @@ def setup_formatter(logger: logging.Logger) -> None:
|
|
|
61
61
|
"""Set up the console formatter for a given logger."""
|
|
62
62
|
# Deregister any previous console loggers.
|
|
63
63
|
if hasattr(logger, "streamlit_console_handler"):
|
|
64
|
-
logger.removeHandler(logger.streamlit_console_handler)
|
|
64
|
+
logger.removeHandler(cast("logging.Handler", logger.streamlit_console_handler))
|
|
65
65
|
|
|
66
66
|
logger.streamlit_console_handler = logging.StreamHandler() # type: ignore[attr-defined]
|
|
67
67
|
|