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
@@ -341,12 +341,11 @@ class RadioMixin:
|
|
341
341
|
def handle_captions(caption: str | None) -> str:
|
342
342
|
if caption is None:
|
343
343
|
return ""
|
344
|
-
|
344
|
+
if isinstance(caption, str):
|
345
345
|
return caption
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
)
|
346
|
+
raise StreamlitAPIException(
|
347
|
+
f"Radio captions must be strings. Passed type: {type(caption).__name__}"
|
348
|
+
)
|
350
349
|
|
351
350
|
session_state = get_session_state().filtered_state
|
352
351
|
if key is not None and key in session_state and session_state[key] is None:
|
@@ -102,8 +102,7 @@ class SelectSliderSerde(Generic[T]):
|
|
102
102
|
if start > end:
|
103
103
|
slider_value = [end, start]
|
104
104
|
return slider_value
|
105
|
-
|
106
|
-
return [index_(self.options, v)]
|
105
|
+
return [index_(self.options, v)]
|
107
106
|
|
108
107
|
|
109
108
|
class SelectSliderMixin:
|
@@ -367,15 +366,14 @@ class SelectSliderMixin:
|
|
367
366
|
if start > end:
|
368
367
|
slider_value = [end, start]
|
369
368
|
return slider_value
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
return [0]
|
369
|
+
# Simplify future logic by always making value a list
|
370
|
+
try:
|
371
|
+
return [index_(opt, v)]
|
372
|
+
except ValueError:
|
373
|
+
if value is not None:
|
374
|
+
raise
|
375
|
+
|
376
|
+
return [0]
|
379
377
|
|
380
378
|
# Convert element to index of the elements
|
381
379
|
slider_value = as_index_list(value)
|
@@ -692,7 +692,7 @@ class SliderMixin:
|
|
692
692
|
if single_value:
|
693
693
|
value = [value]
|
694
694
|
|
695
|
-
def value_to_generic_type(v):
|
695
|
+
def value_to_generic_type(v: Any) -> SliderProto.DataType.ValueType:
|
696
696
|
if isinstance(v, Integral):
|
697
697
|
return SUPPORTED_TYPES[Integral]
|
698
698
|
if isinstance(v, Real):
|
streamlit/elements/write.py
CHANGED
@@ -156,7 +156,7 @@ class WriteMixin:
|
|
156
156
|
streamed_response: str = ""
|
157
157
|
written_content: list[Any] = StreamingOutput()
|
158
158
|
|
159
|
-
def flush_stream_response():
|
159
|
+
def flush_stream_response() -> None:
|
160
160
|
"""Write the full response to the app."""
|
161
161
|
nonlocal streamed_response
|
162
162
|
nonlocal stream_container
|
@@ -428,7 +428,7 @@ class WriteMixin:
|
|
428
428
|
"when called as `st.write()` or `st.sidebar.write()`."
|
429
429
|
)
|
430
430
|
|
431
|
-
def flush_buffer():
|
431
|
+
def flush_buffer() -> None:
|
432
432
|
if string_buffer:
|
433
433
|
text_content = " ".join(string_buffer)
|
434
434
|
# The usage of empty here prevents
|
streamlit/error_util.py
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
-
from typing import Final
|
17
|
+
from typing import Any, Final
|
18
18
|
|
19
19
|
import streamlit
|
20
20
|
from streamlit import config
|
@@ -26,17 +26,24 @@ _LOGGER: Final = get_logger(__name__)
|
|
26
26
|
|
27
27
|
|
28
28
|
def _print_rich_exception(e: BaseException) -> None:
|
29
|
-
from rich import
|
29
|
+
from rich.box import Box
|
30
|
+
from rich.panel import Panel
|
30
31
|
|
31
32
|
# Monkey patch the panel to use our custom box style
|
32
|
-
class ConfigurablePanel(
|
33
|
+
class ConfigurablePanel(Panel):
|
33
34
|
def __init__(
|
34
35
|
self,
|
35
|
-
renderable,
|
36
|
-
box=
|
37
|
-
**kwargs,
|
38
|
-
):
|
39
|
-
super().__init__(
|
36
|
+
renderable: Any,
|
37
|
+
box: Box | None = None,
|
38
|
+
**kwargs: Any,
|
39
|
+
) -> None:
|
40
|
+
super().__init__(
|
41
|
+
renderable,
|
42
|
+
box
|
43
|
+
if box is not None
|
44
|
+
else Box("────\n \n────\n \n────\n────\n \n────\n"),
|
45
|
+
**kwargs,
|
46
|
+
)
|
40
47
|
|
41
48
|
from rich import traceback as rich_traceback
|
42
49
|
|
streamlit/errors.py
CHANGED
@@ -20,6 +20,7 @@ from typing import TYPE_CHECKING, Any, Literal
|
|
20
20
|
from streamlit import util
|
21
21
|
|
22
22
|
if TYPE_CHECKING:
|
23
|
+
from collections.abc import Collection
|
23
24
|
from datetime import date, time
|
24
25
|
|
25
26
|
|
@@ -140,7 +141,7 @@ class StreamlitAPIWarning(StreamlitAPIException, Warning):
|
|
140
141
|
instead.
|
141
142
|
"""
|
142
143
|
|
143
|
-
def __init__(self, *args):
|
144
|
+
def __init__(self, *args: Any) -> None:
|
144
145
|
super().__init__(*args)
|
145
146
|
import inspect
|
146
147
|
import traceback
|
@@ -157,7 +158,7 @@ class StreamlitModuleNotFoundError(StreamlitAPIWarning):
|
|
157
158
|
that is not one of our core dependencies.
|
158
159
|
"""
|
159
160
|
|
160
|
-
def __init__(self, module_name, *args):
|
161
|
+
def __init__(self, module_name: str, *args: Any) -> None:
|
161
162
|
message = (
|
162
163
|
f'This Streamlit command requires module "{module_name}" to be installed.'
|
163
164
|
)
|
@@ -220,7 +221,7 @@ class StreamlitInvalidURLError(LocalizableStreamlitException):
|
|
220
221
|
class StreamlitInvalidColumnSpecError(LocalizableStreamlitException):
|
221
222
|
"""Exception raised when no weights are specified, or a negative weight is specified."""
|
222
223
|
|
223
|
-
def __init__(self):
|
224
|
+
def __init__(self) -> None:
|
224
225
|
super().__init__(
|
225
226
|
"The `spec` argument to `st.columns` must be either a "
|
226
227
|
"positive integer (number of columns) or a list of positive numbers (width ratios of the columns). "
|
@@ -370,7 +371,7 @@ class StreamlitInvalidNumberFormatError(LocalizableStreamlitException):
|
|
370
371
|
class StreamlitMissingPageLabelError(LocalizableStreamlitException):
|
371
372
|
"""Exception raised when a page_link is created without a label."""
|
372
373
|
|
373
|
-
def __init__(self):
|
374
|
+
def __init__(self) -> None:
|
374
375
|
super().__init__(
|
375
376
|
"The `label` param is required for external links used with `st.page_link` - please provide a `label`."
|
376
377
|
)
|
@@ -409,7 +410,7 @@ class StreamlitPageNotFoundError(LocalizableStreamlitException):
|
|
409
410
|
class StreamlitFragmentWidgetsNotAllowedOutsideError(LocalizableStreamlitException):
|
410
411
|
"""Exception raised when the fragment attempts to write to an element outside of its container."""
|
411
412
|
|
412
|
-
def __init__(self):
|
413
|
+
def __init__(self) -> None:
|
413
414
|
super().__init__("Fragments cannot write widgets to outside containers.")
|
414
415
|
|
415
416
|
|
@@ -418,7 +419,7 @@ class StreamlitInvalidFormCallbackError(LocalizableStreamlitException):
|
|
418
419
|
the `st.form_submit_button`.
|
419
420
|
"""
|
420
421
|
|
421
|
-
def __init__(self):
|
422
|
+
def __init__(self) -> None:
|
422
423
|
super().__init__(
|
423
424
|
"Within a form, callbacks can only be defined on `st.form_submit_button`. "
|
424
425
|
"Defining callbacks on other widgets inside a form is not allowed."
|
@@ -436,7 +437,9 @@ class StreamlitValueAssignmentNotAllowedError(LocalizableStreamlitException):
|
|
436
437
|
|
437
438
|
|
438
439
|
class StreamlitInvalidColorError(LocalizableStreamlitException):
|
439
|
-
def __init__(
|
440
|
+
def __init__(
|
441
|
+
self, color: str | Collection[Any] | tuple[int, int, int, int]
|
442
|
+
) -> None:
|
440
443
|
super().__init__(
|
441
444
|
"This does not look like a valid color: {color}.\n\n"
|
442
445
|
"Colors must be in one of the following formats:"
|
streamlit/file_util.py
CHANGED
@@ -19,11 +19,14 @@ import errno
|
|
19
19
|
import io
|
20
20
|
import os
|
21
21
|
from pathlib import Path
|
22
|
-
from typing import Final
|
22
|
+
from typing import IO, TYPE_CHECKING, Any, Final
|
23
23
|
|
24
24
|
from streamlit import env_util, errors
|
25
25
|
from streamlit.string_util import is_binary_string
|
26
26
|
|
27
|
+
if TYPE_CHECKING:
|
28
|
+
from collections.abc import Generator
|
29
|
+
|
27
30
|
# Configuration and credentials are stored inside the ~/.streamlit folder
|
28
31
|
CONFIG_FOLDER_NAME: Final = ".streamlit"
|
29
32
|
|
@@ -63,7 +66,7 @@ def get_encoded_file_data(
|
|
63
66
|
|
64
67
|
|
65
68
|
@contextlib.contextmanager
|
66
|
-
def streamlit_read(path, binary=False):
|
69
|
+
def streamlit_read(path: str, binary: bool = False) -> Generator[IO[Any], None, None]:
|
67
70
|
"""Opens a context to read this file relative to the streamlit path.
|
68
71
|
|
69
72
|
For example:
|
@@ -88,7 +91,7 @@ def streamlit_read(path, binary=False):
|
|
88
91
|
|
89
92
|
|
90
93
|
@contextlib.contextmanager
|
91
|
-
def streamlit_write(path, binary=False):
|
94
|
+
def streamlit_write(path: str, binary: bool = False) -> Generator[IO[Any], None, None]:
|
92
95
|
"""Opens a file for writing within the streamlit path, and
|
93
96
|
ensuring that the path exists.
|
94
97
|
|
streamlit/git_util.py
CHANGED
@@ -16,10 +16,13 @@ from __future__ import annotations
|
|
16
16
|
|
17
17
|
import os
|
18
18
|
import re
|
19
|
-
from typing import
|
19
|
+
from typing import TYPE_CHECKING, cast
|
20
20
|
|
21
21
|
from streamlit import util
|
22
22
|
|
23
|
+
if TYPE_CHECKING:
|
24
|
+
from git import Commit, Remote, RemoteReference, Repo
|
25
|
+
|
23
26
|
# Github has two URLs, one that is https and one that is ssh
|
24
27
|
GITHUB_HTTP_URL = r"^https://(www\.)?github.com/(.+)/(.+)(?:.git)?$"
|
25
28
|
GITHUB_SSH_URL = r"^git@github.com:(.+)/(.+)(?:.git)?$"
|
@@ -31,7 +34,9 @@ MIN_GIT_VERSION = (2, 7, 0)
|
|
31
34
|
|
32
35
|
|
33
36
|
class GitRepo:
|
34
|
-
|
37
|
+
repo: Repo | None
|
38
|
+
|
39
|
+
def __init__(self, path: str) -> None:
|
35
40
|
# If we have a valid repo, git_version will be a tuple
|
36
41
|
# of 3+ ints: (major, minor, patch, possible_additional_patch_number)
|
37
42
|
self.git_version: tuple[int, ...] | None = None
|
@@ -39,11 +44,7 @@ class GitRepo:
|
|
39
44
|
try:
|
40
45
|
import git
|
41
46
|
|
42
|
-
|
43
|
-
# type errors on Mac and Linux. We bypass type checking entirely
|
44
|
-
# by redeclaring the `git` import as an "Any".
|
45
|
-
git_package: Any = git
|
46
|
-
self.repo = git_package.Repo(path, search_parent_directories=True)
|
47
|
+
self.repo = git.Repo(path, search_parent_directories=True)
|
47
48
|
self.git_version = self.repo.git.version_info
|
48
49
|
|
49
50
|
if self.git_version >= MIN_GIT_VERSION:
|
@@ -69,8 +70,8 @@ class GitRepo:
|
|
69
70
|
)
|
70
71
|
|
71
72
|
@property
|
72
|
-
def tracking_branch(self):
|
73
|
-
if not self.is_valid():
|
73
|
+
def tracking_branch(self) -> RemoteReference | None:
|
74
|
+
if self.repo is None or not self.is_valid():
|
74
75
|
return None
|
75
76
|
|
76
77
|
if self.is_head_detached:
|
@@ -79,41 +80,45 @@ class GitRepo:
|
|
79
80
|
return self.repo.active_branch.tracking_branch()
|
80
81
|
|
81
82
|
@property
|
82
|
-
def untracked_files(self):
|
83
|
-
if not self.is_valid():
|
83
|
+
def untracked_files(self) -> list[str] | None:
|
84
|
+
if self.repo is None or not self.is_valid():
|
84
85
|
return None
|
85
86
|
|
86
87
|
return self.repo.untracked_files
|
87
88
|
|
88
89
|
@property
|
89
|
-
def is_head_detached(self):
|
90
|
-
if not self.is_valid():
|
90
|
+
def is_head_detached(self) -> bool:
|
91
|
+
if self.repo is None or not self.is_valid():
|
91
92
|
return False
|
92
93
|
|
93
94
|
return self.repo.head.is_detached
|
94
95
|
|
95
96
|
@property
|
96
|
-
def uncommitted_files(self):
|
97
|
-
if not self.is_valid():
|
97
|
+
def uncommitted_files(self) -> list[str] | None:
|
98
|
+
if self.repo is None or not self.is_valid():
|
98
99
|
return None
|
99
100
|
|
100
|
-
return [item.a_path for item in self.repo.index.diff(None)]
|
101
|
+
return [cast("str", item.a_path) for item in self.repo.index.diff(None)]
|
101
102
|
|
102
103
|
@property
|
103
|
-
def ahead_commits(self):
|
104
|
-
if not self.is_valid():
|
104
|
+
def ahead_commits(self) -> list[Commit] | None:
|
105
|
+
if self.repo is None or not self.is_valid():
|
105
106
|
return None
|
106
107
|
|
107
108
|
try:
|
108
|
-
|
109
|
+
tracking_branch_info = self.get_tracking_branch_remote()
|
110
|
+
if tracking_branch_info is None:
|
111
|
+
return None
|
112
|
+
|
113
|
+
remote, branch_name = tracking_branch_info
|
109
114
|
remote_branch = f"{remote.name}/{branch_name}"
|
110
115
|
|
111
116
|
return list(self.repo.iter_commits(f"{remote_branch}..{branch_name}"))
|
112
117
|
except Exception:
|
113
118
|
return []
|
114
119
|
|
115
|
-
def get_tracking_branch_remote(self):
|
116
|
-
if not self.is_valid():
|
120
|
+
def get_tracking_branch_remote(self) -> tuple[Remote, str] | None:
|
121
|
+
if self.repo is None or not self.is_valid():
|
117
122
|
return None
|
118
123
|
|
119
124
|
tracking_branch = self.tracking_branch
|
@@ -21,7 +21,7 @@ import streamlit as st
|
|
21
21
|
from streamlit.hello.utils import show_code
|
22
22
|
|
23
23
|
|
24
|
-
def data_frame_demo():
|
24
|
+
def data_frame_demo() -> None:
|
25
25
|
@st.cache_data
|
26
26
|
def get_un_data() -> pd.DataFrame:
|
27
27
|
AWS_BUCKET_URL = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
|
streamlit/hello/mapping_demo.py
CHANGED
streamlit/hello/plotting_demo.py
CHANGED
@@ -20,14 +20,14 @@ import streamlit as st
|
|
20
20
|
from streamlit.hello.utils import show_code
|
21
21
|
|
22
22
|
|
23
|
-
def plotting_demo():
|
23
|
+
def plotting_demo() -> None:
|
24
24
|
progress_bar = st.sidebar.progress(0)
|
25
25
|
status_text = st.sidebar.empty()
|
26
|
-
last_rows = np.random.randn(1, 1)
|
26
|
+
last_rows = np.random.randn(1, 1) # noqa: NPY002
|
27
27
|
chart = st.line_chart(last_rows)
|
28
28
|
|
29
29
|
for i in range(1, 101):
|
30
|
-
new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0)
|
30
|
+
new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0) # noqa: NPY002
|
31
31
|
status_text.text(f"{i}% complete")
|
32
32
|
chart.add_rows(new_rows)
|
33
33
|
progress_bar.progress(i)
|
streamlit/hello/streamlit_app.py
CHANGED
streamlit/hello/utils.py
CHANGED
@@ -14,11 +14,12 @@
|
|
14
14
|
|
15
15
|
import inspect
|
16
16
|
import textwrap
|
17
|
+
from typing import Any, Callable
|
17
18
|
|
18
19
|
import streamlit as st
|
19
20
|
|
20
21
|
|
21
|
-
def show_code(demo):
|
22
|
+
def show_code(demo: Callable[..., Any]) -> None:
|
22
23
|
"""Showing the code of the demo."""
|
23
24
|
show_code = st.sidebar.checkbox("Show code", True)
|
24
25
|
if show_code:
|
streamlit/navigation/page.py
CHANGED
@@ -289,12 +289,11 @@ class StreamlitPage:
|
|
289
289
|
if callable(self._page):
|
290
290
|
self._page()
|
291
291
|
return
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
exec(code, module.__dict__) # noqa: S102
|
292
|
+
code = ctx.pages_manager.get_page_script_byte_code(str(self._page))
|
293
|
+
module = types.ModuleType("__main__")
|
294
|
+
# We want __file__ to be the string path to the script
|
295
|
+
module.__dict__["__file__"] = str(self._page)
|
296
|
+
exec(code, module.__dict__) # noqa: S102
|
298
297
|
|
299
298
|
@property
|
300
299
|
def _script_hash(self) -> str:
|
streamlit/runtime/app_session.py
CHANGED
@@ -151,7 +151,7 @@ class AppSession:
|
|
151
151
|
self._client_state = ClientState()
|
152
152
|
|
153
153
|
self._local_sources_watcher: LocalSourcesWatcher | None = None
|
154
|
-
self._stop_config_listener: Callable[[],
|
154
|
+
self._stop_config_listener: Callable[[], None] | None = None
|
155
155
|
self._stop_pages_listener: Callable[[], None] | None = None
|
156
156
|
|
157
157
|
if config.get_option("server.fileWatcherType") != "none":
|
@@ -792,12 +792,12 @@ class AppSession:
|
|
792
792
|
msg.git_info_changed.branch = branch
|
793
793
|
msg.git_info_changed.module = module
|
794
794
|
|
795
|
-
msg.git_info_changed.untracked_files[:] = repo.untracked_files
|
796
|
-
msg.git_info_changed.uncommitted_files[:] = repo.uncommitted_files
|
795
|
+
msg.git_info_changed.untracked_files[:] = repo.untracked_files or []
|
796
|
+
msg.git_info_changed.uncommitted_files[:] = repo.uncommitted_files or []
|
797
797
|
|
798
798
|
if repo.is_head_detached:
|
799
799
|
msg.git_info_changed.state = GitInfo.GitStates.HEAD_DETACHED
|
800
|
-
elif len(repo.ahead_commits) > 0:
|
800
|
+
elif repo.ahead_commits and len(repo.ahead_commits) > 0:
|
801
801
|
msg.git_info_changed.state = GitInfo.GitStates.AHEAD_OF_REMOTE
|
802
802
|
else:
|
803
803
|
msg.git_info_changed.state = GitInfo.GitStates.DEFAULT
|
@@ -147,7 +147,7 @@ class CachedDataFuncInfo(CachedFuncInfo):
|
|
147
147
|
class DataCaches(CacheStatsProvider):
|
148
148
|
"""Manages all DataCache instances."""
|
149
149
|
|
150
|
-
def __init__(self):
|
150
|
+
def __init__(self) -> None:
|
151
151
|
self._caches_lock = threading.Lock()
|
152
152
|
self._function_caches: dict[str, DataCache] = {}
|
153
153
|
|
@@ -566,7 +566,7 @@ class CacheDataAPI:
|
|
566
566
|
if experimental_allow_widgets:
|
567
567
|
show_widget_replay_deprecation("cache_data")
|
568
568
|
|
569
|
-
def wrapper(f):
|
569
|
+
def wrapper(f): # noqa: ANN001, ANN202
|
570
570
|
return make_cached_func_wrapper(
|
571
571
|
CachedDataFuncInfo(
|
572
572
|
func=f,
|
@@ -30,7 +30,7 @@ def get_cached_func_name_md(func: Any) -> str:
|
|
30
30
|
"""Get markdown representation of the function name."""
|
31
31
|
if hasattr(func, "__name__"):
|
32
32
|
return f"`{func.__name__}()`"
|
33
|
-
|
33
|
+
if hasattr(type(func), "__name__"):
|
34
34
|
return f"`{type(func).__name__}`"
|
35
35
|
return f"`{type(func)}`"
|
36
36
|
|
@@ -69,7 +69,7 @@ def _equal_validate_funcs(a: ValidateFunc | None, b: ValidateFunc | None) -> boo
|
|
69
69
|
class ResourceCaches(CacheStatsProvider):
|
70
70
|
"""Manages all ResourceCache instances."""
|
71
71
|
|
72
|
-
def __init__(self):
|
72
|
+
def __init__(self) -> None:
|
73
73
|
self._caches_lock = threading.Lock()
|
74
74
|
self._function_caches: dict[str, ResourceCache] = {}
|
75
75
|
|
@@ -65,7 +65,7 @@ TTLCACHE_TIMER = time.monotonic
|
|
65
65
|
class Cache:
|
66
66
|
"""Function cache interface. Caches persist across script runs."""
|
67
67
|
|
68
|
-
def __init__(self):
|
68
|
+
def __init__(self) -> None:
|
69
69
|
self._value_locks: dict[str, threading.Lock] = defaultdict(threading.Lock)
|
70
70
|
self._value_locks_lock = threading.Lock()
|
71
71
|
|
@@ -196,7 +196,7 @@ class CachedFunc:
|
|
196
196
|
def __repr__(self) -> str:
|
197
197
|
return f"<CachedFunc: {self._info.func}>"
|
198
198
|
|
199
|
-
def __get__(self, instance, owner=None):
|
199
|
+
def __get__(self, instance: Any, owner: Any | None = None) -> Any:
|
200
200
|
"""CachedFunc implements descriptor protocol to support cache methods."""
|
201
201
|
if instance is None:
|
202
202
|
return self
|
@@ -346,7 +346,7 @@ class CachedFunc:
|
|
346
346
|
return_value=computed_value, func=self._info.func
|
347
347
|
)
|
348
348
|
|
349
|
-
def clear(self, *args, **kwargs):
|
349
|
+
def clear(self, *args: Any, **kwargs: Any) -> None:
|
350
350
|
"""Clear the cached function's associated cache.
|
351
351
|
|
352
352
|
If no arguments are passed, Streamlit will clear all values cached for
|
@@ -218,8 +218,7 @@ class CachedMessageReplayContext(threading.local):
|
|
218
218
|
"""
|
219
219
|
if len(self._seen_dg_stack) > 0 and acting_on_id in self._seen_dg_stack[-1]:
|
220
220
|
return acting_on_id
|
221
|
-
|
222
|
-
return invoked_id
|
221
|
+
return invoked_id
|
223
222
|
|
224
223
|
def save_image_data(
|
225
224
|
self, image_data: bytes | str, mimetype: str, image_id: str
|
@@ -182,7 +182,7 @@ class _HashStack:
|
|
182
182
|
This causes the "in" to crash since it expects a boolean.
|
183
183
|
"""
|
184
184
|
|
185
|
-
def __init__(self):
|
185
|
+
def __init__(self) -> None:
|
186
186
|
self._stack: collections.OrderedDict[int, list[Any]] = collections.OrderedDict()
|
187
187
|
# A function that we decorate with streamlit cache
|
188
188
|
# primitive (st.cache_data or st.cache_resource).
|
@@ -213,7 +213,7 @@ class _HashStack:
|
|
213
213
|
class _HashStacks:
|
214
214
|
"""Stacks of what has been hashed, with at most 1 stack per thread."""
|
215
215
|
|
216
|
-
def __init__(self):
|
216
|
+
def __init__(self) -> None:
|
217
217
|
self._stacks: weakref.WeakKeyDictionary[threading.Thread, _HashStack] = (
|
218
218
|
weakref.WeakKeyDictionary()
|
219
219
|
)
|
@@ -131,9 +131,8 @@ class InMemoryCacheStorageWrapper(CacheStorage):
|
|
131
131
|
_LOGGER.debug("Memory cache HIT: %s", key)
|
132
132
|
return entry
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
raise CacheStorageKeyNotFoundError("Key not found in mem cache")
|
134
|
+
_LOGGER.debug("Memory cache MISS: %s", key)
|
135
|
+
raise CacheStorageKeyNotFoundError("Key not found in mem cache")
|
137
136
|
|
138
137
|
def _write_to_mem_cache(self, key: str, entry_bytes: bytes) -> None:
|
139
138
|
with self._mem_cache_lock:
|
streamlit/runtime/context.py
CHANGED
@@ -328,11 +328,7 @@ class ContextProxy:
|
|
328
328
|
url_without_page_prefix = maybe_trim_page_path(
|
329
329
|
url_from_frontend, ctx.pages_manager
|
330
330
|
)
|
331
|
-
|
332
|
-
url_without_page_prefix, ctx.pages_manager
|
333
|
-
)
|
334
|
-
|
335
|
-
return url_with_page_prefix
|
331
|
+
return maybe_add_page_path(url_without_page_prefix, ctx.pages_manager)
|
336
332
|
|
337
333
|
@property
|
338
334
|
@gather_metrics("context.ip_address")
|
streamlit/runtime/credentials.py
CHANGED
@@ -66,7 +66,7 @@ Collecting usage statistics. To deactivate, set browser.gatherUsageStats to fals
|
|
66
66
|
"""
|
67
67
|
|
68
68
|
|
69
|
-
def _send_email(email: str) -> None:
|
69
|
+
def _send_email(email: str | None) -> None:
|
70
70
|
"""Send the user's email for metrics, if submitted."""
|
71
71
|
import requests
|
72
72
|
|
@@ -124,15 +124,15 @@ class Credentials:
|
|
124
124
|
|
125
125
|
return cast("Credentials", Credentials._singleton)
|
126
126
|
|
127
|
-
def __init__(self):
|
127
|
+
def __init__(self) -> None:
|
128
128
|
"""Initialize class."""
|
129
129
|
if Credentials._singleton is not None:
|
130
130
|
raise RuntimeError(
|
131
131
|
"Credentials already initialized. Use .get_current() instead"
|
132
132
|
)
|
133
133
|
|
134
|
-
self.activation = None
|
135
|
-
self._conf_file = _get_credential_file_path()
|
134
|
+
self.activation: _Activation | None = None
|
135
|
+
self._conf_file: str = _get_credential_file_path()
|
136
136
|
|
137
137
|
Credentials._singleton = self
|
138
138
|
|
@@ -41,7 +41,7 @@ class ForwardMsgQueue:
|
|
41
41
|
"""
|
42
42
|
ForwardMsgQueue._before_enqueue_msg = before_enqueue_msg
|
43
43
|
|
44
|
-
def __init__(self):
|
44
|
+
def __init__(self) -> None:
|
45
45
|
self._queue: list[ForwardMsg] = []
|
46
46
|
# A mapping of (delta_path -> _queue.indexof(msg)) for each
|
47
47
|
# Delta message in the queue. We use this for coalescing
|
@@ -38,8 +38,7 @@ def _get_session_id() -> str:
|
|
38
38
|
# "streamlit run myscript.py". In which case the session ID doesn't
|
39
39
|
# matter and can just be a constant, as there's only ever "session".
|
40
40
|
return "dontcare"
|
41
|
-
|
42
|
-
return ctx.session_id
|
41
|
+
return ctx.session_id
|
43
42
|
|
44
43
|
|
45
44
|
class MediaFileMetadata:
|
@@ -92,7 +92,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
|
|
92
92
|
|
93
93
|
self.file_storage[session_id][file.file_id] = file
|
94
94
|
|
95
|
-
def remove_file(self, session_id, file_id):
|
95
|
+
def remove_file(self, session_id: str, file_id: str) -> None:
|
96
96
|
"""Remove file with given file_id associated with a given session."""
|
97
97
|
session_storage = self.file_storage[session_id]
|
98
98
|
session_storage.pop(file_id, None)
|
streamlit/runtime/runtime.py
CHANGED
@@ -50,7 +50,7 @@ class modified_sys_path: # noqa: N801
|
|
50
50
|
def __repr__(self) -> str:
|
51
51
|
return util.repr_(self)
|
52
52
|
|
53
|
-
def __enter__(self):
|
53
|
+
def __enter__(self) -> None:
|
54
54
|
if self._main_script_path not in sys.path:
|
55
55
|
sys.path.insert(0, self._main_script_path)
|
56
56
|
self._added_path = True
|