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.
Files changed (203) hide show
  1. streamlit/auth_util.py +3 -3
  2. streamlit/cli_util.py +3 -2
  3. streamlit/commands/logo.py +2 -2
  4. streamlit/commands/navigation.py +5 -4
  5. streamlit/commands/page_config.py +3 -1
  6. streamlit/components/types/base_custom_component.py +7 -7
  7. streamlit/components/v1/custom_component.py +6 -6
  8. streamlit/config.py +84 -48
  9. streamlit/config_option.py +2 -2
  10. streamlit/config_util.py +20 -12
  11. streamlit/connections/base_connection.py +3 -3
  12. streamlit/connections/snowflake_connection.py +5 -5
  13. streamlit/connections/snowpark_connection.py +3 -3
  14. streamlit/connections/sql_connection.py +9 -10
  15. streamlit/cursor.py +6 -6
  16. streamlit/delta_generator.py +7 -6
  17. streamlit/delta_generator_singletons.py +2 -2
  18. streamlit/deprecation_util.py +1 -1
  19. streamlit/elements/arrow.py +2 -3
  20. streamlit/elements/deck_gl_json_chart.py +30 -17
  21. streamlit/elements/dialog_decorator.py +3 -3
  22. streamlit/elements/doc_string.py +20 -20
  23. streamlit/elements/layouts.py +26 -7
  24. streamlit/elements/lib/built_in_chart_utils.py +37 -39
  25. streamlit/elements/lib/color_util.py +3 -3
  26. streamlit/elements/lib/column_types.py +2 -2
  27. streamlit/elements/lib/dialog.py +2 -2
  28. streamlit/elements/lib/event_utils.py +1 -1
  29. streamlit/elements/lib/mutable_status_container.py +1 -1
  30. streamlit/elements/lib/policies.py +3 -3
  31. streamlit/elements/lib/utils.py +5 -5
  32. streamlit/elements/map.py +20 -15
  33. streamlit/elements/progress.py +9 -12
  34. streamlit/elements/vega_charts.py +2 -2
  35. streamlit/elements/widgets/button_group.py +2 -2
  36. streamlit/elements/widgets/data_editor.py +2 -2
  37. streamlit/elements/widgets/multiselect.py +2 -2
  38. streamlit/elements/widgets/selectbox.py +1 -1
  39. streamlit/elements/widgets/slider.py +16 -14
  40. streamlit/elements/write.py +3 -6
  41. streamlit/errors.py +34 -21
  42. streamlit/external/langchain/streamlit_callback_handler.py +2 -2
  43. streamlit/file_util.py +8 -8
  44. streamlit/git_util.py +1 -1
  45. streamlit/hello/dataframe_demo.py +1 -1
  46. streamlit/hello/mapping_demo.py +1 -1
  47. streamlit/navigation/page.py +1 -1
  48. streamlit/proto/Block_pb2.py +38 -29
  49. streamlit/proto/Block_pb2.pyi +68 -4
  50. streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -1
  51. streamlit/proto/GapSize_pb2.py +29 -0
  52. streamlit/proto/GapSize_pb2.pyi +70 -0
  53. streamlit/proto/HeightConfig_pb2.py +27 -0
  54. streamlit/proto/HeightConfig_pb2.pyi +48 -0
  55. streamlit/proto/WidthConfig_pb2.py +2 -2
  56. streamlit/proto/WidthConfig_pb2.pyi +15 -1
  57. streamlit/runtime/app_session.py +2 -2
  58. streamlit/runtime/caching/cache_data_api.py +9 -5
  59. streamlit/runtime/caching/cache_errors.py +3 -3
  60. streamlit/runtime/caching/cache_resource_api.py +7 -7
  61. streamlit/runtime/caching/cache_utils.py +9 -9
  62. streamlit/runtime/caching/cached_message_replay.py +1 -1
  63. streamlit/runtime/caching/hashing.py +70 -74
  64. streamlit/runtime/caching/legacy_cache_api.py +1 -1
  65. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +3 -1
  66. streamlit/runtime/caching/storage/local_disk_cache_storage.py +1 -1
  67. streamlit/runtime/connection_factory.py +12 -12
  68. streamlit/runtime/context.py +2 -2
  69. streamlit/runtime/credentials.py +3 -3
  70. streamlit/runtime/fragment.py +3 -4
  71. streamlit/runtime/media_file_manager.py +2 -2
  72. streamlit/runtime/memory_media_file_storage.py +1 -1
  73. streamlit/runtime/memory_uploaded_file_manager.py +1 -1
  74. streamlit/runtime/metrics_util.py +5 -6
  75. streamlit/runtime/pages_manager.py +3 -3
  76. streamlit/runtime/runtime.py +1 -1
  77. streamlit/runtime/runtime_util.py +2 -2
  78. streamlit/runtime/scriptrunner/exec_code.py +10 -3
  79. streamlit/runtime/scriptrunner/magic.py +13 -8
  80. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  81. streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
  82. streamlit/runtime/scriptrunner_utils/script_run_context.py +6 -5
  83. streamlit/runtime/secrets.py +8 -11
  84. streamlit/runtime/state/query_params.py +2 -2
  85. streamlit/runtime/state/safe_session_state.py +2 -2
  86. streamlit/runtime/state/session_state.py +17 -15
  87. streamlit/runtime/stats.py +1 -1
  88. streamlit/runtime/uploaded_file_manager.py +1 -1
  89. streamlit/source_util.py +3 -4
  90. streamlit/static/index.html +1 -1
  91. streamlit/static/static/js/{ErrorOutline.esm.BgsGCsV4.js → ErrorOutline.esm.C-0hf1-k.js} +1 -1
  92. streamlit/static/static/js/{FileDownload.esm.CCKezPn5.js → FileDownload.esm.B-fFGI-X.js} +1 -1
  93. streamlit/static/static/js/{FileHelper.CprSF_kT.js → FileHelper.ACYo0OZo.js} +1 -1
  94. streamlit/static/static/js/{FormClearHelper.DiwQ0EtT.js → FormClearHelper.CVNTT-bJ.js} +1 -1
  95. streamlit/static/static/js/{Hooks.DDqhyZ1_.js → Hooks.C3thlpd2.js} +1 -1
  96. streamlit/static/static/js/{InputInstructions.BCEZxme4.js → InputInstructions.CwAxousX.js} +1 -1
  97. streamlit/static/static/js/{ProgressBar.CGdY94g_.js → ProgressBar.xh599Rum.js} +2 -2
  98. streamlit/static/static/js/{RenderInPortalIfExists.uGJp_Q0v.js → RenderInPortalIfExists.CQLIsNPE.js} +1 -1
  99. streamlit/static/static/js/{Toolbar.hTlw0-K1.js → Toolbar.LKdyvP0u.js} +1 -1
  100. streamlit/static/static/js/{index.xsH4HHeE.js → UploadFileInfo.0DCkpDDf.js} +5 -5
  101. streamlit/static/static/js/{base-input.mGTY3-qU.js → base-input.D8OdS4WW.js} +4 -4
  102. streamlit/static/static/js/{checkbox.Cg-5cKAh.js → checkbox.DSdYKlOI.js} +2 -2
  103. streamlit/static/static/js/{createSuper.-HPb1oYT.js → createSuper.B2pyCfWw.js} +1 -1
  104. streamlit/static/static/js/{data-grid-overlay-editor.BpNYxiTp.js → data-grid-overlay-editor.DhO2r0ne.js} +1 -1
  105. streamlit/static/static/js/{downloader.DS9891pS.js → downloader.C24skoDM.js} +1 -1
  106. streamlit/static/static/js/{es6.CU1PEL2w.js → es6.DHkvCKPh.js} +2 -2
  107. streamlit/static/static/js/{iframeResizer.contentWindow.CgJE2bJN.js → iframeResizer.contentWindow.2ckQaC2c.js} +1 -1
  108. streamlit/static/static/js/index.0dGwl8CJ.js +1 -0
  109. streamlit/static/static/js/index.B5A28NpR.js +1 -0
  110. streamlit/static/static/js/{index.BC0ueJ8H.js → index.B5EFweZ4.js} +1 -1
  111. streamlit/static/static/js/{index.CyGuL4If.js → index.BAafqHfB.js} +2 -2
  112. streamlit/static/static/js/{index.DWV80Vyw.js → index.BHTbGZPQ.js} +1 -1
  113. streamlit/static/static/js/index.BNXtQAj4.js +1 -0
  114. streamlit/static/static/js/index.BRhKaVdO.js +1 -0
  115. streamlit/static/static/js/index.BSOiJVQd.js +2 -0
  116. streamlit/static/static/js/{index.GSYBrzVp.js → index.BVgTQbOJ.js} +1 -1
  117. streamlit/static/static/js/{index.BTTj6ld4.js → index.BflIniLm.js} +1 -1
  118. streamlit/static/static/js/{index.DLTqo4pp.js → index.BjeNtZIz.js} +3 -3
  119. streamlit/static/static/js/{index.DZ6oX-v9.js → index.By-NmdnB.js} +161 -161
  120. streamlit/static/static/js/{index.DVpzZJNg.js → index.CIoOEhZ2.js} +1 -1
  121. streamlit/static/static/js/{index.CN91oQMB.js → index.CRCdonis.js} +36 -36
  122. streamlit/static/static/js/index.CRxaBCJ7.js +1 -0
  123. streamlit/static/static/js/index.CU-pbYVN.js +1 -0
  124. streamlit/static/static/js/{index.CzGUd4IN.js → index.CUsk52t2.js} +1 -1
  125. streamlit/static/static/js/{index.BHVQ94t4.js → index.CVO14oQG.js} +2 -2
  126. streamlit/static/static/js/index.CXFuA6J-.js +1 -0
  127. streamlit/static/static/js/{index.DJHUlWgy.js → index.C_dd5q7u.js} +1 -1
  128. streamlit/static/static/js/{index.Bph6ZoI5.js → index.CjWUnKIN.js} +1 -1
  129. streamlit/static/static/js/{index.B209tswL.js → index.CkTL9bAR.js} +256 -256
  130. streamlit/static/static/js/{index.ErkF0SoX.js → index.CsbhsAPy.js} +2 -2
  131. streamlit/static/static/js/{index.hPjr68pz.js → index.CtCnBUtk.js} +1 -1
  132. streamlit/static/static/js/{index.BT0p7gAu.js → index.CwuKadAX.js} +1 -1
  133. streamlit/static/static/js/{index.CtoDsUtq.js → index.D0R7Xh4Z.js} +1 -1
  134. streamlit/static/static/js/index.D2D75EDw.js +73 -0
  135. streamlit/static/static/js/index.D4eMiZ1F.js +1 -0
  136. streamlit/static/static/js/{index.Dh4RKl-F.js → index.D7SCC3z9.js} +1 -1
  137. streamlit/static/static/js/index.DZiilxEt.js +1 -0
  138. streamlit/static/static/js/{index.DtqvdV-p.js → index.Dvr1cEJS.js} +1 -1
  139. streamlit/static/static/js/index.JtIlC6Uq.js +1 -0
  140. streamlit/static/static/js/index.fz_c3Xh_.js +1 -0
  141. streamlit/static/static/js/{index.CvFsF3FD.js → index.gFjPlsMT.js} +1 -1
  142. streamlit/static/static/js/{index.DPJBu2uZ.js → index.jCJYMVED.js} +1 -1
  143. streamlit/static/static/js/index.xldt56AE.js +1 -0
  144. streamlit/static/static/js/{index.Bb-Ukg41.js → index.yzoj_DuM.js} +1 -1
  145. streamlit/static/static/js/{input.DY17i94N.js → input.BP6LX_Bg.js} +2 -2
  146. streamlit/static/static/js/{memory.DsIIcbSd.js → memory.E9x2ZYJv.js} +1 -1
  147. streamlit/static/static/js/{mergeWith.cRgGdgvI.js → mergeWith.CZP2AaVS.js} +1 -1
  148. streamlit/static/static/js/{number-overlay-editor.B8Xi2dYq.js → number-overlay-editor.D-Kl79U_.js} +1 -1
  149. streamlit/static/static/js/{possibleConstructorReturn.BgDi5nUm.js → possibleConstructorReturn.P2ILVC_6.js} +1 -1
  150. streamlit/static/static/js/{sandbox.BH9emp13.js → sandbox.DfzJIGMV.js} +1 -1
  151. streamlit/static/static/js/{textarea.DAyShsGG.js → textarea.4PjzfDWF.js} +2 -2
  152. streamlit/static/static/js/{timepicker.CCH2R2Y0.js → timepicker.DMQdaNzO.js} +1 -1
  153. streamlit/static/static/js/{toConsumableArray.CNffSDCu.js → toConsumableArray.BEdkbHYx.js} +1 -1
  154. streamlit/static/static/js/{uniqueId.B49CstkV.js → uniqueId.CAs7ftHC.js} +1 -1
  155. streamlit/static/static/js/{useBasicWidgetState.CkThOkF9.js → useBasicWidgetState.Cedp0V76.js} +1 -1
  156. streamlit/static/static/js/useOnInputChange.CvRKHHKx.js +1 -0
  157. streamlit/static/static/js/{withFullScreenWrapper.UsvF_Jwr.js → withFullScreenWrapper.BbmjZAzW.js} +1 -1
  158. streamlit/string_util.py +6 -7
  159. streamlit/temporary_directory.py +12 -3
  160. streamlit/testing/v1/app_test.py +11 -6
  161. streamlit/testing/v1/element_tree.py +134 -158
  162. streamlit/testing/v1/local_script_runner.py +5 -5
  163. streamlit/testing/v1/util.py +11 -4
  164. streamlit/type_util.py +3 -4
  165. streamlit/user_info.py +3 -2
  166. streamlit/util.py +1 -1
  167. streamlit/watcher/event_based_path_watcher.py +1 -1
  168. streamlit/watcher/folder_black_list.py +1 -1
  169. streamlit/watcher/local_sources_watcher.py +5 -5
  170. streamlit/watcher/path_watcher.py +1 -1
  171. streamlit/web/bootstrap.py +2 -1
  172. streamlit/web/cli.py +12 -11
  173. streamlit/web/server/browser_websocket_handler.py +1 -1
  174. streamlit/web/server/component_request_handler.py +1 -1
  175. streamlit/web/server/media_file_handler.py +2 -1
  176. streamlit/web/server/oauth_authlib_routes.py +9 -2
  177. streamlit/web/server/oidc_mixin.py +13 -6
  178. streamlit/web/server/routes.py +3 -3
  179. streamlit/web/server/server.py +1 -1
  180. streamlit/web/server/server_util.py +7 -6
  181. streamlit/web/server/upload_file_request_handler.py +5 -5
  182. {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/METADATA +1 -1
  183. {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/RECORD +187 -184
  184. {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/WHEEL +1 -1
  185. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +0 -1
  186. streamlit/static/static/js/index.BVjgrQ4R.js +0 -1
  187. streamlit/static/static/js/index.BXYstdPh.js +0 -2
  188. streamlit/static/static/js/index.BZ9mqzEJ.js +0 -1
  189. streamlit/static/static/js/index.BhTok8vt.js +0 -1
  190. streamlit/static/static/js/index.CJPcdxPe.js +0 -1
  191. streamlit/static/static/js/index.CMOA-8Q2.js +0 -1
  192. streamlit/static/static/js/index.DAxf3_iz.js +0 -1
  193. streamlit/static/static/js/index.Dn76KVNf.js +0 -1
  194. streamlit/static/static/js/index.OngWTN39.js +0 -1
  195. streamlit/static/static/js/index.PSwG8ayC.js +0 -1
  196. streamlit/static/static/js/index.UTlCdasa.js +0 -73
  197. streamlit/static/static/js/index.eR_vQpeg.js +0 -1
  198. streamlit/static/static/js/index.fLsU9uCJ.js +0 -1
  199. streamlit/static/static/js/index.kXOZCC_6.js +0 -1
  200. streamlit/static/static/js/useOnInputChange.BqEq0xFZ.js +0 -1
  201. {streamlit_nightly-1.45.1.dev20250507.data → streamlit_nightly-1.45.1.dev20250509.data}/scripts/streamlit.cmd +0 -0
  202. {streamlit_nightly-1.45.1.dev20250507.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/entry_points.txt +0 -0
  203. {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:
@@ -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(config_overrides: dict[str, Any]):
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(overrides_dict):
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
- else:
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
- elif isinstance(obj, bytes):
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
@@ -27,7 +27,7 @@ def memoize(func: Callable[..., Any]) -> Callable[..., Any]:
27
27
  result: list[Any] = []
28
28
 
29
29
  @functools.wraps(func)
30
- def wrapped_func():
30
+ def wrapped_func() -> Any:
31
31
  if not result:
32
32
  result.append(func())
33
33
  return result[0]
@@ -243,7 +243,7 @@ class WatchedPath:
243
243
  *, # keyword-only arguments:
244
244
  glob_pattern: str | None = None,
245
245
  allow_nonexistent: bool = False,
246
- ):
246
+ ) -> None:
247
247
  self.md5 = md5
248
248
  self.modification_time = modification_time
249
249
 
@@ -67,7 +67,7 @@ class FolderBlackList:
67
67
  def __repr__(self) -> str:
68
68
  return util.repr_(self)
69
69
 
70
- def is_blacklisted(self, filepath):
70
+ def is_blacklisted(self, filepath: str) -> bool:
71
71
  """Test if filepath is in the blacklist.
72
72
 
73
73
  Parameters
@@ -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)
@@ -38,7 +38,7 @@ class NoOpPathWatcher:
38
38
  *, # keyword-only arguments:
39
39
  glob_pattern: str | None = None,
40
40
  allow_nonexistent: bool = False,
41
- ):
41
+ ) -> None:
42
42
  pass
43
43
 
44
44
 
@@ -141,7 +141,8 @@ def _fix_pydeck_mapbox_api_warning() -> None:
141
141
  will throw an exception.
142
142
  """
143
143
 
144
- os.environ["MAPBOX_API_KEY"] = config.get_option("mapbox.token")
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(config_option: ConfigOption):
67
- def callback(_ctx: click.Context, _param: click.Parameter, cli_value) -> None:
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 None
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
- else:
220
- raise click.BadArgumentUsage(
221
- f"Streamlit requires raw Python (.py) files, not {extension}.\nFor more information, please see https://docs.streamlit.io"
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, request_handler: tornado.web.RequestHandler, redirect_uri=None, **kwargs
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
  """
@@ -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)
@@ -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, trailing_slash: Literal["optional", "required", "prohibited"] = "optional"
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
- path = [x.strip("/") for x in path if x] # Filter out falsely components.
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(path)
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"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-nightly
3
- Version: 1.45.1.dev20250507
3
+ Version: 1.45.1.dev20250509
4
4
  Summary: A faster way to build and share data apps
5
5
  Home-page: https://streamlit.io
6
6
  Author: Snowflake Inc