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
@@ -195,6 +195,7 @@ class ColorPickerMixin:
|
|
195
195
|
"color_picker",
|
196
196
|
user_key=key,
|
197
197
|
form_id=current_form_id(self.dg),
|
198
|
+
dg=self.dg,
|
198
199
|
label=label,
|
199
200
|
value=str(value),
|
200
201
|
help=help,
|
@@ -206,25 +207,19 @@ class ColorPickerMixin:
|
|
206
207
|
|
207
208
|
# make sure the value is a string
|
208
209
|
if not isinstance(value, str):
|
209
|
-
raise StreamlitAPIException(
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
"""
|
214
|
-
% type(value).__name__
|
215
|
-
)
|
210
|
+
raise StreamlitAPIException(f"""
|
211
|
+
Color Picker Value has invalid type: {type(value).__name__}. Expects a hex string
|
212
|
+
like '#00FFAA' or '#000'.
|
213
|
+
""")
|
216
214
|
|
217
215
|
# validate the value and expects a hex string
|
218
216
|
match = re.match(r"^#(?:[0-9a-fA-F]{3}){1,2}$", value)
|
219
217
|
|
220
218
|
if not match:
|
221
|
-
raise StreamlitAPIException(
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
"""
|
226
|
-
% value
|
227
|
-
)
|
219
|
+
raise StreamlitAPIException(f"""
|
220
|
+
'{value}' is not a valid hex code for colors. Valid ones are like
|
221
|
+
'#00FFAA' or '#000'.
|
222
|
+
""")
|
228
223
|
|
229
224
|
color_picker_proto = ColorPickerProto()
|
230
225
|
color_picker_proto.id = element_id
|
@@ -370,8 +370,8 @@ def _apply_row_additions(
|
|
370
370
|
# Row cannot be added -> skip it and log a warning.
|
371
371
|
_LOGGER.warning(
|
372
372
|
"Cannot automatically add row for the index "
|
373
|
-
|
374
|
-
|
373
|
+
"of type %s without an explicit index value. Row addition skipped.",
|
374
|
+
type(df.index).__name__,
|
375
375
|
)
|
376
376
|
|
377
377
|
|
@@ -933,6 +933,7 @@ class DataEditorMixin:
|
|
933
933
|
"data_editor",
|
934
934
|
user_key=key,
|
935
935
|
form_id=current_form_id(self.dg),
|
936
|
+
dg=self.dg,
|
936
937
|
data=arrow_bytes,
|
937
938
|
width=width,
|
938
939
|
height=height,
|
@@ -341,6 +341,7 @@ class RadioMixin:
|
|
341
341
|
"radio",
|
342
342
|
user_key=key,
|
343
343
|
form_id=current_form_id(self.dg),
|
344
|
+
dg=self.dg,
|
344
345
|
label=label,
|
345
346
|
options=[str(format_func(option)) for option in opt],
|
346
347
|
index=index,
|
@@ -351,7 +352,7 @@ class RadioMixin:
|
|
351
352
|
|
352
353
|
if not isinstance(index, int) and index is not None:
|
353
354
|
raise StreamlitAPIException(
|
354
|
-
"Radio Value has invalid type:
|
355
|
+
f"Radio Value has invalid type: {type(index).__name__}"
|
355
356
|
)
|
356
357
|
|
357
358
|
if index is not None and len(opt) > 0 and not 0 <= index < len(opt):
|
@@ -495,7 +495,7 @@ class SelectboxMixin:
|
|
495
495
|
|
496
496
|
if not isinstance(index, int) and index is not None:
|
497
497
|
raise StreamlitAPIException(
|
498
|
-
"Selectbox Value has invalid type:
|
498
|
+
f"Selectbox Value has invalid type: {type(index).__name__}"
|
499
499
|
)
|
500
500
|
|
501
501
|
if index is not None and len(opt) > 0 and not 0 <= index < len(opt):
|
@@ -519,6 +519,7 @@ class SelectboxMixin:
|
|
519
519
|
"selectbox",
|
520
520
|
user_key=key,
|
521
521
|
form_id=current_form_id(self.dg),
|
522
|
+
dg=self.dg,
|
522
523
|
label=label,
|
523
524
|
options=formatted_options,
|
524
525
|
index=index,
|
@@ -118,6 +118,15 @@ DAYS_TO_MICROS: Final = 24 * 60 * 60 * SECONDS_TO_MICROS
|
|
118
118
|
|
119
119
|
UTC_EPOCH: Final = datetime(1970, 1, 1, tzinfo=timezone.utc)
|
120
120
|
|
121
|
+
SUPPORTED_TYPES: Final = {
|
122
|
+
Integral: SliderProto.INT,
|
123
|
+
Real: SliderProto.FLOAT,
|
124
|
+
datetime: SliderProto.DATETIME,
|
125
|
+
date: SliderProto.DATE,
|
126
|
+
time: SliderProto.TIME,
|
127
|
+
}
|
128
|
+
TIMELIKE_TYPES: Final = (SliderProto.DATETIME, SliderProto.TIME, SliderProto.DATE)
|
129
|
+
|
121
130
|
|
122
131
|
def _time_to_datetime(time_: time) -> datetime:
|
123
132
|
# Note, here we pick an arbitrary date well after Unix epoch.
|
@@ -665,6 +674,7 @@ class SliderMixin:
|
|
665
674
|
"slider",
|
666
675
|
user_key=key,
|
667
676
|
form_id=current_form_id(self.dg),
|
677
|
+
dg=self.dg,
|
668
678
|
label=label,
|
669
679
|
min_value=min_value,
|
670
680
|
max_value=max_value,
|
@@ -675,15 +685,6 @@ class SliderMixin:
|
|
675
685
|
width=width,
|
676
686
|
)
|
677
687
|
|
678
|
-
SUPPORTED_TYPES = {
|
679
|
-
Integral: SliderProto.INT,
|
680
|
-
Real: SliderProto.FLOAT,
|
681
|
-
datetime: SliderProto.DATETIME,
|
682
|
-
date: SliderProto.DATE,
|
683
|
-
time: SliderProto.TIME,
|
684
|
-
}
|
685
|
-
TIMELIKE_TYPES = (SliderProto.DATETIME, SliderProto.TIME, SliderProto.DATE)
|
686
|
-
|
687
688
|
if value is None:
|
688
689
|
# We need to know if this is a single or range slider, but don't have
|
689
690
|
# a default value, so we check if session_state can tell us.
|
@@ -747,7 +748,7 @@ class SliderMixin:
|
|
747
748
|
datetime_min = value[0] - timedelta(days=14)
|
748
749
|
datetime_max = value[0] + timedelta(days=14)
|
749
750
|
|
750
|
-
|
751
|
+
defaults: Final = {
|
751
752
|
SliderProto.INT: {
|
752
753
|
"min_value": 0,
|
753
754
|
"max_value": 100,
|
@@ -781,18 +782,18 @@ class SliderMixin:
|
|
781
782
|
}
|
782
783
|
|
783
784
|
if min_value is None:
|
784
|
-
min_value =
|
785
|
+
min_value = defaults[data_type]["min_value"]
|
785
786
|
if max_value is None:
|
786
|
-
max_value =
|
787
|
+
max_value = defaults[data_type]["max_value"]
|
787
788
|
if step is None:
|
788
|
-
step =
|
789
|
+
step = defaults[data_type]["step"]
|
789
790
|
if data_type in (
|
790
791
|
SliderProto.DATETIME,
|
791
792
|
SliderProto.DATE,
|
792
793
|
) and max_value - min_value < timedelta(days=1):
|
793
794
|
step = timedelta(minutes=15)
|
794
795
|
if format is None:
|
795
|
-
format = cast("str",
|
796
|
+
format = cast("str", defaults[data_type]["format"]) # noqa: A001
|
796
797
|
|
797
798
|
if step == 0:
|
798
799
|
raise StreamlitAPIException(
|
@@ -813,17 +814,13 @@ class SliderMixin:
|
|
813
814
|
)
|
814
815
|
|
815
816
|
if not int_args and not float_args and not timelike_args:
|
816
|
-
|
817
|
+
msg = (
|
817
818
|
"Slider value arguments must be of matching types."
|
818
|
-
"\n`min_value` has
|
819
|
-
"\n`max_value` has
|
820
|
-
"\n`step` has
|
821
|
-
% {
|
822
|
-
"min_type": type(min_value).__name__,
|
823
|
-
"max_type": type(max_value).__name__,
|
824
|
-
"step": type(step).__name__,
|
825
|
-
}
|
819
|
+
f"\n`min_value` has {type(min_value).__name__} type."
|
820
|
+
f"\n`max_value` has {type(max_value).__name__} type."
|
821
|
+
f"\n`step` has {type(step).__name__} type."
|
826
822
|
)
|
823
|
+
raise StreamlitAPIException(msg)
|
827
824
|
|
828
825
|
# Ensure that the value matches arguments' types.
|
829
826
|
all_ints = data_type == SliderProto.INT and int_args
|
@@ -831,17 +828,13 @@ class SliderMixin:
|
|
831
828
|
all_timelikes = data_type in TIMELIKE_TYPES and timelike_args
|
832
829
|
|
833
830
|
if not all_ints and not all_floats and not all_timelikes:
|
834
|
-
|
831
|
+
msg = (
|
835
832
|
"Both value and arguments must be of the same type."
|
836
|
-
"\n`value` has
|
837
|
-
"\n`min_value` has
|
838
|
-
"\n`max_value` has
|
839
|
-
% {
|
840
|
-
"value_type": type(value).__name__,
|
841
|
-
"min_type": type(min_value).__name__,
|
842
|
-
"max_type": type(max_value).__name__,
|
843
|
-
}
|
833
|
+
f"\n`value` has {type(value).__name__} type."
|
834
|
+
f"\n`min_value` has {type(min_value).__name__} type."
|
835
|
+
f"\n`max_value` has {type(max_value).__name__} type."
|
844
836
|
)
|
837
|
+
raise StreamlitAPIException(msg)
|
845
838
|
|
846
839
|
# Ensure that min <= value(s) <= max, adjusting the bounds as necessary.
|
847
840
|
min_value = min(min_value, max_value)
|
@@ -317,6 +317,7 @@ class TextWidgetsMixin:
|
|
317
317
|
"text_input",
|
318
318
|
user_key=key,
|
319
319
|
form_id=current_form_id(self.dg),
|
320
|
+
dg=self.dg,
|
320
321
|
label=label,
|
321
322
|
value=value,
|
322
323
|
max_chars=max_chars,
|
@@ -369,8 +370,7 @@ class TextWidgetsMixin:
|
|
369
370
|
text_input_proto.type = TextInputProto.PASSWORD
|
370
371
|
else:
|
371
372
|
raise StreamlitAPIException(
|
372
|
-
"'
|
373
|
-
% type
|
373
|
+
f"'{type}' is not a valid text_input type. Valid types are 'default' and 'password'."
|
374
374
|
)
|
375
375
|
|
376
376
|
# Marshall the autocomplete param. If unspecified, this will be
|
@@ -622,6 +622,7 @@ class TextWidgetsMixin:
|
|
622
622
|
"text_area",
|
623
623
|
user_key=key,
|
624
624
|
form_id=current_form_id(self.dg),
|
625
|
+
dg=self.dg,
|
625
626
|
label=label,
|
626
627
|
value=value,
|
627
628
|
height=height,
|
@@ -523,6 +523,7 @@ class TimeWidgetsMixin:
|
|
523
523
|
"time_input",
|
524
524
|
user_key=key,
|
525
525
|
form_id=current_form_id(self.dg),
|
526
|
+
dg=self.dg,
|
526
527
|
label=label,
|
527
528
|
value=parsed_time if isinstance(value, (datetime, time)) else value,
|
528
529
|
help=help,
|
@@ -909,6 +910,7 @@ class TimeWidgetsMixin:
|
|
909
910
|
"date_input",
|
910
911
|
user_key=key,
|
911
912
|
form_id=current_form_id(self.dg),
|
913
|
+
dg=self.dg,
|
912
914
|
label=label,
|
913
915
|
value=parsed,
|
914
916
|
min_value=parsed_min_date,
|
@@ -42,22 +42,22 @@ def animation_demo() -> None:
|
|
42
42
|
for frame_num, a in enumerate(np.linspace(0.0, 4 * np.pi, 100)):
|
43
43
|
# Here were setting value for these two elements.
|
44
44
|
progress_bar.progress(frame_num)
|
45
|
-
frame_text.text("Frame
|
45
|
+
frame_text.text(f"Frame {frame_num + 1}/100")
|
46
46
|
|
47
47
|
# Performing some fractal wizardry.
|
48
48
|
c = separation * np.exp(1j * a)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
z = np.tile(x, (n, 1)) + 1j * np.tile(y, (1, m))
|
50
|
+
c_matrix = np.full((n, m), c)
|
51
|
+
m_matrix: Any = np.full((n, m), True, dtype=bool)
|
52
|
+
n_matrix = np.zeros((n, m))
|
53
53
|
|
54
54
|
for i in range(iterations):
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
z[m_matrix] = z[m_matrix] * z[m_matrix] + c_matrix[m_matrix]
|
56
|
+
m_matrix[np.abs(z) > 2] = False
|
57
|
+
n_matrix[m_matrix] = i
|
58
58
|
|
59
59
|
# Update the image placeholder by calling the image() function on it.
|
60
|
-
image.image(1.0 - (
|
60
|
+
image.image(1.0 - (n_matrix / n_matrix.max()), use_container_width=True)
|
61
61
|
|
62
62
|
# We clear elements by calling empty on them.
|
63
63
|
progress_bar.empty()
|
@@ -24,8 +24,8 @@ from streamlit.hello.utils import show_code
|
|
24
24
|
def data_frame_demo() -> None:
|
25
25
|
@st.cache_data
|
26
26
|
def get_un_data() -> pd.DataFrame:
|
27
|
-
|
28
|
-
df = pd.read_csv(
|
27
|
+
aws_bucket_url = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
|
28
|
+
df = pd.read_csv(aws_bucket_url + "/agri.csv.gz")
|
29
29
|
return df.set_index("Region")
|
30
30
|
|
31
31
|
try:
|
streamlit/hello/mapping_demo.py
CHANGED
@@ -26,12 +26,12 @@ def mapping_demo() -> None:
|
|
26
26
|
def from_data_file(filename: str) -> pd.DataFrame:
|
27
27
|
url = (
|
28
28
|
"https://raw.githubusercontent.com/streamlit/"
|
29
|
-
"example-data/master/hello/v1
|
29
|
+
f"example-data/master/hello/v1/{filename}"
|
30
30
|
)
|
31
31
|
return pd.read_json(url)
|
32
32
|
|
33
33
|
try:
|
34
|
-
|
34
|
+
all_layers = {
|
35
35
|
"Bike rentals": pdk.Layer(
|
36
36
|
"HexagonLayer",
|
37
37
|
data=from_data_file("bike_rental_stats.json"),
|
@@ -75,7 +75,7 @@ def mapping_demo() -> None:
|
|
75
75
|
st.sidebar.subheader("Map layers")
|
76
76
|
selected_layers = [
|
77
77
|
layer
|
78
|
-
for layer_name, layer in
|
78
|
+
for layer_name, layer in all_layers.items()
|
79
79
|
if st.sidebar.checkbox(layer_name, True)
|
80
80
|
]
|
81
81
|
if selected_layers:
|
@@ -95,11 +95,10 @@ def mapping_demo() -> None:
|
|
95
95
|
st.error("Please choose at least one layer above.")
|
96
96
|
except URLError as e:
|
97
97
|
st.error(
|
98
|
-
"""
|
98
|
+
f"""
|
99
99
|
**This demo requires internet access.**
|
100
|
-
Connection error:
|
100
|
+
Connection error: {e.reason}
|
101
101
|
"""
|
102
|
-
% e.reason
|
103
102
|
)
|
104
103
|
|
105
104
|
|
streamlit/logger.py
CHANGED
streamlit/runtime/app_session.py
CHANGED
@@ -375,8 +375,9 @@ class AppSession:
|
|
375
375
|
# sometimes stays open.
|
376
376
|
if fragment_id and not self._fragment_storage.contains(fragment_id):
|
377
377
|
_LOGGER.info(
|
378
|
-
|
379
|
-
"it might have been removed during a preceding full-app rerun."
|
378
|
+
"The fragment with id %s does not exist anymore - "
|
379
|
+
"it might have been removed during a preceding full-app rerun.",
|
380
|
+
fragment_id,
|
380
381
|
)
|
381
382
|
return
|
382
383
|
|
@@ -954,9 +955,10 @@ def _populate_theme_msg(msg: CustomThemeConfig, section: str = "theme") -> None:
|
|
954
955
|
if base is not None:
|
955
956
|
if base not in base_map:
|
956
957
|
_LOGGER.warning(
|
957
|
-
|
958
|
-
|
959
|
-
|
958
|
+
'"%s" is an invalid value for theme.base. Allowed values include %s. '
|
959
|
+
'Setting theme.base to "light".',
|
960
|
+
base,
|
961
|
+
list(base_map.keys()),
|
960
962
|
)
|
961
963
|
else:
|
962
964
|
msg.base = base_map[base]
|
@@ -976,8 +978,8 @@ def _populate_theme_msg(msg: CustomThemeConfig, section: str = "theme") -> None:
|
|
976
978
|
font_faces = json.loads(font_faces)
|
977
979
|
except Exception as e:
|
978
980
|
_LOGGER.warning(
|
979
|
-
"Failed to parse the theme.fontFaces config option with json.loads: "
|
980
|
-
|
981
|
+
"Failed to parse the theme.fontFaces config option with json.loads: %s.",
|
982
|
+
font_faces,
|
981
983
|
exc_info=e,
|
982
984
|
)
|
983
985
|
font_faces = None
|
@@ -988,7 +990,8 @@ def _populate_theme_msg(msg: CustomThemeConfig, section: str = "theme") -> None:
|
|
988
990
|
msg.font_faces.append(ParseDict(font_face, FontFace()))
|
989
991
|
except Exception as e: # noqa: PERF203
|
990
992
|
_LOGGER.warning(
|
991
|
-
|
993
|
+
"Failed to parse the theme.fontFaces config option: %s.",
|
994
|
+
font_face,
|
992
995
|
exc_info=e,
|
993
996
|
)
|
994
997
|
|
@@ -92,26 +92,25 @@ class UserHashError(StreamlitAPIException):
|
|
92
92
|
args = self._get_error_message_args(orig_exc, cached_func)
|
93
93
|
|
94
94
|
return (
|
95
|
-
"""
|
96
|
-
|
95
|
+
f"""
|
96
|
+
{args["orig_exception_desc"]}
|
97
97
|
|
98
|
-
This error is likely due to a bug in
|
99
|
-
user-defined hash function that was passed into the
|
100
|
-
|
98
|
+
This error is likely due to a bug in {args["hash_func_name"]}, which is a
|
99
|
+
user-defined hash function that was passed into the `{args["cache_primitive"]}` decorator of
|
100
|
+
{args["object_desc"]}.
|
101
101
|
|
102
|
-
|
103
|
-
|
102
|
+
{args["hash_func_name"]} failed when hashing an object of type
|
103
|
+
`{args["failed_obj_type_str"]}`. If you don't know where that object is coming from,
|
104
104
|
try looking at the hash chain below for an object that you do recognize, then
|
105
105
|
pass that to `hash_funcs` instead:
|
106
106
|
|
107
107
|
```
|
108
|
-
|
108
|
+
{args["hash_stack"]}
|
109
109
|
```
|
110
110
|
|
111
111
|
If you think this is actually a Streamlit bug, please
|
112
112
|
[file a bug report here](https://github.com/streamlit/streamlit/issues/new/choose).
|
113
113
|
"""
|
114
|
-
% args
|
115
114
|
).strip("\n")
|
116
115
|
|
117
116
|
def _get_error_message_args(
|
@@ -109,9 +109,9 @@ class LocalDiskCacheStorageManager(CacheStorageManager):
|
|
109
109
|
and not math.isinf(context.ttl_seconds)
|
110
110
|
):
|
111
111
|
_LOGGER.warning(
|
112
|
-
|
113
|
-
"
|
114
|
-
|
112
|
+
"The cached function '%s' has a TTL that will be ignored. "
|
113
|
+
"Persistent cached functions currently don't support TTL.",
|
114
|
+
context.function_display_name,
|
115
115
|
)
|
116
116
|
|
117
117
|
|
@@ -38,13 +38,13 @@ if TYPE_CHECKING:
|
|
38
38
|
# 2. Writing two new @overloads for connection_factory (one for the case where the
|
39
39
|
# only the connection name is specified and another when both name and type are).
|
40
40
|
# 3. Updating test_get_first_party_connection_helper in connection_factory_test.py.
|
41
|
-
|
41
|
+
_FIRST_PARTY_CONNECTIONS: Final[dict[str, type[BaseConnection[Any]]]] = {
|
42
42
|
"snowflake": SnowflakeConnection,
|
43
43
|
"snowpark": SnowparkConnection,
|
44
44
|
"sql": SQLConnection,
|
45
45
|
}
|
46
|
-
|
47
|
-
|
46
|
+
_MODULE_EXTRACTION_REGEX = re.compile(r"No module named \'(.+)\'")
|
47
|
+
_MODULES_TO_PYPI_PACKAGES: Final[dict[str, str]] = {
|
48
48
|
"MySQLdb": "mysqlclient",
|
49
49
|
"psycopg2": "psycopg2-binary",
|
50
50
|
"sqlalchemy": "sqlalchemy",
|
@@ -52,6 +52,7 @@ MODULES_TO_PYPI_PACKAGES: Final[dict[str, str]] = {
|
|
52
52
|
"snowflake.connector": "snowflake-connector-python",
|
53
53
|
"snowflake.snowpark": "snowflake-snowpark-python",
|
54
54
|
}
|
55
|
+
_USE_ENV_PREFIX: Final = "env:"
|
55
56
|
|
56
57
|
# The BaseConnection bound is parameterized to `Any` below as subclasses of
|
57
58
|
# BaseConnection are responsible for binding the type parameter of BaseConnection to a
|
@@ -104,12 +105,12 @@ def _create_connection(
|
|
104
105
|
|
105
106
|
|
106
107
|
def _get_first_party_connection(connection_class: str) -> type[BaseConnection[Any]]:
|
107
|
-
if connection_class in
|
108
|
-
return
|
108
|
+
if connection_class in _FIRST_PARTY_CONNECTIONS:
|
109
|
+
return _FIRST_PARTY_CONNECTIONS[connection_class]
|
109
110
|
|
110
111
|
raise StreamlitAPIException(
|
111
112
|
f"Invalid connection '{connection_class}'. "
|
112
|
-
f"Supported connection classes: {
|
113
|
+
f"Supported connection classes: {_FIRST_PARTY_CONNECTIONS}"
|
113
114
|
)
|
114
115
|
|
115
116
|
|
@@ -366,12 +367,11 @@ def connection_factory( # type: ignore
|
|
366
367
|
>>> conn = st.connection("my_sql_connection", type=SQLConnection)
|
367
368
|
|
368
369
|
"""
|
369
|
-
USE_ENV_PREFIX = "env:"
|
370
370
|
|
371
|
-
if name.startswith(
|
371
|
+
if name.startswith(_USE_ENV_PREFIX):
|
372
372
|
# It'd be nice to use str.removeprefix() here, but we won't be able to do that
|
373
373
|
# until the minimum Python version we support is 3.9.
|
374
|
-
envvar_name = name[len(
|
374
|
+
envvar_name = name[len(_USE_ENV_PREFIX) :]
|
375
375
|
name = os.environ[envvar_name]
|
376
376
|
|
377
377
|
# type is a nice kwarg name for the st.connection user but is annoying to work with
|
@@ -380,7 +380,7 @@ def connection_factory( # type: ignore
|
|
380
380
|
connection_class = type
|
381
381
|
|
382
382
|
if connection_class is None:
|
383
|
-
if name in
|
383
|
+
if name in _FIRST_PARTY_CONNECTIONS:
|
384
384
|
# We allow users to simply write `st.connection("sql")` instead of
|
385
385
|
# `st.connection("sql", type="sql")`.
|
386
386
|
connection_class = _get_first_party_connection(name)
|
@@ -424,11 +424,11 @@ def connection_factory( # type: ignore
|
|
424
424
|
return conn
|
425
425
|
except ModuleNotFoundError as e:
|
426
426
|
err_string = str(e)
|
427
|
-
missing_module = re.search(
|
427
|
+
missing_module = re.search(_MODULE_EXTRACTION_REGEX, err_string)
|
428
428
|
|
429
429
|
extra_info = "You may be missing a dependency required to use this connection."
|
430
430
|
if missing_module:
|
431
|
-
pypi_package =
|
431
|
+
pypi_package = _MODULES_TO_PYPI_PACKAGES.get(missing_module.group(1))
|
432
432
|
if pypi_package:
|
433
433
|
extra_info = f"You need to install the '{pypi_package}' package to use this connection."
|
434
434
|
|
streamlit/runtime/credentials.py
CHANGED
@@ -29,7 +29,7 @@ from streamlit.logger import get_logger
|
|
29
29
|
_LOGGER: Final = get_logger(__name__)
|
30
30
|
|
31
31
|
|
32
|
-
_CONFIG_FILE_PATH = (
|
32
|
+
_CONFIG_FILE_PATH: Final = (
|
33
33
|
r"%userprofile%/.streamlit/config.toml"
|
34
34
|
if env_util.IS_WINDOWS
|
35
35
|
else "~/.streamlit/config.toml"
|
@@ -263,43 +263,30 @@ class Credentials:
|
|
263
263
|
if self.activation.is_valid:
|
264
264
|
self.save()
|
265
265
|
# IMPORTANT: Break the text below at 80 chars.
|
266
|
-
|
267
|
-
You can find our privacy policy at
|
266
|
+
telemetry_text = f"""
|
267
|
+
You can find our privacy policy at {cli_util.style_for_cli("https://streamlit.io/privacy-policy", underline=True)}
|
268
268
|
|
269
269
|
Summary:
|
270
270
|
- This open source library collects usage statistics.
|
271
271
|
- We cannot see and do not store information contained inside Streamlit apps,
|
272
272
|
such as text, charts, images, etc.
|
273
273
|
- Telemetry data is stored in servers in the United States.
|
274
|
-
- If you'd like to opt out, add the following to
|
274
|
+
- If you'd like to opt out, add the following to {cli_util.style_for_cli(_CONFIG_FILE_PATH)},
|
275
275
|
creating that file if necessary:
|
276
276
|
|
277
277
|
[browser]
|
278
278
|
gatherUsageStats = false
|
279
|
-
"""
|
280
|
-
|
281
|
-
|
282
|
-
),
|
283
|
-
"config": cli_util.style_for_cli(_CONFIG_FILE_PATH),
|
284
|
-
}
|
285
|
-
|
286
|
-
cli_util.print_to_cli(TELEMETRY_TEXT)
|
279
|
+
"""
|
280
|
+
|
281
|
+
cli_util.print_to_cli(telemetry_text)
|
287
282
|
if show_instructions:
|
288
283
|
# IMPORTANT: Break the text below at 80 chars.
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
"""
|
293
|
-
|
294
|
-
|
295
|
-
),
|
296
|
-
"prompt": cli_util.style_for_cli("$", fg="blue"),
|
297
|
-
"hello": cli_util.style_for_cli(
|
298
|
-
"streamlit hello", bold=True
|
299
|
-
),
|
300
|
-
}
|
301
|
-
|
302
|
-
cli_util.print_to_cli(INSTRUCTIONS_TEXT)
|
284
|
+
instructions_text = f"""
|
285
|
+
{cli_util.style_for_cli("Get started by typing:", fg="blue", bold=True)}
|
286
|
+
{cli_util.style_for_cli("$", fg="blue")} {cli_util.style_for_cli("streamlit hello", bold=True)}
|
287
|
+
"""
|
288
|
+
|
289
|
+
cli_util.print_to_cli(instructions_text)
|
303
290
|
activated = True
|
304
291
|
else: # pragma: nocover
|
305
292
|
_LOGGER.error("Please try again.")
|
@@ -79,8 +79,8 @@ def serialize_forward_msg(msg: ForwardMsg) -> bytes:
|
|
79
79
|
|
80
80
|
msg_size_error = MessageSizeError(msg_str)
|
81
81
|
_LOGGER.warning(
|
82
|
-
"Websocket message size limit exceeded. "
|
83
|
-
|
82
|
+
"Websocket message size limit exceeded. Showing error to the user: %s",
|
83
|
+
msg_size_error,
|
84
84
|
)
|
85
85
|
exception.marshall(msg.delta.new_element.exception, msg_size_error)
|
86
86
|
# Deactivate caching for this error message:
|