streamlit-nightly 1.45.1.dev20250508__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 +9 -9
- streamlit/config_option.py +2 -2
- 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/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/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/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.C9UoaGEN.js → ErrorOutline.esm.C-0hf1-k.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.DoToR9q0.js → FileDownload.esm.B-fFGI-X.js} +1 -1
- streamlit/static/static/js/{FileHelper.Bt4VJ--Q.js → FileHelper.ACYo0OZo.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.D5PbW8FI.js → FormClearHelper.CVNTT-bJ.js} +1 -1
- streamlit/static/static/js/{Hooks.DgkQ2Xp9.js → Hooks.C3thlpd2.js} +1 -1
- streamlit/static/static/js/{InputInstructions.DLnLhwHI.js → InputInstructions.CwAxousX.js} +1 -1
- streamlit/static/static/js/{ProgressBar.BtSgh_K-.js → ProgressBar.xh599Rum.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.CjdyBvQX.js → RenderInPortalIfExists.CQLIsNPE.js} +1 -1
- streamlit/static/static/js/{Toolbar.CAYIzVZk.js → Toolbar.LKdyvP0u.js} +1 -1
- streamlit/static/static/js/{base-input.CD4xW4_9.js → base-input.D8OdS4WW.js} +1 -1
- streamlit/static/static/js/{checkbox.Ba4jj5dR.js → checkbox.DSdYKlOI.js} +1 -1
- streamlit/static/static/js/{createSuper.BBGT9Ijd.js → createSuper.B2pyCfWw.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.CYuk1Aj7.js → data-grid-overlay-editor.DhO2r0ne.js} +1 -1
- streamlit/static/static/js/{downloader.DM9KEOCw.js → downloader.C24skoDM.js} +1 -1
- streamlit/static/static/js/{es6.FqM62T4b.js → es6.DHkvCKPh.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.s2B09mw2.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.B9FiDQ3U.js → index.B5EFweZ4.js} +1 -1
- streamlit/static/static/js/{index.DkGCnTMe.js → index.BAafqHfB.js} +1 -1
- streamlit/static/static/js/{index.BMXmhMlZ.js → index.BHTbGZPQ.js} +1 -1
- streamlit/static/static/js/{index.CpDFZQ4Y.js → index.BNXtQAj4.js} +1 -1
- streamlit/static/static/js/index.BRhKaVdO.js +1 -0
- streamlit/static/static/js/index.BSOiJVQd.js +2 -0
- streamlit/static/static/js/{index.BoMRR3tN.js → index.BVgTQbOJ.js} +1 -1
- streamlit/static/static/js/{index.Cwtbhfaf.js → index.BflIniLm.js} +1 -1
- streamlit/static/static/js/{index.DMrO9G6A.js → index.BjeNtZIz.js} +1 -1
- streamlit/static/static/js/{index.C2qCX1Lh.js → index.By-NmdnB.js} +151 -151
- streamlit/static/static/js/{index.b9kK7Vzl.js → index.CIoOEhZ2.js} +1 -1
- streamlit/static/static/js/{index.CEKMSkSh.js → index.CRCdonis.js} +36 -36
- streamlit/static/static/js/{index.T5LKPcND.js → index.CRxaBCJ7.js} +1 -1
- streamlit/static/static/js/{index.CeiCniCg.js → index.CU-pbYVN.js} +1 -1
- streamlit/static/static/js/{index.BVA8TXNT.js → index.CUsk52t2.js} +1 -1
- streamlit/static/static/js/{index.CH9XN_-G.js → index.CVO14oQG.js} +2 -2
- streamlit/static/static/js/index.CXFuA6J-.js +1 -0
- streamlit/static/static/js/{index.DQi04JYE.js → index.C_dd5q7u.js} +1 -1
- streamlit/static/static/js/{index.DTi8Lw0k.js → index.CjWUnKIN.js} +1 -1
- streamlit/static/static/js/{index.DG8IxVeM.js → index.CkTL9bAR.js} +2 -2
- streamlit/static/static/js/{index.D9FvPPrI.js → index.CsbhsAPy.js} +1 -1
- streamlit/static/static/js/{index.R0peMEpV.js → index.CtCnBUtk.js} +1 -1
- streamlit/static/static/js/{index.CP2PmB93.js → index.CwuKadAX.js} +1 -1
- streamlit/static/static/js/{index.BFqpCk2P.js → index.D0R7Xh4Z.js} +1 -1
- streamlit/static/static/js/{index.DSDkXosb.js → index.D2D75EDw.js} +2 -2
- streamlit/static/static/js/{index.BsjuUMyW.js → index.D4eMiZ1F.js} +1 -1
- streamlit/static/static/js/{index.BDTYk2an.js → index.D7SCC3z9.js} +1 -1
- streamlit/static/static/js/{index.JTeVe9GQ.js → index.DZiilxEt.js} +1 -1
- streamlit/static/static/js/{index.BY7-qCf5.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.CqaahZPf.js → index.gFjPlsMT.js} +1 -1
- streamlit/static/static/js/{index.0pkoyBcb.js → index.jCJYMVED.js} +1 -1
- streamlit/static/static/js/{index.DWaB7Scf.js → index.xldt56AE.js} +1 -1
- streamlit/static/static/js/{index.CyE1OdOj.js → index.yzoj_DuM.js} +1 -1
- streamlit/static/static/js/{input.DMOGBelK.js → input.BP6LX_Bg.js} +1 -1
- streamlit/static/static/js/{memory.DmCktBGW.js → memory.E9x2ZYJv.js} +1 -1
- streamlit/static/static/js/{mergeWith.DeWTsJ5h.js → mergeWith.CZP2AaVS.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.DDFelcUP.js → number-overlay-editor.D-Kl79U_.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.CYJtAqB-.js → possibleConstructorReturn.P2ILVC_6.js} +1 -1
- streamlit/static/static/js/{sandbox.CfaU9Ih9.js → sandbox.DfzJIGMV.js} +1 -1
- streamlit/static/static/js/{textarea.7hWYKDw2.js → textarea.4PjzfDWF.js} +1 -1
- streamlit/static/static/js/{timepicker.DZsgZ9oE.js → timepicker.DMQdaNzO.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.CqWB4Jry.js → toConsumableArray.BEdkbHYx.js} +1 -1
- streamlit/static/static/js/{uniqueId.DQ533D9O.js → uniqueId.CAs7ftHC.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.-99xbU_o.js → useBasicWidgetState.Cedp0V76.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.B4G2Q7Bu.js → useOnInputChange.CvRKHHKx.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.BJQZ2aNc.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/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 +2 -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.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/RECORD +181 -177
- {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/WHEEL +1 -1
- streamlit/static/static/js/index.CCD4LJ9Q.js +0 -1
- streamlit/static/static/js/index.CbLZDRQu.js +0 -1
- streamlit/static/static/js/index.D9qEk5xd.js +0 -1
- streamlit/static/static/js/index.DTXSsTgK.js +0 -1
- streamlit/static/static/js/index.DqVjOqxm.js +0 -1
- streamlit/static/static/js/index.RHbaxsqm.js +0 -1
- streamlit/static/static/js/index.hT9gkW3a.js +0 -2
- {streamlit_nightly-1.45.1.dev20250508.data → streamlit_nightly-1.45.1.dev20250509.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ import weakref
|
|
34
34
|
from enum import Enum
|
35
35
|
from re import Pattern
|
36
36
|
from types import MappingProxyType
|
37
|
-
from typing import Any, Callable, Final, Union, cast
|
37
|
+
from typing import TYPE_CHECKING, Any, Callable, Final, Union, cast
|
38
38
|
|
39
39
|
from typing_extensions import TypeAlias
|
40
40
|
|
@@ -44,6 +44,10 @@ from streamlit.runtime.caching.cache_errors import UnhashableTypeError
|
|
44
44
|
from streamlit.runtime.caching.cache_type import CacheType
|
45
45
|
from streamlit.runtime.uploaded_file_manager import UploadedFile
|
46
46
|
|
47
|
+
if TYPE_CHECKING:
|
48
|
+
import numpy.typing as npt
|
49
|
+
from PIL.Image import Image
|
50
|
+
|
47
51
|
_LOGGER: Final = logger.get_logger(__name__)
|
48
52
|
|
49
53
|
# If a dataframe has more than this many rows, we consider it large and hash a sample.
|
@@ -66,11 +70,11 @@ _CYCLE_PLACEHOLDER: Final = (
|
|
66
70
|
class UserHashError(StreamlitAPIException):
|
67
71
|
def __init__(
|
68
72
|
self,
|
69
|
-
orig_exc,
|
70
|
-
object_to_hash,
|
71
|
-
hash_func,
|
73
|
+
orig_exc: BaseException,
|
74
|
+
object_to_hash: Any,
|
75
|
+
hash_func: Callable[[Any], Any],
|
72
76
|
cache_type: CacheType | None = None,
|
73
|
-
):
|
77
|
+
) -> None:
|
74
78
|
self.alternate_name = type(orig_exc).__name__
|
75
79
|
self.hash_func = hash_func
|
76
80
|
self.cache_type = cache_type
|
@@ -80,7 +84,11 @@ class UserHashError(StreamlitAPIException):
|
|
80
84
|
super().__init__(msg)
|
81
85
|
self.with_traceback(orig_exc.__traceback__)
|
82
86
|
|
83
|
-
def _get_message_from_func(
|
87
|
+
def _get_message_from_func(
|
88
|
+
self,
|
89
|
+
orig_exc: BaseException,
|
90
|
+
cached_func: Any,
|
91
|
+
) -> str:
|
84
92
|
args = self._get_error_message_args(orig_exc, cached_func)
|
85
93
|
|
86
94
|
return (
|
@@ -145,7 +153,7 @@ If you think this is actually a Streamlit bug, please
|
|
145
153
|
|
146
154
|
def update_hash(
|
147
155
|
val: Any,
|
148
|
-
hasher,
|
156
|
+
hasher: Any,
|
149
157
|
cache_type: CacheType,
|
150
158
|
hash_source: Callable[..., Any] | None = None,
|
151
159
|
hash_funcs: HashFuncsDict | None = None,
|
@@ -182,13 +190,13 @@ class _HashStack:
|
|
182
190
|
def __repr__(self) -> str:
|
183
191
|
return util.repr_(self)
|
184
192
|
|
185
|
-
def push(self, val: Any):
|
193
|
+
def push(self, val: Any) -> None:
|
186
194
|
self._stack[id(val)] = val
|
187
195
|
|
188
|
-
def pop(self):
|
196
|
+
def pop(self) -> None:
|
189
197
|
self._stack.popitem()
|
190
198
|
|
191
|
-
def __contains__(self, val: Any):
|
199
|
+
def __contains__(self, val: Any) -> bool:
|
192
200
|
return id(val) in self._stack
|
193
201
|
|
194
202
|
def pretty_print(self) -> str:
|
@@ -247,28 +255,20 @@ def _key(obj: Any | None) -> Any:
|
|
247
255
|
if obj is None:
|
248
256
|
return None
|
249
257
|
|
250
|
-
def is_simple(obj):
|
258
|
+
def is_simple(obj: Any) -> bool:
|
251
259
|
return (
|
252
|
-
isinstance(obj, bytes)
|
253
|
-
or isinstance(obj, bytearray)
|
254
|
-
or isinstance(obj, str)
|
255
|
-
or isinstance(obj, float)
|
256
|
-
or isinstance(obj, int)
|
257
|
-
or isinstance(obj, bool)
|
258
|
-
or isinstance(obj, uuid.UUID)
|
260
|
+
isinstance(obj, (bytes, bytearray, str, float, int, bool, uuid.UUID))
|
259
261
|
or obj is None
|
260
262
|
)
|
261
263
|
|
262
264
|
if is_simple(obj):
|
263
265
|
return obj
|
264
266
|
|
265
|
-
if isinstance(obj, tuple):
|
266
|
-
|
267
|
-
return obj
|
267
|
+
if isinstance(obj, tuple) and all(map(is_simple, obj)):
|
268
|
+
return obj
|
268
269
|
|
269
|
-
if isinstance(obj, list):
|
270
|
-
|
271
|
-
return ("__l", tuple(obj))
|
270
|
+
if isinstance(obj, list) and all(map(is_simple, obj)):
|
271
|
+
return ("__l", tuple(obj))
|
272
272
|
|
273
273
|
if inspect.isbuiltin(obj) or inspect.isroutine(obj) or inspect.iscode(obj):
|
274
274
|
return id(obj)
|
@@ -279,7 +279,9 @@ def _key(obj: Any | None) -> Any:
|
|
279
279
|
class _CacheFuncHasher:
|
280
280
|
"""A hasher that can hash objects with cycles."""
|
281
281
|
|
282
|
-
def __init__(
|
282
|
+
def __init__(
|
283
|
+
self, cache_type: CacheType, hash_funcs: HashFuncsDict | None = None
|
284
|
+
) -> None:
|
283
285
|
# Can't use types as the keys in the internal _hash_funcs because
|
284
286
|
# we always remove user-written modules from memory when rerunning a
|
285
287
|
# script in order to reload it and grab the latest code changes.
|
@@ -339,7 +341,7 @@ class _CacheFuncHasher:
|
|
339
341
|
|
340
342
|
return b
|
341
343
|
|
342
|
-
def update(self, hasher, obj: Any) -> None:
|
344
|
+
def update(self, hasher: Any, obj: Any) -> None:
|
343
345
|
"""Update the provided hasher with the hash of an object."""
|
344
346
|
b = self.to_bytes(obj)
|
345
347
|
hasher.update(b)
|
@@ -360,10 +362,10 @@ class _CacheFuncHasher:
|
|
360
362
|
# deep, so we don't try to hash them at all.
|
361
363
|
return self.to_bytes(id(obj))
|
362
364
|
|
363
|
-
|
365
|
+
if isinstance(obj, bytes) or isinstance(obj, bytearray):
|
364
366
|
return obj
|
365
367
|
|
366
|
-
|
368
|
+
if type_util.get_fqn_type(obj) in self._hash_funcs:
|
367
369
|
# Escape hatch for unsupported objects
|
368
370
|
hash_func = self._hash_funcs[type_util.get_fqn_type(obj)]
|
369
371
|
try:
|
@@ -374,57 +376,59 @@ class _CacheFuncHasher:
|
|
374
376
|
) from ex
|
375
377
|
return self.to_bytes(output)
|
376
378
|
|
377
|
-
|
379
|
+
if isinstance(obj, str):
|
378
380
|
return obj.encode()
|
379
381
|
|
380
|
-
|
382
|
+
if isinstance(obj, float):
|
381
383
|
return _float_to_bytes(obj)
|
382
384
|
|
383
|
-
|
385
|
+
if isinstance(obj, int):
|
384
386
|
return _int_to_bytes(obj)
|
385
387
|
|
386
|
-
|
388
|
+
if isinstance(obj, uuid.UUID):
|
387
389
|
return obj.bytes
|
388
390
|
|
389
|
-
|
391
|
+
if isinstance(obj, datetime.datetime):
|
390
392
|
return obj.isoformat().encode()
|
391
393
|
|
392
|
-
|
394
|
+
if isinstance(obj, (list, tuple)):
|
393
395
|
for item in obj:
|
394
396
|
self.update(h, item)
|
395
397
|
return h.digest()
|
396
398
|
|
397
|
-
|
399
|
+
if isinstance(obj, dict):
|
398
400
|
for item in obj.items():
|
399
401
|
self.update(h, item)
|
400
402
|
return h.digest()
|
401
403
|
|
402
|
-
|
404
|
+
if obj is None:
|
403
405
|
return b"0"
|
404
406
|
|
405
|
-
|
407
|
+
if obj is True:
|
406
408
|
return b"1"
|
407
409
|
|
408
|
-
|
410
|
+
if obj is False:
|
409
411
|
return b"0"
|
410
412
|
|
411
|
-
|
413
|
+
if not isinstance(obj, type) and dataclasses.is_dataclass(obj):
|
412
414
|
return self.to_bytes(dataclasses.asdict(obj))
|
413
|
-
|
415
|
+
if isinstance(obj, Enum):
|
414
416
|
return str(obj).encode()
|
415
417
|
|
416
|
-
|
418
|
+
if type_util.is_type(obj, "pandas.core.series.Series"):
|
417
419
|
import pandas as pd
|
418
420
|
|
419
|
-
|
420
|
-
self.update(h,
|
421
|
-
self.update(h,
|
421
|
+
series_obj: pd.Series = cast("pd.Series", obj)
|
422
|
+
self.update(h, series_obj.size)
|
423
|
+
self.update(h, series_obj.dtype.name)
|
422
424
|
|
423
|
-
if len(
|
424
|
-
|
425
|
+
if len(series_obj) >= _PANDAS_ROWS_LARGE:
|
426
|
+
series_obj = series_obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
|
425
427
|
|
426
428
|
try:
|
427
|
-
self.update(
|
429
|
+
self.update(
|
430
|
+
h, pd.util.hash_pandas_object(series_obj).to_numpy().tobytes()
|
431
|
+
)
|
428
432
|
return h.digest()
|
429
433
|
except TypeError:
|
430
434
|
_LOGGER.warning(
|
@@ -434,22 +438,22 @@ class _CacheFuncHasher:
|
|
434
438
|
|
435
439
|
# Use pickle if pandas cannot hash the object for example if
|
436
440
|
# it contains unhashable objects.
|
437
|
-
return b"%s" % pickle.dumps(
|
441
|
+
return b"%s" % pickle.dumps(series_obj, pickle.HIGHEST_PROTOCOL)
|
438
442
|
|
439
443
|
elif type_util.is_type(obj, "pandas.core.frame.DataFrame"):
|
440
444
|
import pandas as pd
|
441
445
|
|
442
|
-
|
443
|
-
self.update(h,
|
446
|
+
df_obj: pd.DataFrame = cast("pd.DataFrame", obj)
|
447
|
+
self.update(h, df_obj.shape)
|
444
448
|
|
445
|
-
if len(
|
446
|
-
|
449
|
+
if len(df_obj) >= _PANDAS_ROWS_LARGE:
|
450
|
+
df_obj = df_obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
|
447
451
|
try:
|
448
452
|
column_hash_bytes = self.to_bytes(
|
449
|
-
pd.util.hash_pandas_object(
|
453
|
+
pd.util.hash_pandas_object(df_obj.dtypes)
|
450
454
|
)
|
451
455
|
self.update(h, column_hash_bytes)
|
452
|
-
values_hash_bytes = self.to_bytes(pd.util.hash_pandas_object(
|
456
|
+
values_hash_bytes = self.to_bytes(pd.util.hash_pandas_object(df_obj))
|
453
457
|
self.update(h, values_hash_bytes)
|
454
458
|
return h.digest()
|
455
459
|
except TypeError:
|
@@ -460,7 +464,7 @@ class _CacheFuncHasher:
|
|
460
464
|
|
461
465
|
# Use pickle if pandas cannot hash the object for example if
|
462
466
|
# it contains unhashable objects.
|
463
|
-
return b"%s" % pickle.dumps(
|
467
|
+
return b"%s" % pickle.dumps(df_obj, pickle.HIGHEST_PROTOCOL)
|
464
468
|
|
465
469
|
elif type_util.is_type(obj, "polars.series.series.Series"):
|
466
470
|
import polars as pl # type: ignore[import-not-found]
|
@@ -513,39 +517,32 @@ class _CacheFuncHasher:
|
|
513
517
|
# it contains unhashable objects.
|
514
518
|
return b"%s" % pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
|
515
519
|
elif type_util.is_type(obj, "numpy.ndarray"):
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
# - can be removed once we sunset support for Python 3.8
|
520
|
-
obj = cast("np.ndarray[Any, Any]", obj)
|
521
|
-
self.update(h, obj.shape)
|
522
|
-
self.update(h, str(obj.dtype))
|
520
|
+
np_obj: npt.NDArray[Any] = cast("npt.NDArray[Any]", obj)
|
521
|
+
self.update(h, np_obj.shape)
|
522
|
+
self.update(h, str(np_obj.dtype))
|
523
523
|
|
524
|
-
if
|
524
|
+
if np_obj.size >= _NP_SIZE_LARGE:
|
525
525
|
import numpy as np
|
526
526
|
|
527
527
|
state = np.random.RandomState(0)
|
528
|
-
|
528
|
+
np_obj = state.choice(np_obj.flat, size=_NP_SAMPLE_SIZE)
|
529
529
|
|
530
|
-
self.update(h,
|
530
|
+
self.update(h, np_obj.tobytes())
|
531
531
|
return h.digest()
|
532
532
|
elif type_util.is_type(obj, "PIL.Image.Image"):
|
533
533
|
import numpy as np
|
534
|
-
from PIL.Image import Image # noqa: TC002
|
535
534
|
|
536
|
-
|
535
|
+
pil_obj: Image = cast("Image", obj)
|
537
536
|
|
538
537
|
# we don't just hash the results of obj.tobytes() because we want to use
|
539
538
|
# the sampling logic for numpy data
|
540
|
-
np_array = np.frombuffer(
|
539
|
+
np_array = np.frombuffer(pil_obj.tobytes(), dtype="uint8")
|
541
540
|
return self.to_bytes(np_array)
|
542
541
|
|
543
542
|
elif inspect.isbuiltin(obj):
|
544
543
|
return bytes(obj.__name__.encode())
|
545
544
|
|
546
|
-
elif isinstance(obj, MappingProxyType)
|
547
|
-
obj, collections.abc.ItemsView
|
548
|
-
):
|
545
|
+
elif isinstance(obj, (MappingProxyType, collections.abc.ItemsView)):
|
549
546
|
return self.to_bytes(dict(obj))
|
550
547
|
|
551
548
|
elif type_util.is_type(obj, "builtins.getset_descriptor"):
|
@@ -561,9 +558,8 @@ class _CacheFuncHasher:
|
|
561
558
|
return h.digest()
|
562
559
|
|
563
560
|
elif hasattr(obj, "name") and (
|
564
|
-
isinstance(obj, io.IOBase)
|
565
561
|
# Handle temporary files used during testing
|
566
|
-
|
562
|
+
isinstance(obj, (io.IOBase, tempfile._TemporaryFileWrapper))
|
567
563
|
):
|
568
564
|
# Hash files as name + last modification date + offset.
|
569
565
|
# NB: we're using hasattr("name") to differentiate between
|
@@ -579,7 +575,7 @@ class _CacheFuncHasher:
|
|
579
575
|
elif isinstance(obj, Pattern):
|
580
576
|
return self.to_bytes([obj.pattern, obj.flags])
|
581
577
|
|
582
|
-
elif isinstance(obj, io.StringIO
|
578
|
+
elif isinstance(obj, (io.StringIO, io.BytesIO)):
|
583
579
|
# Hash in-memory StringIO/BytesIO by their full contents
|
584
580
|
# and seek position.
|
585
581
|
self.update(h, obj.tell())
|
@@ -40,7 +40,7 @@ def cache(
|
|
40
40
|
hash_funcs: HashFuncsDict | None = None,
|
41
41
|
max_entries: int | None = None,
|
42
42
|
ttl: float | None = None,
|
43
|
-
):
|
43
|
+
) -> F:
|
44
44
|
"""Legacy caching decorator (deprecated).
|
45
45
|
|
46
46
|
Legacy caching with ``st.cache`` has been removed from Streamlit. This is
|
@@ -57,7 +57,9 @@ class InMemoryCacheStorageWrapper(CacheStorage):
|
|
57
57
|
it from multiple threads.
|
58
58
|
"""
|
59
59
|
|
60
|
-
def __init__(
|
60
|
+
def __init__(
|
61
|
+
self, persist_storage: CacheStorage, context: CacheStorageContext
|
62
|
+
) -> None:
|
61
63
|
self.function_key = context.function_key
|
62
64
|
self.function_display_name = context.function_display_name
|
63
65
|
self._ttl_seconds = context.ttl_seconds
|
@@ -120,7 +120,7 @@ class LocalDiskCacheStorage(CacheStorage):
|
|
120
120
|
This is the default cache persistence layer for `@st.cache_data`.
|
121
121
|
"""
|
122
122
|
|
123
|
-
def __init__(self, context: CacheStorageContext):
|
123
|
+
def __init__(self, context: CacheStorageContext) -> None:
|
124
124
|
self.function_key = context.function_key
|
125
125
|
self.persist = context.persist
|
126
126
|
self._ttl_seconds = context.ttl_seconds
|
@@ -38,7 +38,7 @@ if TYPE_CHECKING:
|
|
38
38
|
# 2. Writing two new @overloads for connection_factory (one for the case where the
|
39
39
|
# only the connection name is specified and another when both name and type are).
|
40
40
|
# 3. Updating test_get_first_party_connection_helper in connection_factory_test.py.
|
41
|
-
FIRST_PARTY_CONNECTIONS = {
|
41
|
+
FIRST_PARTY_CONNECTIONS: Final[dict[str, type[BaseConnection[Any]]]] = {
|
42
42
|
"snowflake": SnowflakeConnection,
|
43
43
|
"snowpark": SnowparkConnection,
|
44
44
|
"sql": SQLConnection,
|
@@ -65,7 +65,7 @@ def _create_connection(
|
|
65
65
|
connection_class: type[ConnectionClass],
|
66
66
|
max_entries: int | None = None,
|
67
67
|
ttl: float | timedelta | None = None,
|
68
|
-
**kwargs,
|
68
|
+
**kwargs: Any,
|
69
69
|
) -> ConnectionClass:
|
70
70
|
"""Create an instance of connection_class with the given name and kwargs.
|
71
71
|
|
@@ -76,7 +76,7 @@ def _create_connection(
|
|
76
76
|
"""
|
77
77
|
|
78
78
|
def __create_connection(
|
79
|
-
name: str, connection_class: type[ConnectionClass], **kwargs
|
79
|
+
name: str, connection_class: type[ConnectionClass], **kwargs: Any
|
80
80
|
) -> ConnectionClass:
|
81
81
|
return connection_class(connection_name=name, **kwargs)
|
82
82
|
|
@@ -103,7 +103,7 @@ def _create_connection(
|
|
103
103
|
return __create_connection(name, connection_class, **kwargs)
|
104
104
|
|
105
105
|
|
106
|
-
def _get_first_party_connection(connection_class: str):
|
106
|
+
def _get_first_party_connection(connection_class: str) -> type[BaseConnection[Any]]:
|
107
107
|
if connection_class in FIRST_PARTY_CONNECTIONS:
|
108
108
|
return FIRST_PARTY_CONNECTIONS[connection_class]
|
109
109
|
|
@@ -119,7 +119,7 @@ def connection_factory(
|
|
119
119
|
max_entries: int | None = None,
|
120
120
|
ttl: float | timedelta | None = None,
|
121
121
|
autocommit: bool = False,
|
122
|
-
**kwargs,
|
122
|
+
**kwargs: Any,
|
123
123
|
) -> SQLConnection:
|
124
124
|
pass
|
125
125
|
|
@@ -131,7 +131,7 @@ def connection_factory(
|
|
131
131
|
max_entries: int | None = None,
|
132
132
|
ttl: float | timedelta | None = None,
|
133
133
|
autocommit: bool = False,
|
134
|
-
**kwargs,
|
134
|
+
**kwargs: Any,
|
135
135
|
) -> SQLConnection:
|
136
136
|
pass
|
137
137
|
|
@@ -142,7 +142,7 @@ def connection_factory(
|
|
142
142
|
max_entries: int | None = None,
|
143
143
|
ttl: float | timedelta | None = None,
|
144
144
|
autocommit: bool = False,
|
145
|
-
**kwargs,
|
145
|
+
**kwargs: Any,
|
146
146
|
) -> SnowflakeConnection:
|
147
147
|
pass
|
148
148
|
|
@@ -154,7 +154,7 @@ def connection_factory(
|
|
154
154
|
max_entries: int | None = None,
|
155
155
|
ttl: float | timedelta | None = None,
|
156
156
|
autocommit: bool = False,
|
157
|
-
**kwargs,
|
157
|
+
**kwargs: Any,
|
158
158
|
) -> SnowflakeConnection:
|
159
159
|
pass
|
160
160
|
|
@@ -164,7 +164,7 @@ def connection_factory(
|
|
164
164
|
name: Literal["snowpark"],
|
165
165
|
max_entries: int | None = None,
|
166
166
|
ttl: float | timedelta | None = None,
|
167
|
-
**kwargs,
|
167
|
+
**kwargs: Any,
|
168
168
|
) -> SnowparkConnection:
|
169
169
|
pass
|
170
170
|
|
@@ -175,7 +175,7 @@ def connection_factory(
|
|
175
175
|
type: Literal["snowpark"],
|
176
176
|
max_entries: int | None = None,
|
177
177
|
ttl: float | timedelta | None = None,
|
178
|
-
**kwargs,
|
178
|
+
**kwargs: Any,
|
179
179
|
) -> SnowparkConnection:
|
180
180
|
pass
|
181
181
|
|
@@ -186,7 +186,7 @@ def connection_factory(
|
|
186
186
|
type: type[ConnectionClass],
|
187
187
|
max_entries: int | None = None,
|
188
188
|
ttl: float | timedelta | None = None,
|
189
|
-
**kwargs,
|
189
|
+
**kwargs: Any,
|
190
190
|
) -> ConnectionClass:
|
191
191
|
pass
|
192
192
|
|
@@ -197,7 +197,7 @@ def connection_factory(
|
|
197
197
|
type: str | None = None,
|
198
198
|
max_entries: int | None = None,
|
199
199
|
ttl: float | timedelta | None = None,
|
200
|
-
**kwargs,
|
200
|
+
**kwargs: Any,
|
201
201
|
) -> BaseConnection[Any]:
|
202
202
|
pass
|
203
203
|
|
streamlit/runtime/context.py
CHANGED
@@ -64,7 +64,7 @@ def _normalize_header(name: str) -> str:
|
|
64
64
|
|
65
65
|
|
66
66
|
class StreamlitHeaders(Mapping[str, str]):
|
67
|
-
def __init__(self, headers: Iterable[tuple[str, str]]):
|
67
|
+
def __init__(self, headers: Iterable[tuple[str, str]]) -> None:
|
68
68
|
dict_like_headers: dict[str, list[str]] = {}
|
69
69
|
|
70
70
|
for key, value in headers:
|
@@ -98,7 +98,7 @@ class StreamlitHeaders(Mapping[str, str]):
|
|
98
98
|
|
99
99
|
|
100
100
|
class StreamlitCookies(Mapping[str, str]):
|
101
|
-
def __init__(self, cookies: Mapping[str, str]):
|
101
|
+
def __init__(self, cookies: Mapping[str, str]) -> None:
|
102
102
|
self._cookies = MappingProxyType(cookies)
|
103
103
|
|
104
104
|
@classmethod
|
streamlit/runtime/credentials.py
CHANGED
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
import os
|
21
21
|
import sys
|
22
22
|
import textwrap
|
23
|
-
from typing import Final, NamedTuple, NoReturn
|
23
|
+
from typing import Final, NamedTuple, NoReturn, cast
|
24
24
|
from uuid import uuid4
|
25
25
|
|
26
26
|
from streamlit import cli_util, env_util, file_util, util
|
@@ -116,12 +116,12 @@ class Credentials:
|
|
116
116
|
_singleton: Credentials | None = None
|
117
117
|
|
118
118
|
@classmethod
|
119
|
-
def get_current(cls):
|
119
|
+
def get_current(cls) -> Credentials:
|
120
120
|
"""Return the singleton instance."""
|
121
121
|
if cls._singleton is None:
|
122
122
|
Credentials()
|
123
123
|
|
124
|
-
return Credentials._singleton
|
124
|
+
return cast("Credentials", Credentials._singleton)
|
125
125
|
|
126
126
|
def __init__(self):
|
127
127
|
"""Initialize class."""
|
streamlit/runtime/fragment.py
CHANGED
@@ -155,11 +155,10 @@ def _fragment(
|
|
155
155
|
)
|
156
156
|
|
157
157
|
return wrapper
|
158
|
-
|
159
|
-
non_optional_func = func
|
158
|
+
non_optional_func = func
|
160
159
|
|
161
160
|
@wraps(non_optional_func)
|
162
|
-
def wrap(*args, **kwargs):
|
161
|
+
def wrap(*args: Any, **kwargs: Any) -> Any:
|
163
162
|
from streamlit.delta_generator_singletons import context_dg_stack
|
164
163
|
|
165
164
|
ctx = get_script_run_ctx()
|
@@ -176,7 +175,7 @@ def _fragment(
|
|
176
175
|
# that the fragment is associated with the correct script running.
|
177
176
|
initialized_active_script_hash = ctx.active_script_hash
|
178
177
|
|
179
|
-
def wrapped_fragment():
|
178
|
+
def wrapped_fragment() -> Any:
|
180
179
|
import streamlit as st
|
181
180
|
|
182
181
|
if should_show_deprecation_warning:
|
@@ -45,7 +45,7 @@ def _get_session_id() -> str:
|
|
45
45
|
class MediaFileMetadata:
|
46
46
|
"""Metadata that the MediaFileManager needs for each file it manages."""
|
47
47
|
|
48
|
-
def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA):
|
48
|
+
def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA) -> None:
|
49
49
|
self._kind = kind
|
50
50
|
self._is_marked_for_delete = False
|
51
51
|
|
@@ -80,7 +80,7 @@ class MediaFileManager:
|
|
80
80
|
we should address it at some point.)
|
81
81
|
"""
|
82
82
|
|
83
|
-
def __init__(self, storage: MediaFileStorage):
|
83
|
+
def __init__(self, storage: MediaFileStorage) -> None:
|
84
84
|
self._storage = storage
|
85
85
|
|
86
86
|
# Dict of [file_id -> MediaFileMetadata]
|
@@ -89,7 +89,7 @@ class MemoryFile(NamedTuple):
|
|
89
89
|
|
90
90
|
|
91
91
|
class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
|
92
|
-
def __init__(self, media_endpoint: str):
|
92
|
+
def __init__(self, media_endpoint: str) -> None:
|
93
93
|
"""Create a new MemoryMediaFileStorage instance.
|
94
94
|
|
95
95
|
Parameters
|
@@ -35,7 +35,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
|
|
35
35
|
This class can be used safely from multiple threads simultaneously.
|
36
36
|
"""
|
37
37
|
|
38
|
-
def __init__(self, upload_endpoint: str):
|
38
|
+
def __init__(self, upload_endpoint: str) -> None:
|
39
39
|
self.file_storage: dict[str, dict[str, UploadedFileRec]] = defaultdict(dict)
|
40
40
|
self.endpoint = upload_endpoint
|
41
41
|
|
@@ -239,7 +239,7 @@ class Installation:
|
|
239
239
|
return util.repr_(self)
|
240
240
|
|
241
241
|
@property
|
242
|
-
def installation_id(self):
|
242
|
+
def installation_id(self) -> str:
|
243
243
|
return self.installation_id_v3
|
244
244
|
|
245
245
|
|
@@ -284,7 +284,7 @@ def _get_arg_metadata(arg: object) -> str | None:
|
|
284
284
|
|
285
285
|
|
286
286
|
def _get_command_telemetry(
|
287
|
-
_command_func: Callable[..., Any], _command_name: str, *args, **kwargs
|
287
|
+
_command_func: Callable[..., Any], _command_name: str, *args: Any, **kwargs: Any
|
288
288
|
) -> Command:
|
289
289
|
"""Get telemetry information for the given callable and its arguments."""
|
290
290
|
arg_keywords = inspect.getfullargspec(_command_func).args
|
@@ -391,12 +391,11 @@ def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
|
|
391
391
|
)
|
392
392
|
|
393
393
|
return wrapper
|
394
|
-
|
395
|
-
|
396
|
-
non_optional_func = func
|
394
|
+
# To make mypy type narrow F | None -> F
|
395
|
+
non_optional_func = func
|
397
396
|
|
398
397
|
@wraps(non_optional_func)
|
399
|
-
def wrapped_func(*args, **kwargs):
|
398
|
+
def wrapped_func(*args: Any, **kwargs: Any) -> Any:
|
400
399
|
from timeit import default_timer as timer
|
401
400
|
|
402
401
|
exec_start = timer()
|
@@ -38,8 +38,8 @@ class PagesManager:
|
|
38
38
|
self,
|
39
39
|
main_script_path: ScriptPath,
|
40
40
|
script_cache: ScriptCache | None = None,
|
41
|
-
**kwargs,
|
42
|
-
):
|
41
|
+
**kwargs: Any,
|
42
|
+
) -> None:
|
43
43
|
self._main_script_path = main_script_path
|
44
44
|
self._main_script_hash: PageHash = calc_md5(main_script_path)
|
45
45
|
self._script_cache = script_cache
|
@@ -135,7 +135,7 @@ class PagesManager:
|
|
135
135
|
self.intended_page_script_hash,
|
136
136
|
self._pages.get(fallback_page_hash, None),
|
137
137
|
)
|
138
|
-
|
138
|
+
if self.intended_page_name:
|
139
139
|
# If a user navigates directly to a non-main page of an app, the
|
140
140
|
# the page name can identify the page script to run
|
141
141
|
return next(
|
streamlit/runtime/runtime.py
CHANGED
@@ -167,7 +167,7 @@ class Runtime:
|
|
167
167
|
"""
|
168
168
|
return cls._instance is not None
|
169
169
|
|
170
|
-
def __init__(self, config: RuntimeConfig):
|
170
|
+
def __init__(self, config: RuntimeConfig) -> None:
|
171
171
|
"""Create a Runtime instance. It won't be started yet.
|
172
172
|
|
173
173
|
Runtime is *not* thread-safe. Its public methods are generally
|
@@ -31,7 +31,7 @@ _LOGGER: Final = getLogger(__name__)
|
|
31
31
|
class MessageSizeError(MarkdownFormattedException):
|
32
32
|
"""Exception raised when a websocket message is larger than the configured limit."""
|
33
33
|
|
34
|
-
def __init__(self, failed_msg_str: Any):
|
34
|
+
def __init__(self, failed_msg_str: Any) -> None:
|
35
35
|
msg = self._get_message(failed_msg_str)
|
36
36
|
super().__init__(msg)
|
37
37
|
|
@@ -55,7 +55,7 @@ of the client's browser and the Streamlit server._
|
|
55
55
|
class BadDurationStringError(StreamlitAPIException):
|
56
56
|
"""Raised when a bad duration argument string is passed."""
|
57
57
|
|
58
|
-
def __init__(self, duration: str):
|
58
|
+
def __init__(self, duration: str) -> None:
|
59
59
|
MarkdownFormattedException.__init__(
|
60
60
|
self,
|
61
61
|
"TTL string doesn't look right. It should be formatted as"
|