streamlit-nightly 1.45.2.dev20250512__py3-none-any.whl → 1.45.2.dev20250514__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 +1 -0
- streamlit/auth_util.py +6 -6
- streamlit/commands/echo.py +5 -3
- streamlit/commands/execution_control.py +30 -30
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/config.py +7 -7
- streamlit/config_util.py +5 -6
- streamlit/delta_generator.py +4 -1
- streamlit/deprecation_util.py +5 -5
- streamlit/elements/doc_string.py +4 -6
- streamlit/elements/heading.py +3 -4
- streamlit/elements/html.py +3 -4
- streamlit/elements/lib/built_in_chart_utils.py +14 -11
- streamlit/elements/lib/image_utils.py +2 -3
- streamlit/elements/lib/options_selector_utils.py +1 -2
- streamlit/elements/lib/pandas_styler_utils.py +1 -3
- streamlit/elements/lib/policies.py +1 -1
- streamlit/elements/lib/subtitle_utils.py +6 -9
- streamlit/elements/map.py +1 -2
- streamlit/elements/plotly_chart.py +1 -2
- streamlit/elements/spinner.py +1 -1
- streamlit/elements/toast.py +1 -2
- streamlit/elements/vega_charts.py +1 -1
- streamlit/elements/widgets/chat.py +25 -27
- streamlit/elements/widgets/file_uploader.py +2 -2
- streamlit/elements/widgets/radio.py +4 -5
- streamlit/elements/widgets/select_slider.py +9 -11
- streamlit/elements/widgets/slider.py +1 -1
- streamlit/elements/write.py +2 -2
- streamlit/error_util.py +15 -8
- streamlit/errors.py +10 -7
- streamlit/file_util.py +6 -3
- streamlit/git_util.py +26 -21
- streamlit/hello/dataframe_demo.py +1 -1
- streamlit/hello/mapping_demo.py +1 -1
- streamlit/hello/plotting_demo.py +3 -3
- streamlit/hello/streamlit_app.py +1 -1
- streamlit/hello/utils.py +2 -1
- streamlit/navigation/page.py +5 -6
- streamlit/runtime/app_session.py +4 -4
- streamlit/runtime/caching/cache_data_api.py +2 -2
- streamlit/runtime/caching/cache_errors.py +1 -1
- streamlit/runtime/caching/cache_resource_api.py +1 -1
- streamlit/runtime/caching/cache_utils.py +3 -3
- streamlit/runtime/caching/cached_message_replay.py +1 -2
- streamlit/runtime/caching/hashing.py +2 -2
- streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +2 -3
- streamlit/runtime/context.py +1 -5
- streamlit/runtime/credentials.py +4 -4
- streamlit/runtime/forward_msg_queue.py +1 -1
- streamlit/runtime/media_file_manager.py +1 -2
- streamlit/runtime/memory_uploaded_file_manager.py +1 -1
- streamlit/runtime/metrics_util.py +1 -1
- streamlit/runtime/runtime.py +1 -1
- streamlit/runtime/scriptrunner/exec_code.py +1 -1
- streamlit/runtime/scriptrunner/script_cache.py +1 -1
- streamlit/runtime/scriptrunner/script_runner.py +9 -2
- streamlit/runtime/scriptrunner_utils/script_requests.py +3 -3
- streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -3
- streamlit/runtime/secrets.py +6 -7
- streamlit/runtime/state/query_params.py +1 -1
- streamlit/runtime/state/session_state.py +1 -2
- streamlit/runtime/stats.py +1 -1
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.Cfhrjz42.js → ErrorOutline.esm.DbGVRvJi.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.BN5DkI-d.js → FileDownload.esm.Dsazfko3.js} +1 -1
- streamlit/static/static/js/{FileHelper.BWWhRdUs.js → FileHelper.MycXbml-.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.CHPGUkGG.js → FormClearHelper.BBCnWP4b.js} +1 -1
- streamlit/static/static/js/{Hooks.DjxyUmgD.js → Hooks.Cogxcj3O.js} +1 -1
- streamlit/static/static/js/{InputInstructions.Bkai2tFZ.js → InputInstructions.DmFmv5Ss.js} +1 -1
- streamlit/static/static/js/{ProgressBar.DFiqS51i.js → ProgressBar.CL8D7fKU.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.DWTzV71R.js → RenderInPortalIfExists.BIF2_x-k.js} +1 -1
- streamlit/static/static/js/{Toolbar.Dk2A3VxL.js → Toolbar.BiePqUs0.js} +1 -1
- streamlit/static/static/js/{base-input.DfiT3r4p.js → base-input.9-IewVJN.js} +1 -1
- streamlit/static/static/js/{checkbox.DLXFjls2.js → checkbox.CvxVkFoK.js} +1 -1
- streamlit/static/static/js/{createSuper.n2DV0o-4.js → createSuper.CcYwpbOm.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.v1LF25Ml.js → data-grid-overlay-editor.DVakjLUQ.js} +1 -1
- streamlit/static/static/js/{downloader.CI8EFE9Y.js → downloader.DUDYpW4X.js} +1 -1
- streamlit/static/static/js/{es6.CH6Tf3Uw.js → es6.Dd8C3gJG.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.VCjyiSg6.js → iframeResizer.contentWindow.ElqrcVSG.js} +1 -1
- streamlit/static/static/js/{index.7XN_jSTW.js → index.3TsDLcVz.js} +1 -1
- streamlit/static/static/js/{index.CmsMgepL.js → index.8U8I-dVE.js} +1 -1
- streamlit/static/static/js/{index.BROoC18J.js → index.B5gxNAgv.js} +1 -1
- streamlit/static/static/js/{index.B1j5m20t.js → index.BANNX-Et.js} +1 -1
- streamlit/static/static/js/{index.9p279joF.js → index.BRTdJWEL.js} +1 -1
- streamlit/static/static/js/{index.DoM9A12Z.js → index.BYGvkzYg.js} +6 -6
- streamlit/static/static/js/{index.DXDmqevk.js → index.Bgid2lLN.js} +1 -1
- streamlit/static/static/js/{index.BgY_Js0s.js → index.BkpDVBQw.js} +1 -1
- streamlit/static/static/js/{index.CXpQxU0G.js → index.Bud-F2Rk.js} +1 -1
- streamlit/static/static/js/{index.B-Q1qQil.js → index.C-wDYZmi.js} +1 -1
- streamlit/static/static/js/{index.C1P3O0oI.js → index.C44ecW4y.js} +1 -1
- streamlit/static/static/js/{index.STF1QdPr.js → index.CDxF0FlW.js} +1 -1
- streamlit/static/static/js/{index.Ovig-AMR.js → index.CM8qhnIu.js} +5 -5
- streamlit/static/static/js/{index.LqvX_Kr6.js → index.Chn8rXFO.js} +1 -1
- streamlit/static/static/js/{index.CR4eM0Q3.js → index.CkOK3vMg.js} +1 -1
- streamlit/static/static/js/{index.DMDjQhhk.js → index.CssifhIa.js} +1 -1
- streamlit/static/static/js/{index.SPkHHODG.js → index.CtEWZzBM.js} +1 -1
- streamlit/static/static/js/{index.uhNJX5pn.js → index.CwLlrvyN.js} +1 -1
- streamlit/static/static/js/{index.nmbrjghZ.js → index.D0fj09K-.js} +1 -1
- streamlit/static/static/js/{index.BFEA8ufN.js → index.D5Y8GQ-0.js} +1 -1
- streamlit/static/static/js/{index.DcH46Eo2.js → index.D8g5_NeN.js} +1 -1
- streamlit/static/static/js/{index.DM_jnlWC.js → index.DK1C5mv_.js} +1 -1
- streamlit/static/static/js/{index.uN3TP5oq.js → index.DNeEyPk6.js} +1 -1
- streamlit/static/static/js/{index.DKsDSPTo.js → index.DWBlm6kP.js} +1 -1
- streamlit/static/static/js/{index.C9ORVZvA.js → index.DWL3vnFa.js} +1 -1
- streamlit/static/static/js/{index.D1DxKfIm.js → index.DX_Td1Hq.js} +1 -1
- streamlit/static/static/js/{index.hFB9saa3.js → index.DfYxhBCm.js} +1 -1
- streamlit/static/static/js/{index.C1TEsRV0.js → index.DgQ-i_4o.js} +75 -75
- streamlit/static/static/js/{index.D_Bv6KD1.js → index.DiE_wY_P.js} +1 -1
- streamlit/static/static/js/{index.DUU38l7N.js → index.DrVpZAT_.js} +1 -1
- streamlit/static/static/js/{index.BEE4v1Vc.js → index.Dxf51cqQ.js} +1 -1
- streamlit/static/static/js/{index.jZkr87Ly.js → index.Ogd9LUng.js} +1 -1
- streamlit/static/static/js/{index.ZuW7Olhm.js → index.PYQDVW05.js} +1 -1
- streamlit/static/static/js/{index.DgeyRl4J.js → index.QqgppQA_.js} +1 -1
- streamlit/static/static/js/{index.D1An7GDs.js → index.rR2rxOdw.js} +1 -1
- streamlit/static/static/js/{index.BWVpiUBA.js → index.uT7_kc4D.js} +1 -1
- streamlit/static/static/js/{index.Cdsxte9t.js → index.y8UOtxmw.js} +1 -1
- streamlit/static/static/js/{input.BAfiLByr.js → input.D1uIuNvR.js} +1 -1
- streamlit/static/static/js/{memory.CvD1KGKJ.js → memory.C_YLF4Fx.js} +1 -1
- streamlit/static/static/js/{mergeWith.Dy4BuY-h.js → mergeWith.BrhEAUIQ.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.Bl84FLfp.js → number-overlay-editor.Cl4hS5U2.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.gffiKeDQ.js → possibleConstructorReturn.BizCfnoE.js} +1 -1
- streamlit/static/static/js/{sandbox.BXw8ya9t.js → sandbox.BYlf4D-n.js} +1 -1
- streamlit/static/static/js/{textarea.DNNNKi6n.js → textarea.BvMrgzVs.js} +1 -1
- streamlit/static/static/js/{timepicker.CgHlrhoy.js → timepicker.8sMF8VpM.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.MtZ-3vir.js → toConsumableArray.Cl96Bc5x.js} +1 -1
- streamlit/static/static/js/{uniqueId.CFcd6g0d.js → uniqueId.BoXr82qs.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.DadZUraL.js → useBasicWidgetState.DYpB4KjS.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.V6d5TCFH.js → useOnInputChange.D17AAeVI.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.8qpius26.js → withFullScreenWrapper.Lq8QUQxx.js} +1 -1
- streamlit/temporary_directory.py +2 -2
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +7 -9
- streamlit/testing/v1/local_script_runner.py +1 -2
- streamlit/url_util.py +1 -1
- streamlit/watcher/folder_black_list.py +1 -1
- streamlit/watcher/local_sources_watcher.py +5 -3
- streamlit/watcher/path_watcher.py +1 -1
- streamlit/watcher/polling_path_watcher.py +1 -1
- streamlit/watcher/util.py +6 -5
- streamlit/web/bootstrap.py +4 -4
- streamlit/web/cli.py +13 -13
- streamlit/web/server/app_static_file_handler.py +1 -1
- streamlit/web/server/authlib_tornado_integration.py +6 -1
- streamlit/web/server/oauth_authlib_routes.py +3 -3
- streamlit/web/server/oidc_mixin.py +15 -3
- streamlit/web/server/routes.py +11 -11
- streamlit/web/server/stats_request_handler.py +2 -2
- {streamlit_nightly-1.45.2.dev20250512.dist-info → streamlit_nightly-1.45.2.dev20250514.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.45.2.dev20250512.dist-info → streamlit_nightly-1.45.2.dev20250514.dist-info}/RECORD +154 -154
- {streamlit_nightly-1.45.2.dev20250512.dist-info → streamlit_nightly-1.45.2.dev20250514.dist-info}/WHEEL +1 -1
- {streamlit_nightly-1.45.2.dev20250512.data → streamlit_nightly-1.45.2.dev20250514.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.45.2.dev20250512.dist-info → streamlit_nightly-1.45.2.dev20250514.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.45.2.dev20250512.dist-info → streamlit_nightly-1.45.2.dev20250514.dist-info}/top_level.txt +0 -0
streamlit/__init__.py
CHANGED
streamlit/auth_util.py
CHANGED
@@ -32,21 +32,21 @@ if TYPE_CHECKING:
|
|
32
32
|
class AuthCache:
|
33
33
|
"""Simple cache implementation for storing info required for Authlib."""
|
34
34
|
|
35
|
-
def __init__(self):
|
36
|
-
self.cache = {}
|
35
|
+
def __init__(self) -> None:
|
36
|
+
self.cache: dict[str, Any] = {}
|
37
37
|
|
38
|
-
def get(self, key):
|
38
|
+
def get(self, key: str) -> Any:
|
39
39
|
return self.cache.get(key)
|
40
40
|
|
41
41
|
# for set method, we are follow the same signature used in Authlib
|
42
42
|
# the expires_in is not used in our case
|
43
|
-
def set(self, key, value, expires_in): # noqa: ARG002
|
43
|
+
def set(self, key: str, value: Any, expires_in: int | None = None) -> None: # noqa: ARG002
|
44
44
|
self.cache[key] = value
|
45
45
|
|
46
|
-
def get_dict(self):
|
46
|
+
def get_dict(self) -> dict[str, Any]:
|
47
47
|
return self.cache
|
48
48
|
|
49
|
-
def delete(self, key):
|
49
|
+
def delete(self, key: str) -> None:
|
50
50
|
self.cache.pop(key, None)
|
51
51
|
|
52
52
|
|
streamlit/commands/echo.py
CHANGED
@@ -19,12 +19,12 @@ import contextlib
|
|
19
19
|
import re
|
20
20
|
import textwrap
|
21
21
|
import traceback
|
22
|
-
from typing import TYPE_CHECKING, Any
|
22
|
+
from typing import TYPE_CHECKING, Any, Literal
|
23
23
|
|
24
24
|
from streamlit.runtime.metrics_util import gather_metrics
|
25
25
|
|
26
26
|
if TYPE_CHECKING:
|
27
|
-
from collections.abc import Iterable
|
27
|
+
from collections.abc import Generator, Iterable
|
28
28
|
|
29
29
|
_SPACES_RE = re.compile("\\s*")
|
30
30
|
_EMPTY_LINE_RE = re.compile("\\s*\n")
|
@@ -32,7 +32,9 @@ _EMPTY_LINE_RE = re.compile("\\s*\n")
|
|
32
32
|
|
33
33
|
@gather_metrics("echo")
|
34
34
|
@contextlib.contextmanager
|
35
|
-
def echo(
|
35
|
+
def echo(
|
36
|
+
code_location: Literal["above", "below"] = "above",
|
37
|
+
) -> Generator[None, None, None]:
|
36
38
|
"""Use in a `with` block to draw some code on the app, then execute it.
|
37
39
|
|
38
40
|
Parameters
|
@@ -64,38 +64,38 @@ def _new_fragment_id_queue(
|
|
64
64
|
if scope == "app":
|
65
65
|
return []
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
)
|
92
|
-
|
93
|
-
new_queue = list(dropwhile(lambda x: x != ctx.current_fragment_id, curr_queue))
|
94
|
-
assert new_queue, (
|
95
|
-
"Could not find current_fragment_id in fragment_id_queue. This should never happen."
|
67
|
+
# > scope == "fragment"
|
68
|
+
curr_queue = ctx.fragment_ids_this_run
|
69
|
+
|
70
|
+
# If st.rerun(scope="fragment") is called during a full script run, we raise an
|
71
|
+
# exception. This occurs, of course, if st.rerun(scope="fragment") is called
|
72
|
+
# outside of a fragment, but it somewhat surprisingly occurs if it gets called
|
73
|
+
# from within a fragment during a run of the full script. While this behavior may
|
74
|
+
# be surprising, it seems somewhat reasonable given that the correct behavior of
|
75
|
+
# calling st.rerun(scope="fragment") in this situation is unclear to me:
|
76
|
+
# * Rerunning just the fragment immediately may cause weirdness down the line
|
77
|
+
# as any part of the script that occurs after the fragment will not be
|
78
|
+
# executed.
|
79
|
+
# * Waiting until the full script run completes before rerunning the fragment
|
80
|
+
# seems odd (even if we normally do this before running a fragment not
|
81
|
+
# triggered by st.rerun()) because it defers the execution of st.rerun().
|
82
|
+
# * Rerunning the full app feels incorrect as we're seemingly ignoring the
|
83
|
+
# `scope` argument.
|
84
|
+
# With these issues and given that it seems pretty unnatural to have a
|
85
|
+
# fragment-scoped rerun happen during a full script run to begin with, it seems
|
86
|
+
# reasonable to just disallow this completely for now.
|
87
|
+
if not curr_queue:
|
88
|
+
raise StreamlitAPIException(
|
89
|
+
'scope="fragment" can only be specified from `@st.fragment`-decorated '
|
90
|
+
"functions during fragment reruns."
|
96
91
|
)
|
97
92
|
|
98
|
-
|
93
|
+
new_queue = list(dropwhile(lambda x: x != ctx.current_fragment_id, curr_queue))
|
94
|
+
assert new_queue, (
|
95
|
+
"Could not find current_fragment_id in fragment_id_queue. This should never happen."
|
96
|
+
)
|
97
|
+
|
98
|
+
return new_queue
|
99
99
|
|
100
100
|
|
101
101
|
@gather_metrics("rerun")
|
@@ -183,7 +183,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
183
183
|
# other arguments change, and the component's iframe won't be
|
184
184
|
# remounted on the frontend.
|
185
185
|
|
186
|
-
def marshall_element_args():
|
186
|
+
def marshall_element_args() -> None:
|
187
187
|
element.component_instance.json_args = serialized_json_args
|
188
188
|
element.component_instance.special_args.extend(special_args)
|
189
189
|
|
@@ -210,7 +210,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
210
210
|
)
|
211
211
|
element.component_instance.id = computed_id
|
212
212
|
|
213
|
-
def deserialize_component(ui_value):
|
213
|
+
def deserialize_component(ui_value: Any) -> Any:
|
214
214
|
# ui_value is an object from json, an ArrowTable proto, or a bytearray
|
215
215
|
return ui_value
|
216
216
|
|
streamlit/config.py
CHANGED
@@ -1651,7 +1651,7 @@ def _set_development_mode() -> None:
|
|
1651
1651
|
|
1652
1652
|
def on_config_parsed(
|
1653
1653
|
func: Callable[[], None], force_connect: bool = False, lock: bool = False
|
1654
|
-
) -> Callable[[],
|
1654
|
+
) -> Callable[[], None]:
|
1655
1655
|
"""Wait for the config file to be parsed then call func.
|
1656
1656
|
|
1657
1657
|
If the config file has already been parsed, just calls func immediately
|
@@ -1671,7 +1671,7 @@ def on_config_parsed(
|
|
1671
1671
|
|
1672
1672
|
Returns
|
1673
1673
|
-------
|
1674
|
-
Callable[[],
|
1674
|
+
Callable[[], None]
|
1675
1675
|
A function that the caller can use to deregister func.
|
1676
1676
|
"""
|
1677
1677
|
|
@@ -1680,13 +1680,13 @@ def on_config_parsed(
|
|
1680
1680
|
# leading to a memory leak because the Signal will keep a reference of the
|
1681
1681
|
# callable argument. When the callable argument is an object method, then
|
1682
1682
|
# the reference to that object won't be released.
|
1683
|
-
def receiver(_):
|
1684
|
-
|
1683
|
+
def receiver(_: Any) -> None:
|
1684
|
+
func_with_lock()
|
1685
1685
|
|
1686
|
-
def disconnect():
|
1687
|
-
|
1686
|
+
def disconnect() -> None:
|
1687
|
+
_on_config_parsed.disconnect(receiver)
|
1688
1688
|
|
1689
|
-
def func_with_lock():
|
1689
|
+
def func_with_lock() -> None:
|
1690
1690
|
if lock:
|
1691
1691
|
with _config_lock:
|
1692
1692
|
func()
|
streamlit/config_util.py
CHANGED
@@ -54,16 +54,16 @@ def show_config(
|
|
54
54
|
)
|
55
55
|
)
|
56
56
|
|
57
|
-
def append_desc(text):
|
57
|
+
def append_desc(text: str) -> None:
|
58
58
|
out.append("# " + cli_util.style_for_cli(text, bold=True))
|
59
59
|
|
60
|
-
def append_comment(text):
|
60
|
+
def append_comment(text: str) -> None:
|
61
61
|
out.append("# " + cli_util.style_for_cli(text))
|
62
62
|
|
63
|
-
def append_section(text):
|
63
|
+
def append_section(text: str) -> None:
|
64
64
|
out.append(cli_util.style_for_cli(text, bold=True, fg="green"))
|
65
65
|
|
66
|
-
def append_setting(text):
|
66
|
+
def append_setting(text: str) -> None:
|
67
67
|
out.append(cli_util.style_for_cli(text, fg="green"))
|
68
68
|
|
69
69
|
for section in section_descriptions:
|
@@ -178,8 +178,7 @@ def _clean_paragraphs(txt: str) -> list[str]:
|
|
178
178
|
# Strip both leading and trailing newlines.
|
179
179
|
txt = txt.strip("\n")
|
180
180
|
paragraphs = txt.split("\n\n")
|
181
|
-
|
181
|
+
return [
|
182
182
|
"\n".join(_clean(line) for line in paragraph.split("\n"))
|
183
183
|
for paragraph in paragraphs
|
184
184
|
]
|
185
|
-
return cleaned_paragraphs
|
streamlit/delta_generator.py
CHANGED
@@ -522,9 +522,12 @@ class DeltaGenerator(
|
|
522
522
|
|
523
523
|
def _block(
|
524
524
|
self,
|
525
|
-
block_proto: Block_pb2.Block =
|
525
|
+
block_proto: Block_pb2.Block | None = None,
|
526
526
|
dg_type: type | None = None,
|
527
527
|
) -> DeltaGenerator:
|
528
|
+
if block_proto is None:
|
529
|
+
block_proto = Block_pb2.Block()
|
530
|
+
|
528
531
|
# Operate on the active DeltaGenerator, in case we're in a `with` block.
|
529
532
|
dg = self._active_dg
|
530
533
|
|
streamlit/deprecation_util.py
CHANGED
@@ -93,7 +93,7 @@ def deprecate_func_name(
|
|
93
93
|
"""
|
94
94
|
|
95
95
|
@functools.wraps(func)
|
96
|
-
def wrapped_func(*args, **kwargs):
|
96
|
+
def wrapped_func(*args: Any, **kwargs: Any) -> Any:
|
97
97
|
result = func(*args, **kwargs)
|
98
98
|
show_deprecation_warning(
|
99
99
|
make_deprecated_name_warning(
|
@@ -167,7 +167,7 @@ def _create_deprecated_obj_wrapper(obj: TObj, show_warning: Callable[[], Any]) -
|
|
167
167
|
show_warning()
|
168
168
|
|
169
169
|
class Wrapper:
|
170
|
-
def __init__(self):
|
170
|
+
def __init__(self) -> None:
|
171
171
|
# Override all the Wrapped object's magic functions
|
172
172
|
for name in Wrapper._get_magic_functions(obj.__class__):
|
173
173
|
setattr(
|
@@ -176,7 +176,7 @@ def _create_deprecated_obj_wrapper(obj: TObj, show_warning: Callable[[], Any]) -
|
|
176
176
|
property(self._make_magic_function_proxy(name)),
|
177
177
|
)
|
178
178
|
|
179
|
-
def __getattr__(self, attr):
|
179
|
+
def __getattr__(self, attr: str) -> Any:
|
180
180
|
# We handle __getattr__ separately from our other magic
|
181
181
|
# functions. The wrapped class may not actually implement it,
|
182
182
|
# but we still need to implement it to call all its normal
|
@@ -199,8 +199,8 @@ def _create_deprecated_obj_wrapper(obj: TObj, show_warning: Callable[[], Any]) -
|
|
199
199
|
]
|
200
200
|
|
201
201
|
@staticmethod
|
202
|
-
def _make_magic_function_proxy(name):
|
203
|
-
def proxy(
|
202
|
+
def _make_magic_function_proxy(name: str) -> Callable[[Any], Any]:
|
203
|
+
def proxy(_self: Any, *args: Any) -> Any:
|
204
204
|
maybe_show_warning()
|
205
205
|
return getattr(obj, name)
|
206
206
|
|
streamlit/elements/doc_string.py
CHANGED
@@ -283,9 +283,7 @@ def _get_variable_name_from_code_str(code: str) -> str | None:
|
|
283
283
|
):
|
284
284
|
# A common pattern is to add "," at the end of a magic command to make it print.
|
285
285
|
# This removes that final ",", so it looks nicer.
|
286
|
-
|
287
|
-
|
288
|
-
return code
|
286
|
+
return code.removesuffix(",")
|
289
287
|
|
290
288
|
arg_node = _get_stcommand_arg(tree)
|
291
289
|
|
@@ -427,7 +425,7 @@ def _get_weight(value: Any) -> int:
|
|
427
425
|
return 0
|
428
426
|
|
429
427
|
|
430
|
-
def _get_value(obj, var_name):
|
428
|
+
def _get_value(obj: object, var_name: str | None) -> str | None:
|
431
429
|
obj_value = _get_human_readable_value(obj)
|
432
430
|
|
433
431
|
if obj_value is not None:
|
@@ -459,7 +457,7 @@ def _get_value(obj, var_name):
|
|
459
457
|
return obj_value
|
460
458
|
|
461
459
|
|
462
|
-
def _get_human_readable_value(value):
|
460
|
+
def _get_human_readable_value(value: Any) -> str | None:
|
463
461
|
if isinstance(value, Secrets):
|
464
462
|
# Don't want to read secrets.toml because that will show a warning if there's no
|
465
463
|
# secrets.toml file.
|
@@ -508,7 +506,7 @@ def _is_computed_property(obj: object, attr_name: str) -> bool:
|
|
508
506
|
return False
|
509
507
|
|
510
508
|
|
511
|
-
def _get_members(obj):
|
509
|
+
def _get_members(obj: object) -> list[MemberProto]:
|
512
510
|
members_for_sorting = []
|
513
511
|
|
514
512
|
for attr_name in dir(obj):
|
streamlit/elements/heading.py
CHANGED
@@ -262,10 +262,9 @@ class HeadingMixin:
|
|
262
262
|
]
|
263
263
|
if divider in valid_colors:
|
264
264
|
return cast("str", divider)
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
)
|
265
|
+
raise StreamlitAPIException(
|
266
|
+
f"Divider parameter has invalid value: `{divider}`. Please choose from: {', '.join(valid_colors)}."
|
267
|
+
)
|
269
268
|
|
270
269
|
@staticmethod
|
271
270
|
def _create_heading_proto(
|
streamlit/elements/html.py
CHANGED
@@ -113,10 +113,9 @@ class HtmlMixin:
|
|
113
113
|
# If true, there are only style tags - send html to the event container
|
114
114
|
html_proto.body = html_content
|
115
115
|
return self._event_dg._enqueue("html", html_proto)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
return self.dg._enqueue("html", html_proto)
|
116
|
+
# Otherwise, send the html to the main container as normal
|
117
|
+
html_proto.body = html_content
|
118
|
+
return self.dg._enqueue("html", html_proto)
|
120
119
|
|
121
120
|
@property
|
122
121
|
def dg(self) -> DeltaGenerator:
|
@@ -559,7 +559,7 @@ def _melt_data(
|
|
559
559
|
|
560
560
|
# Arrow has problems with object types after melting two different dtypes
|
561
561
|
# > pyarrow.lib.ArrowTypeError: "Expected a <TYPE> object, got a object"
|
562
|
-
|
562
|
+
return dataframe_util.fix_arrow_incompatible_column_types(
|
563
563
|
melted_df,
|
564
564
|
selected_columns=[
|
565
565
|
*columns_to_leave_alone,
|
@@ -568,8 +568,6 @@ def _melt_data(
|
|
568
568
|
],
|
569
569
|
)
|
570
570
|
|
571
|
-
return fixed_df
|
572
|
-
|
573
571
|
|
574
572
|
def _maybe_reset_index_in_place(
|
575
573
|
df: pd.DataFrame, x_column: str | None, y_column_list: list[str]
|
@@ -954,7 +952,9 @@ def _get_color_encoding(
|
|
954
952
|
# If the color value is color-like, return that.
|
955
953
|
if is_color_like(cast("Any", color_value)):
|
956
954
|
if len(y_column_list) != 1:
|
957
|
-
raise StreamlitColorLengthError(
|
955
|
+
raise StreamlitColorLengthError(
|
956
|
+
[color_value] if color_value else [], y_column_list
|
957
|
+
)
|
958
958
|
|
959
959
|
return alt.ColorValue(to_css_color(cast("Any", color_value)))
|
960
960
|
|
@@ -975,7 +975,7 @@ def _get_color_encoding(
|
|
975
975
|
title=" ",
|
976
976
|
)
|
977
977
|
|
978
|
-
raise StreamlitInvalidColorError(
|
978
|
+
raise StreamlitInvalidColorError(color_from_user)
|
979
979
|
|
980
980
|
if color_column is not None:
|
981
981
|
column_type: VegaLiteType
|
@@ -1132,7 +1132,7 @@ def _get_y_encoding_type(
|
|
1132
1132
|
|
1133
1133
|
|
1134
1134
|
class StreamlitColumnNotFoundError(StreamlitAPIException):
|
1135
|
-
def __init__(self, df, col_name, *args):
|
1135
|
+
def __init__(self, df: pd.DataFrame, col_name: str, *args: Any) -> None:
|
1136
1136
|
available_columns = ", ".join(str(c) for c in list(df.columns))
|
1137
1137
|
message = (
|
1138
1138
|
f'Data does not have a column named `"{col_name}"`. '
|
@@ -1142,8 +1142,7 @@ class StreamlitColumnNotFoundError(StreamlitAPIException):
|
|
1142
1142
|
|
1143
1143
|
|
1144
1144
|
class StreamlitInvalidColorError(StreamlitAPIException):
|
1145
|
-
def __init__(self,
|
1146
|
-
", ".join(str(c) for c in list(df.columns))
|
1145
|
+
def __init__(self, color_from_user: str | Color | list[Color] | None) -> None:
|
1147
1146
|
message = f"""
|
1148
1147
|
This does not look like a valid color argument: `{color_from_user}`.
|
1149
1148
|
|
@@ -1156,14 +1155,18 @@ The color argument can be:
|
|
1156
1155
|
* The name of a column.
|
1157
1156
|
* Or a list of colors, matching the number of y columns to draw.
|
1158
1157
|
"""
|
1159
|
-
super().__init__(message
|
1158
|
+
super().__init__(message)
|
1160
1159
|
|
1161
1160
|
|
1162
1161
|
class StreamlitColorLengthError(StreamlitAPIException):
|
1163
|
-
def __init__(
|
1162
|
+
def __init__(
|
1163
|
+
self,
|
1164
|
+
color_values: str | Color | Collection[Color] | None,
|
1165
|
+
y_column_list: list[str],
|
1166
|
+
) -> None:
|
1164
1167
|
message = (
|
1165
1168
|
f"The list of colors `{color_values}` must have the same "
|
1166
1169
|
"length as the list of columns to be colored "
|
1167
1170
|
f"`{y_column_list}`."
|
1168
1171
|
)
|
1169
|
-
super().__init__(message
|
1172
|
+
super().__init__(message)
|
@@ -335,9 +335,8 @@ def image_to_url(
|
|
335
335
|
url = runtime.get_instance().media_file_mgr.add(image_data, mimetype, image_id)
|
336
336
|
caching.save_media_data(image_data, mimetype, image_id)
|
337
337
|
return url
|
338
|
-
|
339
|
-
|
340
|
-
return ""
|
338
|
+
# When running in "raw mode", we can't access the MediaFileManager.
|
339
|
+
return ""
|
341
340
|
|
342
341
|
|
343
342
|
def _4d_to_list_3d(array: npt.NDArray[Any]) -> list[npt.NDArray[Any]]:
|
@@ -92,8 +92,7 @@ def get_default_indices(
|
|
92
92
|
indexable_options: Sequence[T], default: Sequence[Any] | Any | None = None
|
93
93
|
) -> list[int]:
|
94
94
|
default_indices = check_and_convert_to_indices(indexable_options, default)
|
95
|
-
|
96
|
-
return default_indices
|
95
|
+
return default_indices if default_indices is not None else []
|
97
96
|
|
98
97
|
|
99
98
|
E1 = TypeVar("E1", bound=Enum)
|
@@ -213,9 +213,7 @@ def _pandas_style_to_css(
|
|
213
213
|
selector = ", ".join(selectors)
|
214
214
|
|
215
215
|
declaration_block = "; ".join(declarations)
|
216
|
-
|
217
|
-
|
218
|
-
return rule_set
|
216
|
+
return selector + " { " + declaration_block + " }"
|
219
217
|
|
220
218
|
|
221
219
|
def _marshall_display_values(
|
@@ -104,9 +104,7 @@ def _srt_to_vtt(srt_data: str | bytes) -> bytes:
|
|
104
104
|
# Add WebVTT file header
|
105
105
|
vtt_content = "WEBVTT\n\n" + vtt_data
|
106
106
|
# Convert the vtt content to bytes
|
107
|
-
|
108
|
-
|
109
|
-
return vtt_content
|
107
|
+
return vtt_content.strip().encode("utf-8")
|
110
108
|
|
111
109
|
|
112
110
|
def _handle_string_or_path_data(data_or_path: str | Path) -> bytes:
|
@@ -123,14 +121,14 @@ def _handle_string_or_path_data(data_or_path: str | Path) -> bytes:
|
|
123
121
|
with open(data_or_path, "rb") as file:
|
124
122
|
content = file.read()
|
125
123
|
return _srt_to_vtt(content) if file_extension == ".srt" else content
|
126
|
-
|
127
|
-
raise ValueError(f"File {data_or_path} does not exist.")
|
124
|
+
if isinstance(data_or_path, Path):
|
125
|
+
raise ValueError(f"File {data_or_path} does not exist.") # noqa: TRY004
|
128
126
|
|
129
127
|
content_string = data_or_path.strip()
|
130
128
|
|
131
129
|
if content_string.startswith("WEBVTT") or content_string == "":
|
132
130
|
return content_string.encode("utf-8")
|
133
|
-
|
131
|
+
if _is_srt(content_string):
|
134
132
|
return _srt_to_vtt(content_string)
|
135
133
|
raise ValueError("The provided string neither matches valid VTT nor SRT format.")
|
136
134
|
|
@@ -173,6 +171,5 @@ def process_subtitle_data(
|
|
173
171
|
)
|
174
172
|
caching.save_media_data(subtitle_data, "text/vtt", coordinates)
|
175
173
|
return file_url
|
176
|
-
|
177
|
-
|
178
|
-
return ""
|
174
|
+
# When running in "raw mode", we can't access the MediaFileManager.
|
175
|
+
return ""
|
streamlit/elements/map.py
CHANGED
@@ -357,8 +357,7 @@ def _get_lat_or_lon_col_name(
|
|
357
357
|
f"Map data must contain a {human_readable_name} column named: "
|
358
358
|
f"{formatted_allowed_col_name}. Existing columns: {formmated_col_names}"
|
359
359
|
)
|
360
|
-
|
361
|
-
col_name = candidate_col_name
|
360
|
+
col_name = candidate_col_name
|
362
361
|
|
363
362
|
# Check that the column is well-formed.
|
364
363
|
# IMPLEMENTATION NOTE: We can't use isnull().values.any() because .values can return
|
@@ -537,8 +537,7 @@ class PlotlyMixin:
|
|
537
537
|
|
538
538
|
self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
539
539
|
return cast("PlotlyState", widget_state.value)
|
540
|
-
|
541
|
-
return self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
540
|
+
return self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
542
541
|
|
543
542
|
@property
|
544
543
|
def dg(self) -> DeltaGenerator:
|
streamlit/elements/spinner.py
CHANGED
streamlit/elements/toast.py
CHANGED
@@ -360,7 +360,7 @@ def _convert_altair_to_vega_lite_spec(
|
|
360
360
|
datasets[name] = data_bytes
|
361
361
|
return {"name": name}
|
362
362
|
|
363
|
-
alt.data_transformers.register("id", id_transform) # type: ignore[attr-defined,unused-ignore]
|
363
|
+
alt.data_transformers.register("id", id_transform) # type: ignore[arg-type,attr-defined,unused-ignore]
|
364
364
|
|
365
365
|
# The default altair theme has some width/height defaults defined
|
366
366
|
# which are not useful for Streamlit. Therefore, we change the theme to
|
@@ -127,7 +127,7 @@ def _process_avatar_input(
|
|
127
127
|
|
128
128
|
if avatar is None:
|
129
129
|
return AvatarType.ICON, ""
|
130
|
-
|
130
|
+
if isinstance(avatar, str) and avatar in {item.value for item in PresetNames}:
|
131
131
|
# On the frontend, we only support "assistant" and "user" for the avatar.
|
132
132
|
return (
|
133
133
|
AvatarType.ICON,
|
@@ -137,25 +137,24 @@ def _process_avatar_input(
|
|
137
137
|
else "user"
|
138
138
|
),
|
139
139
|
)
|
140
|
-
|
140
|
+
if isinstance(avatar, str) and is_emoji(avatar):
|
141
141
|
return AvatarType.EMOJI, avatar
|
142
142
|
|
143
|
-
|
143
|
+
if isinstance(avatar, str) and avatar.startswith(":material"):
|
144
144
|
return AvatarType.ICON, validate_material_icon(avatar)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
) from ex
|
145
|
+
try:
|
146
|
+
return AvatarType.IMAGE, image_to_url(
|
147
|
+
avatar,
|
148
|
+
width=WidthBehavior.ORIGINAL,
|
149
|
+
clamp=False,
|
150
|
+
channels="RGB",
|
151
|
+
output_format="auto",
|
152
|
+
image_id=delta_path,
|
153
|
+
)
|
154
|
+
except Exception as ex:
|
155
|
+
raise StreamlitAPIException(
|
156
|
+
"Failed to load the provided avatar value as an image."
|
157
|
+
) from ex
|
159
158
|
|
160
159
|
|
161
160
|
def _pop_upload_files(
|
@@ -208,16 +207,15 @@ class ChatInputSerde:
|
|
208
207
|
return None
|
209
208
|
if not self.accept_files:
|
210
209
|
return ui_value.data
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
)
|
210
|
+
uploaded_files = _pop_upload_files(ui_value.file_uploader_state)
|
211
|
+
for file in uploaded_files:
|
212
|
+
if self.allowed_types and not isinstance(file, DeletedFile):
|
213
|
+
enforce_filename_restriction(file.name, self.allowed_types)
|
214
|
+
|
215
|
+
return ChatInputValue(
|
216
|
+
text=ui_value.data,
|
217
|
+
files=uploaded_files,
|
218
|
+
)
|
221
219
|
|
222
220
|
def serialize(self, v: str | None) -> ChatInputValueProto:
|
223
221
|
return ChatInputValueProto(data=v)
|
@@ -127,7 +127,7 @@ class FileUploaderSerde:
|
|
127
127
|
|
128
128
|
if not files:
|
129
129
|
return state_proto
|
130
|
-
|
130
|
+
if not isinstance(files, list):
|
131
131
|
files = [files]
|
132
132
|
|
133
133
|
for f in files:
|
@@ -497,7 +497,7 @@ class FileUploaderMixin:
|
|
497
497
|
|
498
498
|
if isinstance(widget_state.value, DeletedFile):
|
499
499
|
return None
|
500
|
-
|
500
|
+
if isinstance(widget_state.value, list):
|
501
501
|
return [f for f in widget_state.value if not isinstance(f, DeletedFile)]
|
502
502
|
|
503
503
|
return widget_state.value
|