streamlit-nightly 1.45.1.dev20250507__py3-none-any.whl → 1.45.1.dev20250509__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/cli_util.py +3 -2
- streamlit/commands/logo.py +2 -2
- streamlit/commands/navigation.py +5 -4
- streamlit/commands/page_config.py +3 -1
- streamlit/components/types/base_custom_component.py +7 -7
- streamlit/components/v1/custom_component.py +6 -6
- streamlit/config.py +84 -48
- streamlit/config_option.py +2 -2
- streamlit/config_util.py +20 -12
- streamlit/connections/base_connection.py +3 -3
- streamlit/connections/snowflake_connection.py +5 -5
- streamlit/connections/snowpark_connection.py +3 -3
- streamlit/connections/sql_connection.py +9 -10
- streamlit/cursor.py +6 -6
- streamlit/delta_generator.py +7 -6
- streamlit/delta_generator_singletons.py +2 -2
- streamlit/deprecation_util.py +1 -1
- streamlit/elements/arrow.py +2 -3
- streamlit/elements/deck_gl_json_chart.py +30 -17
- streamlit/elements/dialog_decorator.py +3 -3
- streamlit/elements/doc_string.py +20 -20
- streamlit/elements/layouts.py +26 -7
- streamlit/elements/lib/built_in_chart_utils.py +37 -39
- streamlit/elements/lib/color_util.py +3 -3
- streamlit/elements/lib/column_types.py +2 -2
- streamlit/elements/lib/dialog.py +2 -2
- streamlit/elements/lib/event_utils.py +1 -1
- streamlit/elements/lib/mutable_status_container.py +1 -1
- streamlit/elements/lib/policies.py +3 -3
- streamlit/elements/lib/utils.py +5 -5
- streamlit/elements/map.py +20 -15
- streamlit/elements/progress.py +9 -12
- streamlit/elements/vega_charts.py +2 -2
- streamlit/elements/widgets/button_group.py +2 -2
- streamlit/elements/widgets/data_editor.py +2 -2
- streamlit/elements/widgets/multiselect.py +2 -2
- streamlit/elements/widgets/selectbox.py +1 -1
- streamlit/elements/widgets/slider.py +16 -14
- streamlit/elements/write.py +3 -6
- streamlit/errors.py +34 -21
- streamlit/external/langchain/streamlit_callback_handler.py +2 -2
- streamlit/file_util.py +8 -8
- streamlit/git_util.py +1 -1
- streamlit/hello/dataframe_demo.py +1 -1
- streamlit/hello/mapping_demo.py +1 -1
- streamlit/navigation/page.py +1 -1
- streamlit/proto/Block_pb2.py +38 -29
- streamlit/proto/Block_pb2.pyi +68 -4
- streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
- streamlit/proto/GapSize_pb2.py +29 -0
- streamlit/proto/GapSize_pb2.pyi +70 -0
- streamlit/proto/HeightConfig_pb2.py +27 -0
- streamlit/proto/HeightConfig_pb2.pyi +48 -0
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +15 -1
- streamlit/runtime/app_session.py +2 -2
- streamlit/runtime/caching/cache_data_api.py +9 -5
- streamlit/runtime/caching/cache_errors.py +3 -3
- streamlit/runtime/caching/cache_resource_api.py +7 -7
- streamlit/runtime/caching/cache_utils.py +9 -9
- streamlit/runtime/caching/cached_message_replay.py +1 -1
- streamlit/runtime/caching/hashing.py +70 -74
- streamlit/runtime/caching/legacy_cache_api.py +1 -1
- streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +3 -1
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +1 -1
- streamlit/runtime/connection_factory.py +12 -12
- streamlit/runtime/context.py +2 -2
- streamlit/runtime/credentials.py +3 -3
- streamlit/runtime/fragment.py +3 -4
- streamlit/runtime/media_file_manager.py +2 -2
- streamlit/runtime/memory_media_file_storage.py +1 -1
- streamlit/runtime/memory_uploaded_file_manager.py +1 -1
- streamlit/runtime/metrics_util.py +5 -6
- streamlit/runtime/pages_manager.py +3 -3
- streamlit/runtime/runtime.py +1 -1
- streamlit/runtime/runtime_util.py +2 -2
- streamlit/runtime/scriptrunner/exec_code.py +10 -3
- streamlit/runtime/scriptrunner/magic.py +13 -8
- streamlit/runtime/scriptrunner/script_runner.py +2 -2
- streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
- streamlit/runtime/scriptrunner_utils/script_run_context.py +6 -5
- streamlit/runtime/secrets.py +8 -11
- streamlit/runtime/state/query_params.py +2 -2
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +17 -15
- streamlit/runtime/stats.py +1 -1
- streamlit/runtime/uploaded_file_manager.py +1 -1
- streamlit/source_util.py +3 -4
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.BgsGCsV4.js → ErrorOutline.esm.C-0hf1-k.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.CCKezPn5.js → FileDownload.esm.B-fFGI-X.js} +1 -1
- streamlit/static/static/js/{FileHelper.CprSF_kT.js → FileHelper.ACYo0OZo.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DiwQ0EtT.js → FormClearHelper.CVNTT-bJ.js} +1 -1
- streamlit/static/static/js/{Hooks.DDqhyZ1_.js → Hooks.C3thlpd2.js} +1 -1
- streamlit/static/static/js/{InputInstructions.BCEZxme4.js → InputInstructions.CwAxousX.js} +1 -1
- streamlit/static/static/js/{ProgressBar.CGdY94g_.js → ProgressBar.xh599Rum.js} +2 -2
- streamlit/static/static/js/{RenderInPortalIfExists.uGJp_Q0v.js → RenderInPortalIfExists.CQLIsNPE.js} +1 -1
- streamlit/static/static/js/{Toolbar.hTlw0-K1.js → Toolbar.LKdyvP0u.js} +1 -1
- streamlit/static/static/js/{index.xsH4HHeE.js → UploadFileInfo.0DCkpDDf.js} +5 -5
- streamlit/static/static/js/{base-input.mGTY3-qU.js → base-input.D8OdS4WW.js} +4 -4
- streamlit/static/static/js/{checkbox.Cg-5cKAh.js → checkbox.DSdYKlOI.js} +2 -2
- streamlit/static/static/js/{createSuper.-HPb1oYT.js → createSuper.B2pyCfWw.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.BpNYxiTp.js → data-grid-overlay-editor.DhO2r0ne.js} +1 -1
- streamlit/static/static/js/{downloader.DS9891pS.js → downloader.C24skoDM.js} +1 -1
- streamlit/static/static/js/{es6.CU1PEL2w.js → es6.DHkvCKPh.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.CgJE2bJN.js → iframeResizer.contentWindow.2ckQaC2c.js} +1 -1
- streamlit/static/static/js/index.0dGwl8CJ.js +1 -0
- streamlit/static/static/js/index.B5A28NpR.js +1 -0
- streamlit/static/static/js/{index.BC0ueJ8H.js → index.B5EFweZ4.js} +1 -1
- streamlit/static/static/js/{index.CyGuL4If.js → index.BAafqHfB.js} +2 -2
- streamlit/static/static/js/{index.DWV80Vyw.js → index.BHTbGZPQ.js} +1 -1
- streamlit/static/static/js/index.BNXtQAj4.js +1 -0
- streamlit/static/static/js/index.BRhKaVdO.js +1 -0
- streamlit/static/static/js/index.BSOiJVQd.js +2 -0
- streamlit/static/static/js/{index.GSYBrzVp.js → index.BVgTQbOJ.js} +1 -1
- streamlit/static/static/js/{index.BTTj6ld4.js → index.BflIniLm.js} +1 -1
- streamlit/static/static/js/{index.DLTqo4pp.js → index.BjeNtZIz.js} +3 -3
- streamlit/static/static/js/{index.DZ6oX-v9.js → index.By-NmdnB.js} +161 -161
- streamlit/static/static/js/{index.DVpzZJNg.js → index.CIoOEhZ2.js} +1 -1
- streamlit/static/static/js/{index.CN91oQMB.js → index.CRCdonis.js} +36 -36
- streamlit/static/static/js/index.CRxaBCJ7.js +1 -0
- streamlit/static/static/js/index.CU-pbYVN.js +1 -0
- streamlit/static/static/js/{index.CzGUd4IN.js → index.CUsk52t2.js} +1 -1
- streamlit/static/static/js/{index.BHVQ94t4.js → index.CVO14oQG.js} +2 -2
- streamlit/static/static/js/index.CXFuA6J-.js +1 -0
- streamlit/static/static/js/{index.DJHUlWgy.js → index.C_dd5q7u.js} +1 -1
- streamlit/static/static/js/{index.Bph6ZoI5.js → index.CjWUnKIN.js} +1 -1
- streamlit/static/static/js/{index.B209tswL.js → index.CkTL9bAR.js} +256 -256
- streamlit/static/static/js/{index.ErkF0SoX.js → index.CsbhsAPy.js} +2 -2
- streamlit/static/static/js/{index.hPjr68pz.js → index.CtCnBUtk.js} +1 -1
- streamlit/static/static/js/{index.BT0p7gAu.js → index.CwuKadAX.js} +1 -1
- streamlit/static/static/js/{index.CtoDsUtq.js → index.D0R7Xh4Z.js} +1 -1
- streamlit/static/static/js/index.D2D75EDw.js +73 -0
- streamlit/static/static/js/index.D4eMiZ1F.js +1 -0
- streamlit/static/static/js/{index.Dh4RKl-F.js → index.D7SCC3z9.js} +1 -1
- streamlit/static/static/js/index.DZiilxEt.js +1 -0
- streamlit/static/static/js/{index.DtqvdV-p.js → index.Dvr1cEJS.js} +1 -1
- streamlit/static/static/js/index.JtIlC6Uq.js +1 -0
- streamlit/static/static/js/index.fz_c3Xh_.js +1 -0
- streamlit/static/static/js/{index.CvFsF3FD.js → index.gFjPlsMT.js} +1 -1
- streamlit/static/static/js/{index.DPJBu2uZ.js → index.jCJYMVED.js} +1 -1
- streamlit/static/static/js/index.xldt56AE.js +1 -0
- streamlit/static/static/js/{index.Bb-Ukg41.js → index.yzoj_DuM.js} +1 -1
- streamlit/static/static/js/{input.DY17i94N.js → input.BP6LX_Bg.js} +2 -2
- streamlit/static/static/js/{memory.DsIIcbSd.js → memory.E9x2ZYJv.js} +1 -1
- streamlit/static/static/js/{mergeWith.cRgGdgvI.js → mergeWith.CZP2AaVS.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.B8Xi2dYq.js → number-overlay-editor.D-Kl79U_.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.BgDi5nUm.js → possibleConstructorReturn.P2ILVC_6.js} +1 -1
- streamlit/static/static/js/{sandbox.BH9emp13.js → sandbox.DfzJIGMV.js} +1 -1
- streamlit/static/static/js/{textarea.DAyShsGG.js → textarea.4PjzfDWF.js} +2 -2
- streamlit/static/static/js/{timepicker.CCH2R2Y0.js → timepicker.DMQdaNzO.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CNffSDCu.js → toConsumableArray.BEdkbHYx.js} +1 -1
- streamlit/static/static/js/{uniqueId.B49CstkV.js → uniqueId.CAs7ftHC.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.CkThOkF9.js → useBasicWidgetState.Cedp0V76.js} +1 -1
- streamlit/static/static/js/useOnInputChange.CvRKHHKx.js +1 -0
- streamlit/static/static/js/{withFullScreenWrapper.UsvF_Jwr.js → withFullScreenWrapper.BbmjZAzW.js} +1 -1
- streamlit/string_util.py +6 -7
- streamlit/temporary_directory.py +12 -3
- streamlit/testing/v1/app_test.py +11 -6
- streamlit/testing/v1/element_tree.py +134 -158
- streamlit/testing/v1/local_script_runner.py +5 -5
- streamlit/testing/v1/util.py +11 -4
- streamlit/type_util.py +3 -4
- streamlit/user_info.py +3 -2
- streamlit/util.py +1 -1
- streamlit/watcher/event_based_path_watcher.py +1 -1
- streamlit/watcher/folder_black_list.py +1 -1
- streamlit/watcher/local_sources_watcher.py +5 -5
- streamlit/watcher/path_watcher.py +1 -1
- streamlit/web/bootstrap.py +2 -1
- streamlit/web/cli.py +12 -11
- streamlit/web/server/browser_websocket_handler.py +1 -1
- streamlit/web/server/component_request_handler.py +1 -1
- streamlit/web/server/media_file_handler.py +2 -1
- streamlit/web/server/oauth_authlib_routes.py +9 -2
- streamlit/web/server/oidc_mixin.py +13 -6
- streamlit/web/server/routes.py +3 -3
- streamlit/web/server/server.py +1 -1
- streamlit/web/server/server_util.py +7 -6
- streamlit/web/server/upload_file_request_handler.py +5 -5
- {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/RECORD +187 -184
- {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/WHEEL +1 -1
- streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
- streamlit/static/static/js/index.BVjgrQ4R.js +0 -1
- streamlit/static/static/js/index.BXYstdPh.js +0 -2
- streamlit/static/static/js/index.BZ9mqzEJ.js +0 -1
- streamlit/static/static/js/index.BhTok8vt.js +0 -1
- streamlit/static/static/js/index.CJPcdxPe.js +0 -1
- streamlit/static/static/js/index.CMOA-8Q2.js +0 -1
- streamlit/static/static/js/index.DAxf3_iz.js +0 -1
- streamlit/static/static/js/index.Dn76KVNf.js +0 -1
- streamlit/static/static/js/index.OngWTN39.js +0 -1
- streamlit/static/static/js/index.PSwG8ayC.js +0 -1
- streamlit/static/static/js/index.UTlCdasa.js +0 -73
- streamlit/static/static/js/index.eR_vQpeg.js +0 -1
- streamlit/static/static/js/index.fLsU9uCJ.js +0 -1
- streamlit/static/static/js/index.kXOZCC_6.js +0 -1
- streamlit/static/static/js/useOnInputChange.BqEq0xFZ.js +0 -1
- {streamlit_nightly-1.45.1.dev20250507.data → streamlit_nightly-1.45.1.dev20250509.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/top_level.txt +0 -0
@@ -43,9 +43,9 @@ class LocalScriptRunner(ScriptRunner):
|
|
43
43
|
script_path: str,
|
44
44
|
session_state: SafeSessionState,
|
45
45
|
pages_manager: PagesManager,
|
46
|
-
args=None,
|
47
|
-
kwargs=None,
|
48
|
-
):
|
46
|
+
args: Any = None,
|
47
|
+
kwargs: Any = None,
|
48
|
+
) -> None:
|
49
49
|
"""Initializes the ScriptRunner for the given script_path."""
|
50
50
|
|
51
51
|
assert os.path.isfile(script_path), f"File not found at {script_path}"
|
@@ -73,7 +73,7 @@ class LocalScriptRunner(ScriptRunner):
|
|
73
73
|
self.event_data: list[Any] = []
|
74
74
|
|
75
75
|
def record_event(
|
76
|
-
sender: ScriptRunner | None, event: ScriptRunnerEvent, **kwargs
|
76
|
+
sender: ScriptRunner | None, event: ScriptRunnerEvent, **kwargs: Any
|
77
77
|
) -> None:
|
78
78
|
# Assert that we're not getting unexpected `sender` params
|
79
79
|
# from ScriptRunner.on_event
|
@@ -103,7 +103,7 @@ class LocalScriptRunner(ScriptRunner):
|
|
103
103
|
def run(
|
104
104
|
self,
|
105
105
|
widget_state: WidgetStates | None = None,
|
106
|
-
query_params=None,
|
106
|
+
query_params: dict[str, Any] | None = None,
|
107
107
|
timeout: float = 3,
|
108
108
|
page_hash: str = "",
|
109
109
|
) -> ElementTree:
|
streamlit/testing/v1/util.py
CHANGED
@@ -15,13 +15,18 @@
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
17
|
from contextlib import contextmanager
|
18
|
-
from typing import Any
|
18
|
+
from typing import TYPE_CHECKING, Any, Callable
|
19
19
|
|
20
20
|
from streamlit import config
|
21
21
|
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from collections.abc import Generator
|
24
|
+
|
22
25
|
|
23
26
|
@contextmanager
|
24
|
-
def patch_config_options(
|
27
|
+
def patch_config_options(
|
28
|
+
config_overrides: dict[str, Any],
|
29
|
+
) -> Generator[None, None, None]:
|
25
30
|
"""A context manager that overrides config options. It can
|
26
31
|
also be used as a function decorator.
|
27
32
|
|
@@ -43,10 +48,12 @@ def patch_config_options(config_overrides: dict[str, Any]):
|
|
43
48
|
yield
|
44
49
|
|
45
50
|
|
46
|
-
def build_mock_config_get_option(
|
51
|
+
def build_mock_config_get_option(
|
52
|
+
overrides_dict: dict[str, Any],
|
53
|
+
) -> Callable[[str], Any]:
|
47
54
|
orig_get_option = config.get_option
|
48
55
|
|
49
|
-
def mock_config_get_option(name):
|
56
|
+
def mock_config_get_option(name: str) -> Any:
|
50
57
|
if name in overrides_dict:
|
51
58
|
return overrides_dict[name]
|
52
59
|
return orig_get_option(name)
|
streamlit/type_util.py
CHANGED
@@ -119,8 +119,7 @@ def is_type(obj: object, fqn_type_pattern: str | re.Pattern[str]) -> bool:
|
|
119
119
|
fqn_type = get_fqn_type(obj)
|
120
120
|
if isinstance(fqn_type_pattern, str):
|
121
121
|
return fqn_type_pattern == fqn_type
|
122
|
-
|
123
|
-
return fqn_type_pattern.match(fqn_type) is not None
|
122
|
+
return fqn_type_pattern.match(fqn_type) is not None
|
124
123
|
|
125
124
|
|
126
125
|
def _is_type_instance(obj: object, type_to_check: str) -> bool:
|
@@ -161,7 +160,7 @@ def to_bytes(obj: BytesLike) -> bytes:
|
|
161
160
|
"""
|
162
161
|
if isinstance(obj, bytearray):
|
163
162
|
return bytes(obj)
|
164
|
-
|
163
|
+
if isinstance(obj, bytes):
|
165
164
|
return obj
|
166
165
|
|
167
166
|
raise RuntimeError(f"{obj} is not convertible to bytes")
|
@@ -317,7 +316,7 @@ def is_pydeck(obj: object) -> TypeGuard[Deck]:
|
|
317
316
|
return is_type(obj, "pydeck.bindings.deck.Deck")
|
318
317
|
|
319
318
|
|
320
|
-
def is_pydantic_model(obj) -> bool:
|
319
|
+
def is_pydantic_model(obj: object) -> bool:
|
321
320
|
"""True if input looks like a Pydantic model instance."""
|
322
321
|
|
323
322
|
if isinstance(obj, type):
|
streamlit/user_info.py
CHANGED
@@ -17,6 +17,7 @@ from __future__ import annotations
|
|
17
17
|
from collections.abc import Iterator, Mapping
|
18
18
|
from typing import (
|
19
19
|
TYPE_CHECKING,
|
20
|
+
Any,
|
20
21
|
Final,
|
21
22
|
NoReturn,
|
22
23
|
Union,
|
@@ -548,10 +549,10 @@ class DeprecatedUserInfoProxy(UserInfoProxy):
|
|
548
549
|
Streamlit.
|
549
550
|
"""
|
550
551
|
|
551
|
-
def __getattribute__(self, name: str):
|
552
|
+
def __getattribute__(self, name: str) -> Any:
|
552
553
|
maybe_show_deprecated_user_warning()
|
553
554
|
return super().__getattribute__(name)
|
554
555
|
|
555
|
-
def __getitem__(self, key: str):
|
556
|
+
def __getitem__(self, key: str) -> Any:
|
556
557
|
maybe_show_deprecated_user_warning()
|
557
558
|
return super().__getitem__(key)
|
streamlit/util.py
CHANGED
@@ -46,7 +46,7 @@ PathWatcher = None
|
|
46
46
|
|
47
47
|
|
48
48
|
class LocalSourcesWatcher:
|
49
|
-
def __init__(self, pages_manager: PagesManager):
|
49
|
+
def __init__(self, pages_manager: PagesManager) -> None:
|
50
50
|
self._pages_manager = pages_manager
|
51
51
|
self._main_script_path = os.path.abspath(self._pages_manager.main_script_path)
|
52
52
|
self._watch_folders = config.get_option("server.folderWatchList")
|
@@ -108,7 +108,7 @@ class LocalSourcesWatcher:
|
|
108
108
|
def register_file_change_callback(self, cb: Callable[[str], None]) -> None:
|
109
109
|
self._on_path_changed.append(cb)
|
110
110
|
|
111
|
-
def on_path_changed(self, filepath):
|
111
|
+
def on_path_changed(self, filepath: str) -> None:
|
112
112
|
_LOGGER.debug("Path changed: %s", filepath)
|
113
113
|
if filepath not in self._watched_modules:
|
114
114
|
# Check if this is a file in a watched directory
|
@@ -143,7 +143,7 @@ class LocalSourcesWatcher:
|
|
143
143
|
for cb in self._on_path_changed:
|
144
144
|
cb(filepath)
|
145
145
|
|
146
|
-
def close(self):
|
146
|
+
def close(self) -> None:
|
147
147
|
for wm in self._watched_modules.values():
|
148
148
|
wm.watcher.close()
|
149
149
|
self._watched_modules = {}
|
@@ -190,10 +190,10 @@ class LocalSourcesWatcher:
|
|
190
190
|
wm.watcher.close()
|
191
191
|
del self._watched_modules[filepath]
|
192
192
|
|
193
|
-
def _file_is_new(self, filepath):
|
193
|
+
def _file_is_new(self, filepath: str) -> bool:
|
194
194
|
return filepath not in self._watched_modules
|
195
195
|
|
196
|
-
def _file_should_be_watched(self, filepath):
|
196
|
+
def _file_should_be_watched(self, filepath: str) -> bool:
|
197
197
|
# Using short circuiting for performance.
|
198
198
|
return self._file_is_new(filepath) and (
|
199
199
|
file_util.file_is_in_folder_glob(filepath, self._script_folder)
|
streamlit/web/bootstrap.py
CHANGED
@@ -141,7 +141,8 @@ def _fix_pydeck_mapbox_api_warning() -> None:
|
|
141
141
|
will throw an exception.
|
142
142
|
"""
|
143
143
|
|
144
|
-
|
144
|
+
if "MAPBOX_API_KEY" not in os.environ:
|
145
|
+
os.environ["MAPBOX_API_KEY"] = config.get_option("mapbox.token")
|
145
146
|
|
146
147
|
|
147
148
|
def _maybe_print_static_folder_warning(main_script_path: str) -> None:
|
streamlit/web/cli.py
CHANGED
@@ -63,10 +63,12 @@ def _convert_config_option_to_click_option(
|
|
63
63
|
}
|
64
64
|
|
65
65
|
|
66
|
-
def _make_sensitive_option_callback(
|
67
|
-
|
66
|
+
def _make_sensitive_option_callback(
|
67
|
+
config_option: ConfigOption,
|
68
|
+
) -> Callable[[click.Context, click.Parameter, Any], None]:
|
69
|
+
def callback(_ctx: click.Context, _param: click.Parameter, cli_value: Any) -> None:
|
68
70
|
if cli_value is None:
|
69
|
-
return
|
71
|
+
return
|
70
72
|
raise SystemExit(
|
71
73
|
f"Setting {config_option.key!r} option using the CLI flag is not allowed. "
|
72
74
|
f"Set this option in the configuration file or environment "
|
@@ -104,7 +106,7 @@ def configurator_options(func: F) -> F:
|
|
104
106
|
type=parsed_parameter["type"],
|
105
107
|
multiple=parsed_parameter["multiple"],
|
106
108
|
**click_option_kwargs,
|
107
|
-
)
|
109
|
+
) # type: ignore
|
108
110
|
func = config_option(func)
|
109
111
|
return func
|
110
112
|
|
@@ -198,7 +200,7 @@ def main_hello(**kwargs):
|
|
198
200
|
@configurator_options
|
199
201
|
@click.argument("target", required=True, envvar="STREAMLIT_RUN_TARGET")
|
200
202
|
@click.argument("args", nargs=-1)
|
201
|
-
def main_run(target: str, args=None, **kwargs):
|
203
|
+
def main_run(target: str, args: list[str] | None = None, **kwargs: Any) -> None:
|
202
204
|
"""Run a Python script, piping stderr to Streamlit.
|
203
205
|
|
204
206
|
The script can be local or it can be an url. In the latter case, Streamlit
|
@@ -216,10 +218,9 @@ def main_run(target: str, args=None, **kwargs):
|
|
216
218
|
"Streamlit requires raw Python (.py) files, but the provided file has no extension.\n"
|
217
219
|
"For more information, please see https://docs.streamlit.io"
|
218
220
|
)
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
)
|
221
|
+
raise click.BadArgumentUsage(
|
222
|
+
f"Streamlit requires raw Python (.py) files, not {extension}.\nFor more information, please see https://docs.streamlit.io"
|
223
|
+
)
|
223
224
|
|
224
225
|
if url_util.is_url(target):
|
225
226
|
from streamlit.temporary_directory import TemporaryDirectory
|
@@ -260,7 +261,7 @@ def _get_command_line_as_string() -> str | None:
|
|
260
261
|
|
261
262
|
|
262
263
|
def _main_run(
|
263
|
-
file,
|
264
|
+
file: str,
|
264
265
|
args: list[str] | None = None,
|
265
266
|
flag_options: dict[str, Any] | None = None,
|
266
267
|
) -> None:
|
@@ -368,7 +369,7 @@ def test_prog_name():
|
|
368
369
|
|
369
370
|
@main.command("init")
|
370
371
|
@click.argument("directory", required=False)
|
371
|
-
def main_init(directory: str | None = None):
|
372
|
+
def main_init(directory: str | None = None) -> None:
|
372
373
|
"""Initialize a new Streamlit project.
|
373
374
|
|
374
375
|
If DIRECTORY is specified, create it and initialize the project there.
|
@@ -154,7 +154,7 @@ class BrowserWebSocketHandler(WebSocketHandler, SessionClient):
|
|
154
154
|
|
155
155
|
return None
|
156
156
|
|
157
|
-
def open(self, *args, **kwargs) -> Awaitable[None] | None:
|
157
|
+
def open(self, *args: Any, **kwargs: Any) -> Awaitable[None] | None:
|
158
158
|
user_info: dict[str, str | bool | None] = {}
|
159
159
|
|
160
160
|
existing_session_id = None
|
@@ -30,7 +30,7 @@ _LOGGER: Final = get_logger(__name__)
|
|
30
30
|
|
31
31
|
|
32
32
|
class ComponentRequestHandler(tornado.web.RequestHandler):
|
33
|
-
def initialize(self, registry: BaseComponentRegistry):
|
33
|
+
def initialize(self, registry: BaseComponentRegistry) -> None:
|
34
34
|
self._registry = registry
|
35
35
|
|
36
36
|
def get(self, path: str) -> None:
|
@@ -14,6 +14,7 @@
|
|
14
14
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
+
from typing import Any
|
17
18
|
from urllib.parse import quote
|
18
19
|
|
19
20
|
import tornado.web
|
@@ -114,7 +115,7 @@ class MediaFileHandler(tornado.web.StaticFileHandler):
|
|
114
115
|
@classmethod
|
115
116
|
def get_content(
|
116
117
|
cls, abspath: str, start: int | None = None, end: int | None = None
|
117
|
-
):
|
118
|
+
) -> Any:
|
118
119
|
_LOGGER.debug("MediaFileHandler: GET %s", abspath)
|
119
120
|
|
120
121
|
try:
|
@@ -14,7 +14,7 @@
|
|
14
14
|
from __future__ import annotations
|
15
15
|
|
16
16
|
import json
|
17
|
-
from typing import Any, Final
|
17
|
+
from typing import Any, Final, cast
|
18
18
|
from urllib.parse import urlparse
|
19
19
|
|
20
20
|
import tornado.web
|
@@ -74,6 +74,13 @@ class AuthHandlerMixin(tornado.web.RequestHandler):
|
|
74
74
|
|
75
75
|
def set_auth_cookie(self, user_info: dict[str, Any]) -> None:
|
76
76
|
serialized_cookie_value = json.dumps(user_info)
|
77
|
+
|
78
|
+
# log error if cookie value is larger than 4096 bytes
|
79
|
+
if len(serialized_cookie_value.encode()) > 4096:
|
80
|
+
_LOGGER.error(
|
81
|
+
"Authentication cookie size exceeds maximum browser limit of 4096 bytes. Authentication may fail."
|
82
|
+
)
|
83
|
+
|
77
84
|
try:
|
78
85
|
# We don't specify Tornado secure flag here because it leads to missing cookie on Safari.
|
79
86
|
# The OIDC flow should work only on secure context anyway (localhost or HTTPS),
|
@@ -161,7 +168,7 @@ class AuthCallbackHandler(AuthHandlerMixin, tornado.web.RequestHandler):
|
|
161
168
|
|
162
169
|
client, _ = create_oauth_client(provider)
|
163
170
|
token = client.authorize_access_token(self)
|
164
|
-
user = token.get("userinfo")
|
171
|
+
user = cast("dict[str, Any]", token.get("userinfo"))
|
165
172
|
|
166
173
|
cookie_value = dict(user, origin=origin, is_logged_in=True)
|
167
174
|
if user:
|
@@ -12,6 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
# ruff: noqa: ANN201
|
16
|
+
|
17
|
+
from typing import Any, cast
|
18
|
+
|
15
19
|
import tornado.web
|
16
20
|
from authlib.integrations.base_client import ( # type: ignore[import-untyped]
|
17
21
|
BaseApp,
|
@@ -38,8 +42,11 @@ class TornadoOAuth2App(OAuth2Mixin, OpenIDMixin, BaseApp): # type: ignore[misc]
|
|
38
42
|
return result
|
39
43
|
|
40
44
|
def authorize_redirect(
|
41
|
-
self,
|
42
|
-
|
45
|
+
self,
|
46
|
+
request_handler: tornado.web.RequestHandler,
|
47
|
+
redirect_uri: Any = None,
|
48
|
+
**kwargs: Any,
|
49
|
+
) -> None:
|
43
50
|
"""Create a HTTP Redirect for Authorization Endpoint.
|
44
51
|
|
45
52
|
:param request_handler: HTTP request instance from Tornado.
|
@@ -52,8 +59,8 @@ class TornadoOAuth2App(OAuth2Mixin, OpenIDMixin, BaseApp): # type: ignore[misc]
|
|
52
59
|
request_handler.redirect(auth_context["url"], status=302)
|
53
60
|
|
54
61
|
def authorize_access_token(
|
55
|
-
self, request_handler: tornado.web.RequestHandler, **kwargs
|
56
|
-
):
|
62
|
+
self, request_handler: tornado.web.RequestHandler, **kwargs: Any
|
63
|
+
) -> dict[str, Any]:
|
57
64
|
"""
|
58
65
|
:param request_handler: HTTP request instance from Tornado.
|
59
66
|
:return: A token dict.
|
@@ -82,9 +89,9 @@ class TornadoOAuth2App(OAuth2Mixin, OpenIDMixin, BaseApp): # type: ignore[misc]
|
|
82
89
|
token, nonce=state_data["nonce"], claims_options=claims_options
|
83
90
|
)
|
84
91
|
token = {**token, "userinfo": userinfo}
|
85
|
-
return token
|
92
|
+
return cast("dict[str, Any]", token)
|
86
93
|
|
87
|
-
def _save_authorize_data(self, **kwargs):
|
94
|
+
def _save_authorize_data(self, **kwargs: Any) -> None:
|
88
95
|
"""Authlib underlying uses the concept of "session" to store state data.
|
89
96
|
In Tornado, we don't have a session, so we use the framework's cache option.
|
90
97
|
"""
|
streamlit/web/server/routes.py
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
17
|
import os
|
18
|
-
from typing import TYPE_CHECKING
|
18
|
+
from typing import TYPE_CHECKING, Any
|
19
19
|
|
20
20
|
import tornado.web
|
21
21
|
|
@@ -48,7 +48,7 @@ class StaticFileHandler(tornado.web.StaticFileHandler):
|
|
48
48
|
path: str,
|
49
49
|
default_filename: str | None = None,
|
50
50
|
reserved_paths: Sequence[str] = (),
|
51
|
-
):
|
51
|
+
) -> None:
|
52
52
|
self._reserved_paths = reserved_paths
|
53
53
|
|
54
54
|
super().initialize(path, default_filename)
|
@@ -86,7 +86,7 @@ class StaticFileHandler(tornado.web.StaticFileHandler):
|
|
86
86
|
|
87
87
|
raise
|
88
88
|
|
89
|
-
def write_error(self, status_code: int, **kwargs) -> None:
|
89
|
+
def write_error(self, status_code: int, **kwargs: Any) -> None:
|
90
90
|
if status_code == 404:
|
91
91
|
index_file = os.path.join(file_util.get_static_dir(), "index.html")
|
92
92
|
self.render(index_file)
|
streamlit/web/server/server.py
CHANGED
@@ -244,7 +244,7 @@ def start_listening_tcp_socket(http_server: HTTPServer) -> None:
|
|
244
244
|
|
245
245
|
|
246
246
|
class Server:
|
247
|
-
def __init__(self, main_script_path: str, is_hello: bool):
|
247
|
+
def __init__(self, main_script_path: str, is_hello: bool) -> None:
|
248
248
|
"""Create the server. It won't be started yet."""
|
249
249
|
_set_tornado_log_levels()
|
250
250
|
self.initialize_mimetypes()
|
@@ -16,7 +16,7 @@
|
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
from typing import TYPE_CHECKING, Callable, Final, Literal
|
19
|
+
from typing import TYPE_CHECKING, Callable, Final, Literal, cast
|
20
20
|
from urllib.parse import urljoin
|
21
21
|
|
22
22
|
from streamlit import config, net_util, url_util
|
@@ -87,12 +87,12 @@ def get_cookie_secret() -> str:
|
|
87
87
|
return cookie_secret
|
88
88
|
|
89
89
|
|
90
|
-
def is_xsrf_enabled():
|
90
|
+
def is_xsrf_enabled() -> bool:
|
91
91
|
csrf_enabled = config.get_option("server.enableXsrfProtection")
|
92
92
|
if not csrf_enabled and secrets_singleton.load_if_toml_exists():
|
93
93
|
auth_section = secrets_singleton.get("auth", None)
|
94
94
|
csrf_enabled = csrf_enabled or auth_section is not None
|
95
|
-
return csrf_enabled
|
95
|
+
return cast("bool", csrf_enabled)
|
96
96
|
|
97
97
|
|
98
98
|
def _get_server_address_if_manually_set() -> str | None:
|
@@ -102,17 +102,18 @@ def _get_server_address_if_manually_set() -> str | None:
|
|
102
102
|
|
103
103
|
|
104
104
|
def make_url_path_regex(
|
105
|
-
*path
|
105
|
+
*path: str,
|
106
|
+
trailing_slash: Literal["optional", "required", "prohibited"] = "optional",
|
106
107
|
) -> str:
|
107
108
|
"""Get a regex of the form ^/foo/bar/baz/?$ for a path (foo, bar, baz)."""
|
108
|
-
|
109
|
+
filtered_paths = [x.strip("/") for x in path if x] # Filter out falsely components.
|
109
110
|
path_format = r"^/%s$"
|
110
111
|
if trailing_slash == "optional":
|
111
112
|
path_format = r"^/%s/?$"
|
112
113
|
elif trailing_slash == "required":
|
113
114
|
path_format = r"^/%s/$"
|
114
115
|
|
115
|
-
return path_format % "/".join(
|
116
|
+
return path_format % "/".join(filtered_paths)
|
116
117
|
|
117
118
|
|
118
119
|
def get_url(host_ip: str) -> str:
|
@@ -35,7 +35,7 @@ class UploadFileRequestHandler(tornado.web.RequestHandler):
|
|
35
35
|
self,
|
36
36
|
file_mgr: MemoryUploadedFileManager,
|
37
37
|
is_active_session: Callable[[str], bool],
|
38
|
-
):
|
38
|
+
) -> None:
|
39
39
|
"""
|
40
40
|
Parameters
|
41
41
|
----------
|
@@ -49,7 +49,7 @@ class UploadFileRequestHandler(tornado.web.RequestHandler):
|
|
49
49
|
self._file_mgr = file_mgr
|
50
50
|
self._is_active_session = is_active_session
|
51
51
|
|
52
|
-
def set_default_headers(self):
|
52
|
+
def set_default_headers(self) -> None:
|
53
53
|
self.set_header("Access-Control-Allow-Methods", "PUT, OPTIONS, DELETE")
|
54
54
|
self.set_header("Access-Control-Allow-Headers", "Content-Type")
|
55
55
|
if is_xsrf_enabled():
|
@@ -63,7 +63,7 @@ class UploadFileRequestHandler(tornado.web.RequestHandler):
|
|
63
63
|
elif routes.allow_cross_origin_requests():
|
64
64
|
self.set_header("Access-Control-Allow-Origin", "*")
|
65
65
|
|
66
|
-
def options(self, **kwargs):
|
66
|
+
def options(self, **kwargs: Any) -> None:
|
67
67
|
"""/OPTIONS handler for preflight CORS checks.
|
68
68
|
|
69
69
|
When a browser is making a CORS request, it may sometimes first
|
@@ -83,7 +83,7 @@ class UploadFileRequestHandler(tornado.web.RequestHandler):
|
|
83
83
|
self.set_status(204)
|
84
84
|
self.finish()
|
85
85
|
|
86
|
-
def put(self, **kwargs):
|
86
|
+
def put(self, **kwargs: Any) -> None:
|
87
87
|
"""Receive an uploaded file and add it to our UploadedFileManager."""
|
88
88
|
|
89
89
|
args: dict[str, list[bytes]] = {}
|
@@ -129,7 +129,7 @@ class UploadFileRequestHandler(tornado.web.RequestHandler):
|
|
129
129
|
self._file_mgr.add_file(session_id=session_id, file=uploaded_files[0])
|
130
130
|
self.set_status(204)
|
131
131
|
|
132
|
-
def delete(self, **kwargs):
|
132
|
+
def delete(self, **kwargs: Any) -> None:
|
133
133
|
"""Delete file request handler."""
|
134
134
|
session_id = self.path_kwargs["session_id"]
|
135
135
|
file_id = self.path_kwargs["file_id"]
|