streamlit-nightly 1.45.1.dev20250511__py3-none-any.whl → 1.45.2.dev20250513__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/experimental_query_params.py +1 -1
- streamlit/commands/navigation.py +1 -4
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/config.py +16 -18
- streamlit/config_util.py +6 -7
- streamlit/connections/sql_connection.py +1 -1
- streamlit/dataframe_util.py +50 -51
- streamlit/delta_generator.py +4 -1
- streamlit/deprecation_util.py +5 -5
- streamlit/elements/arrow.py +1 -1
- streamlit/elements/deck_gl_json_chart.py +1 -4
- streamlit/elements/doc_string.py +5 -10
- streamlit/elements/exception.py +5 -7
- streamlit/elements/layouts.py +4 -3
- streamlit/elements/lib/built_in_chart_utils.py +22 -22
- streamlit/elements/lib/pandas_styler_utils.py +6 -8
- streamlit/elements/lib/policies.py +1 -1
- streamlit/elements/map.py +2 -8
- streamlit/elements/markdown.py +1 -4
- streamlit/elements/media.py +50 -2
- streamlit/elements/metric.py +9 -10
- streamlit/elements/spinner.py +1 -1
- streamlit/elements/vega_charts.py +1 -1
- streamlit/elements/widgets/audio_input.py +1 -4
- streamlit/elements/widgets/camera_input.py +1 -4
- streamlit/elements/widgets/chat.py +52 -5
- streamlit/elements/widgets/data_editor.py +1 -1
- streamlit/elements/widgets/slider.py +4 -5
- streamlit/elements/widgets/time_widgets.py +1 -4
- streamlit/elements/write.py +2 -2
- streamlit/env_util.py +2 -7
- streamlit/error_util.py +15 -8
- streamlit/errors.py +11 -8
- 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/logger.py +4 -5
- streamlit/proto/Audio_pb2.py +4 -3
- streamlit/proto/Audio_pb2.pyi +8 -1
- streamlit/proto/Block_pb2.py +5 -5
- streamlit/proto/Block_pb2.pyi +7 -1
- streamlit/proto/ChatInput_pb2.py +8 -7
- streamlit/proto/ChatInput_pb2.pyi +10 -1
- streamlit/proto/Video_pb2.py +8 -7
- streamlit/proto/Video_pb2.pyi +8 -1
- streamlit/runtime/app_session.py +5 -5
- streamlit/runtime/caching/cache_data_api.py +2 -2
- streamlit/runtime/caching/cache_resource_api.py +1 -1
- streamlit/runtime/caching/cache_utils.py +3 -3
- streamlit/runtime/caching/hashing.py +10 -10
- streamlit/runtime/credentials.py +9 -8
- streamlit/runtime/forward_msg_queue.py +1 -1
- streamlit/runtime/memory_media_file_storage.py +5 -4
- streamlit/runtime/memory_uploaded_file_manager.py +1 -1
- streamlit/runtime/metrics_util.py +2 -2
- 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 +10 -3
- 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 +3 -5
- streamlit/runtime/state/session_state.py +15 -15
- streamlit/runtime/stats.py +1 -1
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.B5LmzpSn.js → ErrorOutline.esm.CxkgXqSh.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.BgWveG3s.js → FileDownload.esm.DVrjmwoh.js} +1 -1
- streamlit/static/static/js/{FileHelper.DepIpP48.js → FileHelper.CMA9s0t3.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.C_BjP_35.js → FormClearHelper.Ca3GFjxv.js} +1 -1
- streamlit/static/static/js/{Hooks.BpH4YuRQ.js → Hooks.BpCPXt5n.js} +1 -1
- streamlit/static/static/js/{InputInstructions.CjdwGigq.js → InputInstructions.BO_BnHv5.js} +1 -1
- streamlit/static/static/js/{ProgressBar.D1hXcW3N.js → ProgressBar.Ctk1m4EX.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.A1T2s6z-.js → RenderInPortalIfExists.kuKoxpXt.js} +1 -1
- streamlit/static/static/js/{Toolbar.y7vr7z0G.js → Toolbar.Cde1fEcQ.js} +1 -1
- streamlit/static/static/js/{base-input.BKhd-BLG.js → base-input.BwCmIYba.js} +1 -1
- streamlit/static/static/js/{checkbox.DC-GFdrh.js → checkbox.CwPOyuag.js} +1 -1
- streamlit/static/static/js/{createSuper.D5WUtJEy.js → createSuper.BMtevhyt.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.BPJ38mWp.js → data-grid-overlay-editor.gtfE9z1L.js} +1 -1
- streamlit/static/static/js/{downloader.C6a4LRBw.js → downloader.-58ZXBvx.js} +1 -1
- streamlit/static/static/js/{es6.DgMlYq8q.js → es6.6JpsZqpF.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.BpQxex73.js → iframeResizer.contentWindow.Dvm_jxul.js} +1 -1
- streamlit/static/static/js/{index.CiO2JPl_.js → index.9Bu4pGgs.js} +1 -1
- streamlit/static/static/js/{index.4Gtr9egA.js → index.B1T1N6vQ.js} +1 -1
- streamlit/static/static/js/{index.20fI9wQF.js → index.B9LBeTzL.js} +1 -1
- streamlit/static/static/js/{index.VPO2zcSN.js → index.BXdNB_A0.js} +1 -1
- streamlit/static/static/js/{index.sKXwUANU.js → index.Bd91GXu8.js} +1 -1
- streamlit/static/static/js/{index.DT0CWGt3.js → index.BdEKCy-o.js} +1 -1
- streamlit/static/static/js/{index.D3tgBU6x.js → index.BhODUTaJ.js} +1 -1
- streamlit/static/static/js/{index.BcbB70bz.js → index.BjtSRm-c.js} +1 -1
- streamlit/static/static/js/{index.DPiBGVm8.js → index.BnK8pWHN.js} +1 -1
- streamlit/static/static/js/{index.49Q6A5_9.js → index.C5xsotRs.js} +1 -1
- streamlit/static/static/js/{index.xIQLhQKv.js → index.CD3lJu6g.js} +1 -1
- streamlit/static/static/js/{index.BydIp_VR.js → index.CGJjlswG.js} +1 -1
- streamlit/static/static/js/{index.Bj81ZRkx.js → index.CIZd1q4K.js} +1 -1
- streamlit/static/static/js/{index.5k30-U6O.js → index.CZy9JHE4.js} +2 -2
- streamlit/static/static/js/{index.D5PANKHd.js → index.Ce-7kIl6.js} +1 -1
- streamlit/static/static/js/{index.Bo-z1JM2.js → index.CiiU1-bS.js} +1 -1
- streamlit/static/static/js/{index.Cqla7uBZ.js → index.ClE8XHxl.js} +1 -1
- streamlit/static/static/js/{index.CY8tg9lY.js → index.CvKH37SN.js} +1 -1
- streamlit/static/static/js/{index.CkBnHCIQ.js → index.D0G-y_z6.js} +1 -1
- streamlit/static/static/js/{index.B3UoUwtN.js → index.D1ccH_2Z.js} +1 -1
- streamlit/static/static/js/{index.DB42JCH0.js → index.D3ES4sSL.js} +1 -1
- streamlit/static/static/js/{index.BLpDfH1w.js → index.DJ0X7aeY.js} +1 -1
- streamlit/static/static/js/{index.BRN41-Jy.js → index.DNNQBTM6.js} +1 -1
- streamlit/static/static/js/{index.br6zwNIk.js → index.DQJE0i9s.js} +62 -62
- streamlit/static/static/js/{index.DSPS70gp.js → index.DR9ekgzX.js} +1 -1
- streamlit/static/static/js/{index.BbhQIRth.js → index.DUizq_aW.js} +1 -1
- streamlit/static/static/js/{index.ryD8hMpi.js → index.DVE5BhiT.js} +1 -1
- streamlit/static/static/js/{index.C2GjbQtf.js → index.DW60zbv4.js} +1 -1
- streamlit/static/static/js/{index.BhGEwO_d.js → index.DenamHJl.js} +1 -1
- streamlit/static/static/js/{index._oOkpIXS.js → index.DgnhzFgr.js} +1 -1
- streamlit/static/static/js/{index.CHnID3dI.js → index.Dk_aZplH.js} +1 -1
- streamlit/static/static/js/index.Dqcp7EZB.js +779 -0
- streamlit/static/static/js/{index.DAO4Lj-D.js → index.NfOJ2GJ6.js} +1 -1
- streamlit/static/static/js/{index.CcvbHTJu.js → index.WVgPkrrw.js} +1 -1
- streamlit/static/static/js/{index.Du1Pbz0y.js → index.bkU6rhIM.js} +1 -1
- streamlit/static/static/js/{index.Cfi3u2-T.js → index.hQ5adhxG.js} +1 -1
- streamlit/static/static/js/{index.B8ca7fYO.js → index.lYSTjxV_.js} +1 -1
- streamlit/static/static/js/{input.CNjMviuo.js → input.JEUWF6Z-.js} +1 -1
- streamlit/static/static/js/{memory.f8X97LPt.js → memory.BToPJrCN.js} +1 -1
- streamlit/static/static/js/{mergeWith.DU9BO8BA.js → mergeWith.DGon2YId.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.xJPBNdGQ.js → number-overlay-editor.kqkFTYSn.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.BjPX9m9m.js → possibleConstructorReturn.twGQoCQl.js} +1 -1
- streamlit/static/static/js/{sandbox.B23JuuVd.js → sandbox.o85HOKwq.js} +1 -1
- streamlit/static/static/js/{textarea.DodnI6GX.js → textarea.CdOYpTta.js} +1 -1
- streamlit/static/static/js/{timepicker.ClHKNfP9.js → timepicker.Cy1BKBo3.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CK6YGgcW.js → toConsumableArray.BVXfsvDc.js} +1 -1
- streamlit/static/static/js/{uniqueId.BAAVLIKj.js → uniqueId.Dz7-nY8K.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.B1oropKY.js → useBasicWidgetState.CeKdNkz-.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.CHQJz2sf.js → useOnInputChange.CM8BtP-c.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.DZ1W8JUx.js → withFullScreenWrapper.DuyW554J.js} +1 -1
- streamlit/string_util.py +1 -4
- streamlit/temporary_directory.py +2 -2
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +10 -9
- streamlit/testing/v1/local_script_runner.py +1 -4
- streamlit/type_util.py +2 -5
- streamlit/watcher/folder_black_list.py +1 -1
- streamlit/watcher/local_sources_watcher.py +5 -3
- streamlit/watcher/path_watcher.py +3 -6
- streamlit/watcher/polling_path_watcher.py +8 -7
- 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.1.dev20250511.dist-info → streamlit_nightly-1.45.2.dev20250513.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.45.1.dev20250511.dist-info → streamlit_nightly-1.45.2.dev20250513.dist-info}/RECORD +164 -164
- streamlit/static/static/js/index.BgEbLy94.js +0 -779
- {streamlit_nightly-1.45.1.dev20250511.data → streamlit_nightly-1.45.2.dev20250513.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.45.1.dev20250511.dist-info → streamlit_nightly-1.45.2.dev20250513.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.45.1.dev20250511.dist-info → streamlit_nightly-1.45.2.dev20250513.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.45.1.dev20250511.dist-info → streamlit_nightly-1.45.2.dev20250513.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,7 @@ from __future__ import annotations
|
|
18
18
|
|
19
19
|
import time
|
20
20
|
from concurrent.futures import ThreadPoolExecutor
|
21
|
+
from pathlib import Path
|
21
22
|
from typing import Callable, Final
|
22
23
|
|
23
24
|
from streamlit.logger import get_logger
|
@@ -59,7 +60,7 @@ class PollingPathWatcher:
|
|
59
60
|
retains references to all active instances.)
|
60
61
|
"""
|
61
62
|
# TODO(vdonato): Modernize this by switching to pathlib.
|
62
|
-
self._path = path
|
63
|
+
self._path = Path(path) # Changed to pathlib.Path
|
63
64
|
self._on_changed = on_changed
|
64
65
|
|
65
66
|
self._glob_pattern = glob_pattern
|
@@ -68,10 +69,10 @@ class PollingPathWatcher:
|
|
68
69
|
self._active = True
|
69
70
|
|
70
71
|
self._modification_time = util.path_modification_time(
|
71
|
-
self._path, self._allow_nonexistent
|
72
|
+
str(self._path), self._allow_nonexistent
|
72
73
|
)
|
73
74
|
self._md5 = util.calc_md5_with_blocking_retries(
|
74
|
-
self._path,
|
75
|
+
str(self._path),
|
75
76
|
glob_pattern=self._glob_pattern,
|
76
77
|
allow_nonexistent=self._allow_nonexistent,
|
77
78
|
)
|
@@ -81,7 +82,7 @@ class PollingPathWatcher:
|
|
81
82
|
return repr_(self)
|
82
83
|
|
83
84
|
def _schedule(self) -> None:
|
84
|
-
def task():
|
85
|
+
def task() -> None:
|
85
86
|
time.sleep(_POLLING_PERIOD_SECS)
|
86
87
|
self._check_if_path_changed()
|
87
88
|
|
@@ -93,7 +94,7 @@ class PollingPathWatcher:
|
|
93
94
|
return
|
94
95
|
|
95
96
|
modification_time = util.path_modification_time(
|
96
|
-
self._path, self._allow_nonexistent
|
97
|
+
str(self._path), self._allow_nonexistent
|
97
98
|
)
|
98
99
|
# We add modification_time != 0.0 check since on some file systems (s3fs/fuse)
|
99
100
|
# modification_time is always 0.0 because of file system limitations.
|
@@ -104,7 +105,7 @@ class PollingPathWatcher:
|
|
104
105
|
self._modification_time = modification_time
|
105
106
|
|
106
107
|
md5 = util.calc_md5_with_blocking_retries(
|
107
|
-
self._path,
|
108
|
+
str(self._path),
|
108
109
|
glob_pattern=self._glob_pattern,
|
109
110
|
allow_nonexistent=self._allow_nonexistent,
|
110
111
|
)
|
@@ -115,7 +116,7 @@ class PollingPathWatcher:
|
|
115
116
|
self._md5 = md5
|
116
117
|
|
117
118
|
_LOGGER.debug("Change detected: %s", self._path)
|
118
|
-
self._on_changed(self._path)
|
119
|
+
self._on_changed(str(self._path))
|
119
120
|
|
120
121
|
self._schedule()
|
121
122
|
|
streamlit/watcher/util.py
CHANGED
@@ -23,11 +23,14 @@ from __future__ import annotations
|
|
23
23
|
import os
|
24
24
|
import time
|
25
25
|
from pathlib import Path
|
26
|
-
from typing import Callable, TypeVar
|
26
|
+
from typing import TYPE_CHECKING, Callable, TypeVar
|
27
27
|
|
28
28
|
from streamlit.errors import Error
|
29
29
|
from streamlit.util import calc_md5
|
30
30
|
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
from collections.abc import Generator
|
33
|
+
|
31
34
|
# How many times to try to grab the MD5 hash.
|
32
35
|
_MAX_RETRIES = 5
|
33
36
|
|
@@ -173,14 +176,12 @@ def _do_with_retries(
|
|
173
176
|
except exceptions: # noqa: PERF203
|
174
177
|
if i >= _MAX_RETRIES - 1:
|
175
178
|
raise
|
176
|
-
|
177
|
-
# Continue with loop to either retry or raise MaxRetriesError.
|
178
|
-
pass
|
179
|
+
# Continue with loop to either retry or raise MaxRetriesError.
|
179
180
|
|
180
181
|
raise MaxRetriesError(f"Unable to access file or folder: {path}")
|
181
182
|
|
182
183
|
|
183
|
-
def _retry_dance():
|
184
|
+
def _retry_dance() -> Generator[int, None, None]:
|
184
185
|
"""Helper for writing a retry loop.
|
185
186
|
|
186
187
|
This is useful to make sure all our retry loops work the same way. For example,
|
streamlit/web/bootstrap.py
CHANGED
@@ -39,7 +39,7 @@ MAX_APP_STATIC_FOLDER_SIZE = 1 * 1024 * 1024 * 1024 # 1 GB
|
|
39
39
|
def _set_up_signal_handler(server: Server) -> None:
|
40
40
|
_LOGGER.debug("Setting up signal handler")
|
41
41
|
|
42
|
-
def signal_handler(signal_number, stack_frame): # noqa: ARG001
|
42
|
+
def signal_handler(signal_number: int, stack_frame: Any) -> None: # noqa: ARG001
|
43
43
|
# The server will shut down its threads and exit its loop.
|
44
44
|
server.stop()
|
45
45
|
|
@@ -115,7 +115,7 @@ def _on_server_start(server: Server) -> None:
|
|
115
115
|
except Exception:
|
116
116
|
_LOGGER.exception("Failed to load secrets.toml file")
|
117
117
|
|
118
|
-
def maybe_open_browser():
|
118
|
+
def maybe_open_browser() -> None:
|
119
119
|
if config.get_option("server.headless"):
|
120
120
|
# Don't open browser when in headless mode.
|
121
121
|
return
|
@@ -288,7 +288,7 @@ def load_config_options(flag_options: dict[str, Any]) -> None:
|
|
288
288
|
|
289
289
|
|
290
290
|
def _install_config_watchers(flag_options: dict[str, Any]) -> None:
|
291
|
-
def on_config_changed(_path):
|
291
|
+
def on_config_changed(_path: str) -> None:
|
292
292
|
load_config_options(flag_options)
|
293
293
|
|
294
294
|
for filename in CONFIG_FILENAMES:
|
@@ -340,7 +340,7 @@ def run(
|
|
340
340
|
# asyncio.run(run_server()) # noqa: ERA001
|
341
341
|
|
342
342
|
# Define a main function to handle the event loop logic
|
343
|
-
async def main():
|
343
|
+
async def main() -> None:
|
344
344
|
await run_server()
|
345
345
|
|
346
346
|
try:
|
streamlit/web/cli.py
CHANGED
@@ -127,7 +127,7 @@ def _download_remote(main_script_path: str, url_path: str) -> None:
|
|
127
127
|
@click.group(context_settings={"auto_envvar_prefix": "STREAMLIT"})
|
128
128
|
@click.option("--log_level", show_default=True, type=click.Choice(LOG_LEVELS))
|
129
129
|
@click.version_option(prog_name="Streamlit")
|
130
|
-
def main(log_level="info"):
|
130
|
+
def main(log_level: str = "info") -> None:
|
131
131
|
"""Try out a demo with:
|
132
132
|
|
133
133
|
$ streamlit hello
|
@@ -148,7 +148,7 @@ def main(log_level="info"):
|
|
148
148
|
|
149
149
|
|
150
150
|
@main.command("help")
|
151
|
-
def help(): # noqa: A001
|
151
|
+
def help() -> None: # noqa: A001
|
152
152
|
"""Print this help message."""
|
153
153
|
# We use _get_command_line_as_string to run some error checks but don't do
|
154
154
|
# anything with its return value.
|
@@ -162,7 +162,7 @@ def help(): # noqa: A001
|
|
162
162
|
|
163
163
|
|
164
164
|
@main.command("version")
|
165
|
-
def main_version():
|
165
|
+
def main_version() -> None:
|
166
166
|
"""Print Streamlit's version number."""
|
167
167
|
# Pretend user typed 'streamlit --version' instead of 'streamlit version'
|
168
168
|
import sys
|
@@ -177,7 +177,7 @@ def main_version():
|
|
177
177
|
|
178
178
|
|
179
179
|
@main.command("docs")
|
180
|
-
def main_docs():
|
180
|
+
def main_docs() -> None:
|
181
181
|
"""Show help in browser."""
|
182
182
|
click.echo("Showing help page in browser...")
|
183
183
|
from streamlit import cli_util
|
@@ -187,7 +187,7 @@ def main_docs():
|
|
187
187
|
|
188
188
|
@main.command("hello")
|
189
189
|
@configurator_options
|
190
|
-
def main_hello(**kwargs):
|
190
|
+
def main_hello(**kwargs: Any) -> None:
|
191
191
|
"""Runs the Hello World script."""
|
192
192
|
from streamlit.hello import streamlit_app
|
193
193
|
|
@@ -282,13 +282,13 @@ def _main_run(
|
|
282
282
|
|
283
283
|
|
284
284
|
@main.group("cache")
|
285
|
-
def cache():
|
285
|
+
def cache() -> None:
|
286
286
|
"""Manage the Streamlit cache."""
|
287
287
|
pass
|
288
288
|
|
289
289
|
|
290
290
|
@cache.command("clear")
|
291
|
-
def cache_clear():
|
291
|
+
def cache_clear() -> None:
|
292
292
|
"""Clear st.cache_data and st.cache_resource caches."""
|
293
293
|
|
294
294
|
# in this `streamlit cache clear` cli command we cannot use the
|
@@ -305,14 +305,14 @@ def cache_clear():
|
|
305
305
|
|
306
306
|
|
307
307
|
@main.group("config")
|
308
|
-
def config():
|
308
|
+
def config() -> None:
|
309
309
|
"""Manage Streamlit's config settings."""
|
310
310
|
pass
|
311
311
|
|
312
312
|
|
313
313
|
@config.command("show")
|
314
314
|
@configurator_options
|
315
|
-
def config_show(**kwargs):
|
315
|
+
def config_show(**kwargs: Any) -> None:
|
316
316
|
"""Show all of Streamlit's config settings."""
|
317
317
|
|
318
318
|
bootstrap.load_config_options(flag_options=kwargs)
|
@@ -325,14 +325,14 @@ def config_show(**kwargs):
|
|
325
325
|
|
326
326
|
@main.group("activate", invoke_without_command=True)
|
327
327
|
@click.pass_context
|
328
|
-
def activate(ctx):
|
328
|
+
def activate(ctx: click.Context) -> None:
|
329
329
|
"""Activate Streamlit by entering your email."""
|
330
330
|
if not ctx.invoked_subcommand:
|
331
331
|
Credentials.get_current().activate()
|
332
332
|
|
333
333
|
|
334
334
|
@activate.command("reset")
|
335
|
-
def activate_reset():
|
335
|
+
def activate_reset() -> None:
|
336
336
|
"""Reset Activation Credentials."""
|
337
337
|
Credentials.get_current().reset()
|
338
338
|
|
@@ -341,7 +341,7 @@ def activate_reset():
|
|
341
341
|
|
342
342
|
|
343
343
|
@main.group("test", hidden=True)
|
344
|
-
def test():
|
344
|
+
def test() -> None:
|
345
345
|
"""Internal-only commands used for testing.
|
346
346
|
|
347
347
|
These commands are not included in the output of `streamlit help`.
|
@@ -350,7 +350,7 @@ def test():
|
|
350
350
|
|
351
351
|
|
352
352
|
@test.command("prog_name")
|
353
|
-
def test_prog_name():
|
353
|
+
def test_prog_name() -> None:
|
354
354
|
"""Assert that the program name is set to `streamlit test`.
|
355
355
|
|
356
356
|
This is used by our cli-smoke-tests to verify that the program name is set
|
@@ -82,7 +82,7 @@ class AppStaticFileHandler(tornado.web.StaticFileHandler):
|
|
82
82
|
|
83
83
|
return ret_val
|
84
84
|
|
85
|
-
def set_default_headers(self):
|
85
|
+
def set_default_headers(self) -> None:
|
86
86
|
# CORS protection is disabled because we need access to this endpoint
|
87
87
|
# from the inner iframe.
|
88
88
|
self.set_header("Access-Control-Allow-Origin", "*")
|
@@ -29,7 +29,12 @@ if TYPE_CHECKING:
|
|
29
29
|
|
30
30
|
|
31
31
|
class TornadoIntegration(FrameworkIntegration): # type: ignore[misc]
|
32
|
-
def update_token(
|
32
|
+
def update_token(
|
33
|
+
self,
|
34
|
+
token: dict[str, Any],
|
35
|
+
refresh_token: dict[str, Any] | None = None,
|
36
|
+
access_token: dict[str, Any] | None = None,
|
37
|
+
) -> None:
|
33
38
|
"""We do not support access token refresh, since we obtain and operate only on
|
34
39
|
identity tokens. We override this method explicitly to implement all abstract
|
35
40
|
methods of base class.
|
@@ -102,7 +102,7 @@ class AuthHandlerMixin(tornado.web.RequestHandler):
|
|
102
102
|
|
103
103
|
|
104
104
|
class AuthLoginHandler(AuthHandlerMixin, tornado.web.RequestHandler):
|
105
|
-
async def get(self):
|
105
|
+
async def get(self) -> None:
|
106
106
|
"""Redirect to the OAuth provider login page."""
|
107
107
|
provider = self._parse_provider_token()
|
108
108
|
if provider is None:
|
@@ -128,13 +128,13 @@ class AuthLoginHandler(AuthHandlerMixin, tornado.web.RequestHandler):
|
|
128
128
|
|
129
129
|
|
130
130
|
class AuthLogoutHandler(AuthHandlerMixin, tornado.web.RequestHandler):
|
131
|
-
def get(self):
|
131
|
+
def get(self) -> None:
|
132
132
|
self.clear_auth_cookie()
|
133
133
|
self.redirect_to_base()
|
134
134
|
|
135
135
|
|
136
136
|
class AuthCallbackHandler(AuthHandlerMixin, tornado.web.RequestHandler):
|
137
|
-
async def get(self):
|
137
|
+
async def get(self) -> None:
|
138
138
|
provider = self._get_provider_by_state()
|
139
139
|
origin = self._get_origin_from_secrets()
|
140
140
|
if origin is None:
|
@@ -14,9 +14,10 @@
|
|
14
14
|
|
15
15
|
# ruff: noqa: ANN201
|
16
16
|
|
17
|
-
from
|
17
|
+
from __future__ import annotations
|
18
|
+
|
19
|
+
from typing import TYPE_CHECKING, Any, Callable, cast
|
18
20
|
|
19
|
-
import tornado.web
|
20
21
|
from authlib.integrations.base_client import ( # type: ignore[import-untyped]
|
21
22
|
BaseApp,
|
22
23
|
BaseOAuth,
|
@@ -30,6 +31,11 @@ from authlib.integrations.requests_client import ( # type: ignore[import-untype
|
|
30
31
|
|
31
32
|
from streamlit.web.server.authlib_tornado_integration import TornadoIntegration
|
32
33
|
|
34
|
+
if TYPE_CHECKING:
|
35
|
+
import tornado.web
|
36
|
+
|
37
|
+
from streamlit.auth_util import AuthCache
|
38
|
+
|
33
39
|
|
34
40
|
class TornadoOAuth2App(OAuth2Mixin, OpenIDMixin, BaseApp): # type: ignore[misc]
|
35
41
|
client_cls = OAuth2Session
|
@@ -108,7 +114,13 @@ class TornadoOAuth(BaseOAuth): # type: ignore[misc]
|
|
108
114
|
oauth2_client_cls = TornadoOAuth2App
|
109
115
|
framework_integration_cls = TornadoIntegration
|
110
116
|
|
111
|
-
def __init__(
|
117
|
+
def __init__(
|
118
|
+
self,
|
119
|
+
config: dict[str, Any] | None = None,
|
120
|
+
cache: AuthCache | None = None,
|
121
|
+
fetch_token: Callable[[dict[str, Any]], dict[str, Any]] | None = None,
|
122
|
+
update_token: Callable[[dict[str, Any]], dict[str, Any]] | None = None,
|
123
|
+
):
|
112
124
|
super().__init__(
|
113
125
|
cache=cache, fetch_token=fetch_token, update_token=update_token
|
114
126
|
)
|
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, Any
|
18
|
+
from typing import TYPE_CHECKING, Any, Callable
|
19
19
|
|
20
20
|
import tornado.web
|
21
21
|
|
@@ -26,7 +26,7 @@ from streamlit.web.server.server_util import (
|
|
26
26
|
)
|
27
27
|
|
28
28
|
if TYPE_CHECKING:
|
29
|
-
from collections.abc import Sequence
|
29
|
+
from collections.abc import Awaitable, Sequence
|
30
30
|
|
31
31
|
|
32
32
|
def allow_cross_origin_requests() -> bool:
|
@@ -96,25 +96,25 @@ class StaticFileHandler(tornado.web.StaticFileHandler):
|
|
96
96
|
|
97
97
|
class AddSlashHandler(tornado.web.RequestHandler):
|
98
98
|
@tornado.web.addslash
|
99
|
-
def get(self):
|
99
|
+
def get(self) -> None:
|
100
100
|
pass
|
101
101
|
|
102
102
|
|
103
103
|
class RemoveSlashHandler(tornado.web.RequestHandler):
|
104
104
|
@tornado.web.removeslash
|
105
|
-
def get(self):
|
105
|
+
def get(self) -> None:
|
106
106
|
pass
|
107
107
|
|
108
108
|
|
109
109
|
class _SpecialRequestHandler(tornado.web.RequestHandler):
|
110
110
|
"""Superclass for "special" endpoints, like /healthz."""
|
111
111
|
|
112
|
-
def set_default_headers(self):
|
112
|
+
def set_default_headers(self) -> None:
|
113
113
|
self.set_header("Cache-Control", "no-cache")
|
114
114
|
if allow_cross_origin_requests():
|
115
115
|
self.set_header("Access-Control-Allow-Origin", "*")
|
116
116
|
|
117
|
-
def options(self):
|
117
|
+
def options(self) -> None:
|
118
118
|
"""/OPTIONS handler for preflight CORS checks.
|
119
119
|
|
120
120
|
When a browser is making a CORS request, it may sometimes first
|
@@ -136,7 +136,7 @@ class _SpecialRequestHandler(tornado.web.RequestHandler):
|
|
136
136
|
|
137
137
|
|
138
138
|
class HealthHandler(_SpecialRequestHandler):
|
139
|
-
def initialize(self, callback):
|
139
|
+
def initialize(self, callback: Callable[[], Awaitable[tuple[bool, str]]]) -> None:
|
140
140
|
"""Initialize the handler.
|
141
141
|
|
142
142
|
Parameters
|
@@ -147,15 +147,15 @@ class HealthHandler(_SpecialRequestHandler):
|
|
147
147
|
"""
|
148
148
|
self._callback = callback
|
149
149
|
|
150
|
-
async def get(self):
|
150
|
+
async def get(self) -> None:
|
151
151
|
await self.handle_request()
|
152
152
|
|
153
153
|
# Some monitoring services only support the HTTP HEAD method for requests to
|
154
154
|
# healthcheck endpoints, so we support HEAD as well to play nicely with them.
|
155
|
-
async def head(self):
|
155
|
+
async def head(self) -> None:
|
156
156
|
await self.handle_request()
|
157
157
|
|
158
|
-
async def handle_request(self):
|
158
|
+
async def handle_request(self) -> None:
|
159
159
|
if self.request.uri and "_stcore/" not in self.request.uri:
|
160
160
|
new_path = (
|
161
161
|
"/_stcore/script-health-check"
|
@@ -212,7 +212,7 @@ _DEFAULT_ALLOWED_MESSAGE_ORIGINS = [
|
|
212
212
|
|
213
213
|
|
214
214
|
class HostConfigHandler(_SpecialRequestHandler):
|
215
|
-
def initialize(self):
|
215
|
+
def initialize(self) -> None:
|
216
216
|
# Make a copy of the allowedOrigins list, since we might modify it later:
|
217
217
|
self._allowed_origins = _DEFAULT_ALLOWED_MESSAGE_ORIGINS.copy()
|
218
218
|
|
@@ -30,11 +30,11 @@ class StatsRequestHandler(tornado.web.RequestHandler):
|
|
30
30
|
def initialize(self, stats_manager: StatsManager) -> None:
|
31
31
|
self._manager = stats_manager
|
32
32
|
|
33
|
-
def set_default_headers(self):
|
33
|
+
def set_default_headers(self) -> None:
|
34
34
|
if allow_cross_origin_requests():
|
35
35
|
self.set_header("Access-Control-Allow-Origin", "*")
|
36
36
|
|
37
|
-
def options(self):
|
37
|
+
def options(self) -> None:
|
38
38
|
"""/OPTIONS handler for preflight CORS checks."""
|
39
39
|
self.set_status(204)
|
40
40
|
self.finish()
|