streamlit-nightly 1.45.2.dev20250527__py3-none-any.whl → 1.45.2.dev20250528__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamlit/auth_util.py +3 -3
- streamlit/commands/echo.py +1 -1
- streamlit/config.py +14 -12
- streamlit/config_option.py +3 -5
- streamlit/config_util.py +4 -5
- streamlit/connections/snowflake_connection.py +4 -3
- streamlit/elements/arrow.py +1 -0
- streamlit/elements/deck_gl_json_chart.py +1 -0
- streamlit/elements/exception.py +4 -12
- streamlit/elements/graphviz_chart.py +1 -1
- streamlit/elements/heading.py +3 -4
- streamlit/elements/lib/image_utils.py +2 -3
- streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
- streamlit/elements/lib/utils.py +15 -0
- streamlit/elements/markdown.py +1 -1
- streamlit/elements/media.py +1 -1
- streamlit/elements/plotly_chart.py +1 -0
- streamlit/elements/progress.py +3 -3
- streamlit/elements/spinner.py +5 -4
- streamlit/elements/vega_charts.py +1 -0
- streamlit/elements/widgets/audio_input.py +1 -0
- streamlit/elements/widgets/button.py +3 -1
- streamlit/elements/widgets/button_group.py +1 -0
- streamlit/elements/widgets/camera_input.py +1 -0
- streamlit/elements/widgets/chat.py +2 -1
- streamlit/elements/widgets/checkbox.py +1 -0
- streamlit/elements/widgets/color_picker.py +9 -14
- streamlit/elements/widgets/data_editor.py +3 -2
- streamlit/elements/widgets/file_uploader.py +1 -0
- streamlit/elements/widgets/multiselect.py +1 -0
- streamlit/elements/widgets/number_input.py +1 -0
- streamlit/elements/widgets/radio.py +2 -1
- streamlit/elements/widgets/select_slider.py +1 -0
- streamlit/elements/widgets/selectbox.py +2 -1
- streamlit/elements/widgets/slider.py +25 -32
- streamlit/elements/widgets/text_widgets.py +3 -2
- streamlit/elements/widgets/time_widgets.py +2 -0
- streamlit/hello/animation_demo.py +9 -9
- streamlit/hello/dataframe_demo.py +2 -2
- streamlit/hello/mapping_demo.py +5 -6
- streamlit/logger.py +1 -1
- streamlit/runtime/app_session.py +11 -8
- streamlit/runtime/caching/hashing.py +8 -9
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +3 -3
- streamlit/runtime/connection_factory.py +12 -12
- streamlit/runtime/credentials.py +13 -26
- streamlit/runtime/runtime_util.py +2 -2
- streamlit/runtime/scriptrunner/script_runner.py +8 -7
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.qteVcUUN.js → ErrorOutline.esm.CtshIbC5.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.ncu7N-Hr.js → FileDownload.esm.A0XrMp_A.js} +1 -1
- streamlit/static/static/js/{FileHelper.zsMZ7RXt.js → FileHelper.BkYmOfR4.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.W8yVYXZp.js → FormClearHelper.DvUrjO5s.js} +1 -1
- streamlit/static/static/js/{Hooks.DBj6srQ1.js → Hooks.Dw0PPeMp.js} +1 -1
- streamlit/static/static/js/{InputInstructions.BobLsJJb.js → InputInstructions.BwkpOG-3.js} +1 -1
- streamlit/static/static/js/{ProgressBar.CtvJrIzN.js → ProgressBar.Po8toa5U.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.DnT_UdzV.js → RenderInPortalIfExists.DG7izwhP.js} +1 -1
- streamlit/static/static/js/{Toolbar.BVF7NtOB.js → Toolbar.zoRxypF9.js} +1 -1
- streamlit/static/static/js/{base-input.B4sdS3vw.js → base-input.3hmq5vR4.js} +1 -1
- streamlit/static/static/js/{checkbox.DKDitzF8.js → checkbox.DHVebTBP.js} +1 -1
- streamlit/static/static/js/{createSuper.mhx956J9.js → createSuper.CCzF882j.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.CmXS0PAX.js → data-grid-overlay-editor.CRIS0V5u.js} +1 -1
- streamlit/static/static/js/{downloader.Cnd9SuxG.js → downloader.DOuJ7F43.js} +1 -1
- streamlit/static/static/js/{es6.DM-pf09u.js → es6.BojNhy97.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.Gc5GAjZM.js → iframeResizer.contentWindow.CmN7IDO7.js} +1 -1
- streamlit/static/static/js/{index.WWYmGCrM.js → index.3HscCA0Q.js} +1 -1
- streamlit/static/static/js/{index.BV38yp5k.js → index.B0GUCtHl.js} +1 -1
- streamlit/static/static/js/{index.DdyZtGcg.js → index.B3Y99Usz.js} +1 -1
- streamlit/static/static/js/{index.DIyx-z1Q.js → index.B6guKn0h.js} +1 -1
- streamlit/static/static/js/{index.CjBaoWYr.js → index.BEfxU01i.js} +1 -1
- streamlit/static/static/js/{index.BfusYuD8.js → index.BMWx_YQD.js} +1 -1
- streamlit/static/static/js/{index.BWTBe3a1.js → index.BV-8GugV.js} +1 -1
- streamlit/static/static/js/{index.gBOr8z2K.js → index.BXfm7UZe.js} +1 -1
- streamlit/static/static/js/{index.CWgnk1N4.js → index.BfcdLS9y.js} +1 -1
- streamlit/static/static/js/{index.COBionvf.js → index.BgmEuudT.js} +1 -1
- streamlit/static/static/js/{index.DQGSbu2C.js → index.BsiojTxz.js} +1 -1
- streamlit/static/static/js/{index.I3iNnzJx.js → index.BvWDoWjf.js} +1 -1
- streamlit/static/static/js/{index.p2Wl4zMi.js → index.CLFnBokZ.js} +1 -1
- streamlit/static/static/js/{index.DOl-SOKu.js → index.CPiByGGr.js} +1 -1
- streamlit/static/static/js/{index.C_2m4F7k.js → index.CTVSiPCo.js} +1 -1
- streamlit/static/static/js/{index.DTU7qmDP.js → index.CVxkW_lc.js} +1 -1
- streamlit/static/static/js/{index.BkLkRTpZ.js → index.CWweAMBx.js} +1 -1
- streamlit/static/static/js/{index.BR-S54Iv.js → index.CZ6f-p0K.js} +1 -1
- streamlit/static/static/js/{index.B45ExNhw.js → index.CdgLDqMc.js} +1 -1
- streamlit/static/static/js/{index.DAvhwYMG.js → index.Cpz3pp0B.js} +1 -1
- streamlit/static/static/js/{index.CJ-XXd1r.js → index.CzMgwzgb.js} +1 -1
- streamlit/static/static/js/{index.DOYomqqU.js → index.DH2YAEv6.js} +1 -1
- streamlit/static/static/js/{index.B0E6Rv1F.js → index.DNlMgaSP.js} +1 -1
- streamlit/static/static/js/{index.CgOynO1t.js → index.DP7RHJHC.js} +1 -1
- streamlit/static/static/js/{index.B29JQLHa.js → index.DcLQo3NB.js} +5 -5
- streamlit/static/static/js/{index.BJQNG4O1.js → index.DkNaEiLi.js} +1 -1
- streamlit/static/static/js/{index.BONHiJUZ.js → index.DtpZrdsz.js} +1 -1
- streamlit/static/static/js/{index.AWkO-7e-.js → index.HdiDLe37.js} +1 -1
- streamlit/static/static/js/{index.B6xTo8b8.js → index.Ih0EXMso.js} +1 -1
- streamlit/static/static/js/{index.vOqxh1m2.js → index.R5J-UXhx.js} +1 -1
- streamlit/static/static/js/{index.D4XRYl23.js → index.VVmp3qV7.js} +1 -1
- streamlit/static/static/js/{index.DwUISpCs.js → index.YePOPnW6.js} +5 -5
- streamlit/static/static/js/{index.BNNR5Jmd.js → index.YtwVjbe-.js} +1 -1
- streamlit/static/static/js/{index._BaeK1t7.js → index.kWUcv9pK.js} +1 -1
- streamlit/static/static/js/{index.CkKptP1T.js → index.muQ-sA7D.js} +1 -1
- streamlit/static/static/js/{index.C5KKmyWy.js → index.p5qVS5RU.js} +1 -1
- streamlit/static/static/js/{index.CZ5fZcT5.js → index.whcmqOYZ.js} +1 -1
- streamlit/static/static/js/{input.BvD9DHLa.js → input.C95vVzrH.js} +1 -1
- streamlit/static/static/js/{memory.DCVB1HOm.js → memory.lfILky3m.js} +1 -1
- streamlit/static/static/js/{mergeWith.BqTORFAq.js → mergeWith.CdpKbzWl.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.VB_OvuPv.js → number-overlay-editor.D2TjUrKf.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.DhYxBDlj.js → possibleConstructorReturn.DQV58bYB.js} +1 -1
- streamlit/static/static/js/{sandbox.CoN7LRFk.js → sandbox.R1dhBCnm.js} +1 -1
- streamlit/static/static/js/{textarea.DkHpIjdT.js → textarea.t5D4QCw3.js} +1 -1
- streamlit/static/static/js/{timepicker.C8UIzYhf.js → timepicker.BI9iPIxz.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.DXfr1fvT.js → toConsumableArray.COyXrPhy.js} +1 -1
- streamlit/static/static/js/{uniqueId.CgrMSBTb.js → uniqueId.CaWObuU_.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.C-e-WEFS.js → useBasicWidgetState.Wd2TSACf.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.CtRJhZD6.js → useOnInputChange.CUFXty-S.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.od0SAvAK.js → withFullScreenWrapper.wgkD5MeK.js} +1 -1
- streamlit/watcher/local_sources_watcher.py +1 -1
- streamlit/watcher/path_watcher.py +2 -3
- streamlit/web/bootstrap.py +1 -1
- streamlit/web/cli.py +5 -5
- streamlit/web/server/authlib_tornado_integration.py +3 -3
- streamlit/web/server/oauth_authlib_routes.py +4 -2
- streamlit/web/server/oidc_mixin.py +6 -5
- streamlit/web/server/server.py +1 -1
- {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250528.dist-info}/METADATA +2 -2
- {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250528.dist-info}/RECORD +129 -129
- {streamlit_nightly-1.45.2.dev20250527.data → streamlit_nightly-1.45.2.dev20250528.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250528.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250528.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250528.dist-info}/top_level.txt +0 -0
streamlit/auth_util.py
CHANGED
@@ -53,7 +53,7 @@ class AuthCache:
|
|
53
53
|
def is_authlib_installed() -> bool:
|
54
54
|
"""Check if Authlib is installed."""
|
55
55
|
try:
|
56
|
-
import authlib
|
56
|
+
import authlib
|
57
57
|
|
58
58
|
authlib_version = authlib.__version__
|
59
59
|
authlib_version_tuple = tuple(map(int, authlib_version.split(".")))
|
@@ -87,7 +87,7 @@ def get_secrets_auth_section() -> AttrDict:
|
|
87
87
|
def encode_provider_token(provider: str) -> str:
|
88
88
|
"""Returns a signed JWT token with the provider and expiration time."""
|
89
89
|
try:
|
90
|
-
from authlib.jose import jwt
|
90
|
+
from authlib.jose import jwt
|
91
91
|
except ImportError:
|
92
92
|
raise StreamlitAuthError(
|
93
93
|
"""To use authentication features, you need to install Authlib>=1.3.2, e.g. via `pip install Authlib`."""
|
@@ -116,7 +116,7 @@ def decode_provider_token(provider_token: str) -> ProviderTokenPayload:
|
|
116
116
|
# the 'exp' (and it is not expired), and 'provider' field exists.
|
117
117
|
claim_options = {"exp": {"essential": True}, "provider": {"essential": True}}
|
118
118
|
try:
|
119
|
-
payload: JWTClaims = jwt.decode(
|
119
|
+
payload: JWTClaims = jwt.decode( # type: ignore[no-untyped-call]
|
120
120
|
provider_token, get_signing_secret(), claims_options=claim_options
|
121
121
|
)
|
122
122
|
payload.validate()
|
streamlit/commands/echo.py
CHANGED
@@ -101,7 +101,7 @@ def echo(
|
|
101
101
|
show_code(code_string, "python")
|
102
102
|
|
103
103
|
except FileNotFoundError as err:
|
104
|
-
show_warning("Unable to display code.
|
104
|
+
show_warning(f"Unable to display code. {err}")
|
105
105
|
|
106
106
|
|
107
107
|
def _get_initial_indent(lines: Iterable[str]) -> int:
|
streamlit/config.py
CHANGED
@@ -167,7 +167,7 @@ def set_user_option(key: str, value: Any) -> None:
|
|
167
167
|
|
168
168
|
raise StreamlitAPIException(
|
169
169
|
f"{key} cannot be set on the fly. Set as command line option, e.g. "
|
170
|
-
"streamlit run script.py --{key}, or in config.toml instead."
|
170
|
+
f"streamlit run script.py --{key}, or in config.toml instead."
|
171
171
|
)
|
172
172
|
|
173
173
|
|
@@ -1301,7 +1301,8 @@ def get_where_defined(key: str) -> str:
|
|
1301
1301
|
config_options = get_config_options()
|
1302
1302
|
|
1303
1303
|
if key not in config_options:
|
1304
|
-
|
1304
|
+
msg = f'Config key "{key}" not defined.'
|
1305
|
+
raise RuntimeError(msg)
|
1305
1306
|
return config_options[key].where_defined
|
1306
1307
|
|
1307
1308
|
|
@@ -1380,11 +1381,12 @@ def _set_option(key: str, value: Any, where_defined: str) -> None:
|
|
1380
1381
|
# Import logger locally to prevent circular references
|
1381
1382
|
from streamlit.logger import get_logger
|
1382
1383
|
|
1383
|
-
|
1384
|
+
logger: Final = get_logger(__name__)
|
1384
1385
|
|
1385
|
-
|
1386
|
-
|
1387
|
-
"option set, it may have been removed."
|
1386
|
+
logger.warning(
|
1387
|
+
'"%s" is not a valid config option. If you previously had this config '
|
1388
|
+
"option set, it may have been removed.",
|
1389
|
+
key,
|
1388
1390
|
)
|
1389
1391
|
|
1390
1392
|
else:
|
@@ -1505,9 +1507,9 @@ def _maybe_read_env_variable(value: Any) -> Any:
|
|
1505
1507
|
# Import logger locally to prevent circular references
|
1506
1508
|
from streamlit.logger import get_logger
|
1507
1509
|
|
1508
|
-
|
1510
|
+
logger: Final = get_logger(__name__)
|
1509
1511
|
|
1510
|
-
|
1512
|
+
logger.error("No environment variable called %s", var_name)
|
1511
1513
|
else:
|
1512
1514
|
return _maybe_convert_to_number(env_var)
|
1513
1515
|
|
@@ -1607,8 +1609,8 @@ def get_config_options(
|
|
1607
1609
|
# Import logger locally to prevent circular references.
|
1608
1610
|
from streamlit.logger import get_logger
|
1609
1611
|
|
1610
|
-
|
1611
|
-
|
1612
|
+
logger: Final = get_logger(__name__)
|
1613
|
+
logger.warning(
|
1612
1614
|
"An update to the [server] config option section was detected."
|
1613
1615
|
" To have these changes be reflected, please restart streamlit."
|
1614
1616
|
)
|
@@ -1628,7 +1630,7 @@ def _check_conflicts() -> None:
|
|
1628
1630
|
# Import logger locally to prevent circular references
|
1629
1631
|
from streamlit.logger import get_logger
|
1630
1632
|
|
1631
|
-
|
1633
|
+
logger: Final = get_logger(__name__)
|
1632
1634
|
|
1633
1635
|
if get_option("global.developmentMode"):
|
1634
1636
|
if not _is_unset("server.port"):
|
@@ -1645,7 +1647,7 @@ def _check_conflicts() -> None:
|
|
1645
1647
|
if get_option("server.enableXsrfProtection") and (
|
1646
1648
|
not get_option("server.enableCORS") or get_option("global.developmentMode")
|
1647
1649
|
):
|
1648
|
-
|
1650
|
+
logger.warning(
|
1649
1651
|
"""
|
1650
1652
|
Warning: the config option 'server.enableCORS=false' is not compatible with
|
1651
1653
|
'server.enableXsrfProtection=true'.
|
streamlit/config_option.py
CHANGED
@@ -189,7 +189,7 @@ class ConfigOption:
|
|
189
189
|
if self.replaced_by:
|
190
190
|
self.deprecated = True
|
191
191
|
if deprecation_text is None:
|
192
|
-
deprecation_text = "Replaced by
|
192
|
+
deprecation_text = f"Replaced by {self.replaced_by}."
|
193
193
|
|
194
194
|
if self.deprecated:
|
195
195
|
if not expiration_date:
|
@@ -261,8 +261,7 @@ class ConfigOption:
|
|
261
261
|
# Import here to avoid circular imports
|
262
262
|
from streamlit.logger import get_logger
|
263
263
|
|
264
|
-
|
265
|
-
LOGGER.error(
|
264
|
+
get_logger(__name__).error(
|
266
265
|
textwrap.dedent(
|
267
266
|
f"""
|
268
267
|
════════════════════════════════════════════════
|
@@ -279,8 +278,7 @@ class ConfigOption:
|
|
279
278
|
# Import here to avoid circular imports
|
280
279
|
from streamlit.logger import get_logger
|
281
280
|
|
282
|
-
|
283
|
-
LOGGER.warning(
|
281
|
+
get_logger(__name__).warning(
|
284
282
|
textwrap.dedent(
|
285
283
|
f"""s
|
286
284
|
════════════════════════════════════════════════
|
streamlit/config_util.py
CHANGED
@@ -84,7 +84,7 @@ def show_config(
|
|
84
84
|
continue
|
85
85
|
|
86
86
|
out.append("")
|
87
|
-
append_section("[
|
87
|
+
append_section(f"[{section}]")
|
88
88
|
out.append("")
|
89
89
|
|
90
90
|
for option in section_options.values():
|
@@ -125,8 +125,7 @@ def show_config(
|
|
125
125
|
append_comment(line)
|
126
126
|
append_comment("")
|
127
127
|
append_comment(
|
128
|
-
"This option will be removed on or after
|
129
|
-
% option.expiration_date
|
128
|
+
f"This option will be removed on or after {option.expiration_date}."
|
130
129
|
)
|
131
130
|
|
132
131
|
import toml
|
@@ -138,7 +137,7 @@ def show_config(
|
|
138
137
|
# Ensure a line break before appending "Default" comment, if not already there
|
139
138
|
if out[-1] != "#":
|
140
139
|
append_comment("")
|
141
|
-
append_comment("Default:
|
140
|
+
append_comment(f"Default: {toml_default}")
|
142
141
|
else:
|
143
142
|
# Don't say "Default: (unset)" here because this branch applies
|
144
143
|
# to complex config settings too.
|
@@ -151,7 +150,7 @@ def show_config(
|
|
151
150
|
if option_is_manually_set:
|
152
151
|
if out[-1] != "# ":
|
153
152
|
append_comment("")
|
154
|
-
append_comment("The value below was set in
|
153
|
+
append_comment(f"The value below was set in {option.where_defined}")
|
155
154
|
|
156
155
|
toml_setting = toml.dumps({key: option.value})
|
157
156
|
|
@@ -41,6 +41,10 @@ if TYPE_CHECKING:
|
|
41
41
|
SnowflakeConnection as InternalSnowflakeConnection,
|
42
42
|
)
|
43
43
|
|
44
|
+
# the ANSI-compliant SQL code for "connection was not established"
|
45
|
+
# (see docs: https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-api#id6)
|
46
|
+
SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED: Final = "08001"
|
47
|
+
|
44
48
|
|
45
49
|
class SnowflakeConnection(BaseConnection["InternalSnowflakeConnection"]):
|
46
50
|
"""A connection to Snowflake using the Snowflake Connector for Python.
|
@@ -335,9 +339,6 @@ class SnowflakeConnection(BaseConnection["InternalSnowflakeConnection"]):
|
|
335
339
|
"""
|
336
340
|
from tenacity import retry, retry_if_exception, stop_after_attempt, wait_fixed
|
337
341
|
|
338
|
-
# the ANSI-compliant SQL code for "connection was not established" (see docs: https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-api#id6)
|
339
|
-
SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED = "08001"
|
340
|
-
|
341
342
|
@retry(
|
342
343
|
after=lambda _: self.reset(),
|
343
344
|
stop=stop_after_attempt(3),
|
streamlit/elements/arrow.py
CHANGED
@@ -508,6 +508,7 @@ class PydeckMixin:
|
|
508
508
|
pydeck_proto.id = compute_and_register_element_id(
|
509
509
|
"deck_gl_json_chart",
|
510
510
|
user_key=key,
|
511
|
+
dg=self.dg,
|
511
512
|
is_selection_activated=is_selection_activated,
|
512
513
|
selection_mode=selection_mode,
|
513
514
|
use_container_width=use_container_width,
|
streamlit/elements/exception.py
CHANGED
@@ -237,18 +237,10 @@ def _format_syntax_error_message(exception: SyntaxError) -> str:
|
|
237
237
|
)
|
238
238
|
|
239
239
|
return (
|
240
|
-
'File "
|
241
|
-
"
|
242
|
-
"
|
243
|
-
"
|
244
|
-
% {
|
245
|
-
"filename": exception.filename,
|
246
|
-
"lineno": exception.lineno,
|
247
|
-
"text": exception.text.rstrip(),
|
248
|
-
"caret_indent": caret_indent,
|
249
|
-
"errname": type(exception).__name__,
|
250
|
-
"msg": exception.msg,
|
251
|
-
}
|
240
|
+
f'File "{exception.filename}", line {exception.lineno}\n'
|
241
|
+
f" {exception.text.rstrip()}\n"
|
242
|
+
f" {caret_indent}^\n"
|
243
|
+
f"{type(exception).__name__}: {exception.msg}"
|
252
244
|
)
|
253
245
|
# If a few edge cases, SyntaxErrors don't have all these nice fields. So we
|
254
246
|
# have a fall back here.
|
streamlit/elements/heading.py
CHANGED
@@ -286,14 +286,13 @@ class HeadingMixin:
|
|
286
286
|
proto.anchor = anchor
|
287
287
|
elif anchor is True: # type: ignore
|
288
288
|
raise StreamlitAPIException(
|
289
|
-
"Anchor parameter has invalid value:
|
290
|
-
"Supported values: None, any string or False"
|
289
|
+
f"Anchor parameter has invalid value: {anchor}. "
|
290
|
+
"Supported values: None, any string or False"
|
291
291
|
)
|
292
292
|
else:
|
293
293
|
raise StreamlitAPIException(
|
294
|
-
"Anchor parameter has invalid type:
|
294
|
+
f"Anchor parameter has invalid type: {type(anchor).__name__}. "
|
295
295
|
"Supported values: None, any string or False"
|
296
|
-
% type(anchor).__name__
|
297
296
|
)
|
298
297
|
|
299
298
|
if help:
|
@@ -160,8 +160,7 @@ def _verify_np_shape(array: npt.NDArray[Any]) -> npt.NDArray[Any]:
|
|
160
160
|
raise StreamlitAPIException("Numpy shape has to be of length 2 or 3.")
|
161
161
|
if len(shape) == 3 and shape[-1] not in (1, 3, 4):
|
162
162
|
raise StreamlitAPIException(
|
163
|
-
"Channel can only be 1, 3, or 4 got
|
164
|
-
% (shape[-1], str(shape))
|
163
|
+
f"Channel can only be 1, 3, or 4 got {shape[-1]}. Shape is {shape}"
|
165
164
|
)
|
166
165
|
|
167
166
|
# If there's only one channel, convert is to x, y
|
@@ -437,7 +436,7 @@ def marshall_images(
|
|
437
436
|
|
438
437
|
# We use the index of the image in the input image list to identify this image inside
|
439
438
|
# MediaFileManager. For this, we just add the index to the image's "coordinates".
|
440
|
-
image_id = "
|
439
|
+
image_id = f"{coordinates}-{coord_suffix}"
|
441
440
|
|
442
441
|
proto_img.url = image_to_url(
|
443
442
|
single_image, width, clamp, channels, output_format, image_id
|
@@ -15,6 +15,60 @@
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
17
|
import contextlib
|
18
|
+
from typing import Final
|
19
|
+
|
20
|
+
# This is the streamlit theme for plotly where we pass in a template.data
|
21
|
+
# and a template.layout.
|
22
|
+
# Template.data is for changing specific graph properties in a general aspect
|
23
|
+
# such as Contour plots or Waterfall plots.
|
24
|
+
# Template.layout is for changing things such as the x axis and fonts and other
|
25
|
+
# general layout properties for general graphs.
|
26
|
+
# We pass in temporary colors to the frontend and the frontend will replace
|
27
|
+
# those colors because we want to change colors based on the background color.
|
28
|
+
# Start at #0000001 because developers may be likely to use #000000
|
29
|
+
CATEGORY_0: Final = "#000001"
|
30
|
+
CATEGORY_1: Final = "#000002"
|
31
|
+
CATEGORY_2: Final = "#000003"
|
32
|
+
CATEGORY_3: Final = "#000004"
|
33
|
+
CATEGORY_4: Final = "#000005"
|
34
|
+
CATEGORY_5: Final = "#000006"
|
35
|
+
CATEGORY_6: Final = "#000007"
|
36
|
+
CATEGORY_7: Final = "#000008"
|
37
|
+
CATEGORY_8: Final = "#000009"
|
38
|
+
CATEGORY_9: Final = "#000010"
|
39
|
+
|
40
|
+
SEQUENTIAL_0: Final = "#000011"
|
41
|
+
SEQUENTIAL_1: Final = "#000012"
|
42
|
+
SEQUENTIAL_2: Final = "#000013"
|
43
|
+
SEQUENTIAL_3: Final = "#000014"
|
44
|
+
SEQUENTIAL_4: Final = "#000015"
|
45
|
+
SEQUENTIAL_5: Final = "#000016"
|
46
|
+
SEQUENTIAL_6: Final = "#000017"
|
47
|
+
SEQUENTIAL_7: Final = "#000018"
|
48
|
+
SEQUENTIAL_8: Final = "#000019"
|
49
|
+
SEQUENTIAL_9: Final = "#000020"
|
50
|
+
|
51
|
+
DIVERGING_0: Final = "#000021"
|
52
|
+
DIVERGING_1: Final = "#000022"
|
53
|
+
DIVERGING_2: Final = "#000023"
|
54
|
+
DIVERGING_3: Final = "#000024"
|
55
|
+
DIVERGING_4: Final = "#000025"
|
56
|
+
DIVERGING_5: Final = "#000026"
|
57
|
+
DIVERGING_6: Final = "#000027"
|
58
|
+
DIVERGING_7: Final = "#000028"
|
59
|
+
DIVERGING_8: Final = "#000029"
|
60
|
+
DIVERGING_9: Final = "#000030"
|
61
|
+
DIVERGING_10: Final = "#000031"
|
62
|
+
|
63
|
+
INCREASING: Final = "#000032"
|
64
|
+
DECREASING: Final = "#000033"
|
65
|
+
TOTAL: Final = "#000034"
|
66
|
+
|
67
|
+
GRAY_70: Final = "#000036"
|
68
|
+
GRAY_90: Final = "#000037"
|
69
|
+
BG_COLOR: Final = "#000038"
|
70
|
+
FADED_TEXT_05: Final = "#000039"
|
71
|
+
BG_MIX: Final = "#000040"
|
18
72
|
|
19
73
|
|
20
74
|
def configure_streamlit_plotly_theme() -> None:
|
@@ -27,59 +81,6 @@ def configure_streamlit_plotly_theme() -> None:
|
|
27
81
|
import plotly.graph_objects as go
|
28
82
|
import plotly.io as pio
|
29
83
|
|
30
|
-
# This is the streamlit theme for plotly where we pass in a template.data
|
31
|
-
# and a template.layout.
|
32
|
-
# Template.data is for changing specific graph properties in a general aspect
|
33
|
-
# such as Contour plots or Waterfall plots.
|
34
|
-
# Template.layout is for changing things such as the x axis and fonts and other
|
35
|
-
# general layout properties for general graphs.
|
36
|
-
# We pass in temporary colors to the frontend and the frontend will replace
|
37
|
-
# those colors because we want to change colors based on the background color.
|
38
|
-
# Start at #0000001 because developers may be likely to use #000000
|
39
|
-
CATEGORY_0 = "#000001"
|
40
|
-
CATEGORY_1 = "#000002"
|
41
|
-
CATEGORY_2 = "#000003"
|
42
|
-
CATEGORY_3 = "#000004"
|
43
|
-
CATEGORY_4 = "#000005"
|
44
|
-
CATEGORY_5 = "#000006"
|
45
|
-
CATEGORY_6 = "#000007"
|
46
|
-
CATEGORY_7 = "#000008"
|
47
|
-
CATEGORY_8 = "#000009"
|
48
|
-
CATEGORY_9 = "#000010"
|
49
|
-
|
50
|
-
SEQUENTIAL_0 = "#000011"
|
51
|
-
SEQUENTIAL_1 = "#000012"
|
52
|
-
SEQUENTIAL_2 = "#000013"
|
53
|
-
SEQUENTIAL_3 = "#000014"
|
54
|
-
SEQUENTIAL_4 = "#000015"
|
55
|
-
SEQUENTIAL_5 = "#000016"
|
56
|
-
SEQUENTIAL_6 = "#000017"
|
57
|
-
SEQUENTIAL_7 = "#000018"
|
58
|
-
SEQUENTIAL_8 = "#000019"
|
59
|
-
SEQUENTIAL_9 = "#000020"
|
60
|
-
|
61
|
-
DIVERGING_0 = "#000021"
|
62
|
-
DIVERGING_1 = "#000022"
|
63
|
-
DIVERGING_2 = "#000023"
|
64
|
-
DIVERGING_3 = "#000024"
|
65
|
-
DIVERGING_4 = "#000025"
|
66
|
-
DIVERGING_5 = "#000026"
|
67
|
-
DIVERGING_6 = "#000027"
|
68
|
-
DIVERGING_7 = "#000028"
|
69
|
-
DIVERGING_8 = "#000029"
|
70
|
-
DIVERGING_9 = "#000030"
|
71
|
-
DIVERGING_10 = "#000031"
|
72
|
-
|
73
|
-
INCREASING = "#000032"
|
74
|
-
DECREASING = "#000033"
|
75
|
-
TOTAL = "#000034"
|
76
|
-
|
77
|
-
GRAY_70 = "#000036"
|
78
|
-
GRAY_90 = "#000037"
|
79
|
-
BG_COLOR = "#000038"
|
80
|
-
FADED_TEXT_05 = "#000039"
|
81
|
-
BG_MIX = "#000040"
|
82
|
-
|
83
84
|
# Plotly represents continuous colorscale through an array of pairs.
|
84
85
|
# The pair's first index is the starting point and the next pair's first index is the end point.
|
85
86
|
# The pair's second index is the starting color and the next pair's second index is the end color.
|
streamlit/elements/lib/utils.py
CHANGED
@@ -31,6 +31,7 @@ from streamlit import config
|
|
31
31
|
from streamlit.errors import StreamlitDuplicateElementId, StreamlitDuplicateElementKey
|
32
32
|
from streamlit.proto.ChatInput_pb2 import ChatInput
|
33
33
|
from streamlit.proto.LabelVisibilityMessage_pb2 import LabelVisibilityMessage
|
34
|
+
from streamlit.proto.RootContainer_pb2 import RootContainer
|
34
35
|
from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
35
36
|
ScriptRunContext,
|
36
37
|
get_script_run_ctx,
|
@@ -45,6 +46,8 @@ if TYPE_CHECKING:
|
|
45
46
|
from builtins import ellipsis
|
46
47
|
from collections.abc import Iterable
|
47
48
|
|
49
|
+
from streamlit.delta_generator import DeltaGenerator
|
50
|
+
|
48
51
|
|
49
52
|
Key: TypeAlias = Union[str, int]
|
50
53
|
|
@@ -182,6 +185,7 @@ def compute_and_register_element_id(
|
|
182
185
|
*,
|
183
186
|
user_key: str | None,
|
184
187
|
form_id: str | None,
|
188
|
+
dg: DeltaGenerator | None = None,
|
185
189
|
**kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
|
186
190
|
) -> str:
|
187
191
|
"""Compute and register the ID for the given element.
|
@@ -212,6 +216,9 @@ def compute_and_register_element_id(
|
|
212
216
|
The ID of the form that the element belongs to. `None` or empty string
|
213
217
|
if the element doesn't belong to a form or doesn't support forms.
|
214
218
|
|
219
|
+
dg : DeltaGenerator | None
|
220
|
+
The DeltaGenerator of each element. `None` if the element is not a widget.
|
221
|
+
|
215
222
|
kwargs : SAFE_VALUES | Iterable[SAFE_VALUES]
|
216
223
|
The arguments to use to compute the element ID.
|
217
224
|
The arguments must be stable, deterministic values.
|
@@ -229,6 +236,14 @@ def compute_and_register_element_id(
|
|
229
236
|
# pages unique IDs.
|
230
237
|
kwargs_to_use["active_script_hash"] = ctx.active_script_hash
|
231
238
|
|
239
|
+
if dg:
|
240
|
+
# If no key is provided and the widget element is inside the sidebar area
|
241
|
+
# add it to the kwargs
|
242
|
+
# allowing the same widget to be both in main area and sidebar.
|
243
|
+
active_dg_root_container = dg._active_dg._root_container
|
244
|
+
if active_dg_root_container == RootContainer.SIDEBAR and user_key is None:
|
245
|
+
kwargs_to_use["active_dg_root_container"] = str(active_dg_root_container)
|
246
|
+
|
232
247
|
element_id = _compute_element_id(
|
233
248
|
element_type,
|
234
249
|
user_key,
|
streamlit/elements/markdown.py
CHANGED
@@ -252,7 +252,7 @@ class MarkdownMixin:
|
|
252
252
|
body = sympy.latex(body)
|
253
253
|
|
254
254
|
latex_proto = MarkdownProto()
|
255
|
-
latex_proto.body = "$$\n
|
255
|
+
latex_proto.body = f"$$\n{clean_text(body)}\n$$"
|
256
256
|
latex_proto.element_type = MarkdownProto.Type.LATEX
|
257
257
|
if help:
|
258
258
|
latex_proto.help = help
|
streamlit/elements/media.py
CHANGED
@@ -478,7 +478,7 @@ def _marshall_av_media(
|
|
478
478
|
elif type_util.is_type(data, "numpy.ndarray"):
|
479
479
|
data_or_filename = cast("npt.NDArray[Any]", data).tobytes()
|
480
480
|
else:
|
481
|
-
raise RuntimeError("Invalid binary data format:
|
481
|
+
raise RuntimeError(f"Invalid binary data format: {type(data)}")
|
482
482
|
|
483
483
|
if runtime.exists():
|
484
484
|
file_url = runtime.get_instance().media_file_mgr.add(
|
streamlit/elements/progress.py
CHANGED
@@ -66,17 +66,17 @@ def _get_value(value: FloatOrInt) -> int:
|
|
66
66
|
if 0 <= value <= 100:
|
67
67
|
return value
|
68
68
|
raise StreamlitAPIException(
|
69
|
-
"Progress Value has invalid value [0, 100]:
|
69
|
+
f"Progress Value has invalid value [0, 100]: {value}"
|
70
70
|
)
|
71
71
|
|
72
72
|
if isinstance(value, float):
|
73
73
|
if _check_float_between(value, low=0.0, high=1.0):
|
74
74
|
return int(value * 100)
|
75
75
|
raise StreamlitAPIException(
|
76
|
-
"Progress Value has invalid value [0.0, 1.0]:
|
76
|
+
f"Progress Value has invalid value [0.0, 1.0]: {value}"
|
77
77
|
)
|
78
78
|
raise StreamlitAPIException(
|
79
|
-
"Progress Value has invalid type:
|
79
|
+
f"Progress Value has invalid type: {type(value).__name__}"
|
80
80
|
)
|
81
81
|
|
82
82
|
|
streamlit/elements/spinner.py
CHANGED
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
16
16
|
|
17
17
|
import contextlib
|
18
18
|
import threading
|
19
|
-
from typing import TYPE_CHECKING
|
19
|
+
from typing import TYPE_CHECKING, Final
|
20
20
|
|
21
21
|
import streamlit as st
|
22
22
|
from streamlit.runtime.scriptrunner import add_script_run_ctx
|
@@ -24,6 +24,10 @@ from streamlit.runtime.scriptrunner import add_script_run_ctx
|
|
24
24
|
if TYPE_CHECKING:
|
25
25
|
from collections.abc import Iterator
|
26
26
|
|
27
|
+
# Set the message 0.5 seconds in the future to avoid annoying
|
28
|
+
# flickering if this spinner runs too quickly.
|
29
|
+
DELAY_SECS: Final = 0.5
|
30
|
+
|
27
31
|
|
28
32
|
@contextlib.contextmanager
|
29
33
|
def spinner(
|
@@ -75,9 +79,6 @@ def spinner(
|
|
75
79
|
|
76
80
|
message = st.empty()
|
77
81
|
|
78
|
-
# Set the message 0.5 seconds in the future to avoid annoying
|
79
|
-
# flickering if this spinner runs too quickly.
|
80
|
-
DELAY_SECS = 0.5
|
81
82
|
display_message = True
|
82
83
|
display_message_lock = threading.Lock()
|
83
84
|
|
@@ -1947,6 +1947,7 @@ class VegaChartsMixin:
|
|
1947
1947
|
"arrow_vega_lite_chart",
|
1948
1948
|
user_key=key,
|
1949
1949
|
form_id=vega_lite_proto.form_id,
|
1950
|
+
dg=self.dg,
|
1950
1951
|
vega_lite_spec=vega_lite_proto.spec,
|
1951
1952
|
# The data is either in vega_lite_proto.data.data
|
1952
1953
|
# or in a named dataset in vega_lite_proto.datasets
|
@@ -818,6 +818,7 @@ class ButtonMixin:
|
|
818
818
|
user_key=key,
|
819
819
|
# download_button is not allowed to be used in a form.
|
820
820
|
form_id=None,
|
821
|
+
dg=self.dg,
|
821
822
|
label=label,
|
822
823
|
icon=icon,
|
823
824
|
file_name=file_name,
|
@@ -1009,6 +1010,7 @@ class ButtonMixin:
|
|
1009
1010
|
user_key=key,
|
1010
1011
|
# Only the
|
1011
1012
|
form_id=form_id,
|
1013
|
+
dg=self.dg,
|
1012
1014
|
label=label,
|
1013
1015
|
icon=icon,
|
1014
1016
|
help=help,
|
@@ -1105,7 +1107,7 @@ def marshall_file(
|
|
1105
1107
|
data_as_bytes = data.read() or b""
|
1106
1108
|
mimetype = mimetype or "application/octet-stream"
|
1107
1109
|
else:
|
1108
|
-
raise StreamlitAPIException("Invalid binary data format:
|
1110
|
+
raise StreamlitAPIException(f"Invalid binary data format: {type(data)}")
|
1109
1111
|
|
1110
1112
|
if runtime.exists():
|
1111
1113
|
file_url = runtime.get_instance().media_file_mgr.add(
|
@@ -123,7 +123,7 @@ def _process_avatar_input(
|
|
123
123
|
Tuple[AvatarType, str]
|
124
124
|
The detected avatar type and the prepared avatar data.
|
125
125
|
"""
|
126
|
-
AvatarType = BlockProto.ChatMessage.AvatarType
|
126
|
+
AvatarType = BlockProto.ChatMessage.AvatarType # noqa: N806
|
127
127
|
|
128
128
|
if avatar is None:
|
129
129
|
return AvatarType.ICON, ""
|
@@ -596,6 +596,7 @@ class ChatMixin:
|
|
596
596
|
user_key=key,
|
597
597
|
# chat_input is not allowed to be used in a form.
|
598
598
|
form_id=None,
|
599
|
+
dg=self.dg,
|
599
600
|
placeholder=placeholder,
|
600
601
|
max_chars=max_chars,
|
601
602
|
accept_file=accept_file,
|