streamlit-nightly 1.45.1.dev20250505__py3-none-any.whl → 1.45.1.dev20250507__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 (51) hide show
  1. streamlit/__init__.py +4 -1
  2. streamlit/column_config.py +3 -1
  3. streamlit/commands/execution_control.py +3 -1
  4. streamlit/commands/logo.py +7 -2
  5. streamlit/connections/base_connection.py +2 -2
  6. streamlit/connections/snowflake_connection.py +4 -3
  7. streamlit/dataframe_util.py +2 -1
  8. streamlit/delta_generator.py +15 -35
  9. streamlit/elements/arrow.py +3 -3
  10. streamlit/elements/deck_gl_json_chart.py +1 -1
  11. streamlit/elements/exception.py +5 -1
  12. streamlit/elements/layouts.py +3 -9
  13. streamlit/elements/lib/column_types.py +2 -2
  14. streamlit/elements/lib/dialog.py +2 -1
  15. streamlit/elements/lib/js_number.py +4 -4
  16. streamlit/elements/lib/options_selector_utils.py +8 -5
  17. streamlit/elements/media.py +8 -7
  18. streamlit/elements/vega_charts.py +2 -2
  19. streamlit/elements/widgets/button.py +5 -6
  20. streamlit/elements/widgets/number_input.py +81 -28
  21. streamlit/elements/widgets/slider.py +87 -35
  22. streamlit/errors.py +9 -6
  23. streamlit/runtime/caching/cache_data_api.py +7 -9
  24. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -1
  25. streamlit/runtime/credentials.py +3 -3
  26. streamlit/runtime/fragment.py +2 -2
  27. streamlit/runtime/metrics_util.py +2 -2
  28. streamlit/runtime/runtime.py +1 -1
  29. streamlit/runtime/runtime_util.py +2 -1
  30. streamlit/runtime/scriptrunner/script_runner.py +3 -3
  31. streamlit/runtime/scriptrunner_utils/script_run_context.py +1 -0
  32. streamlit/runtime/secrets.py +14 -7
  33. streamlit/runtime/state/query_params.py +8 -8
  34. streamlit/runtime/state/session_state.py +8 -1
  35. streamlit/string_util.py +8 -5
  36. streamlit/web/bootstrap.py +2 -2
  37. streamlit/web/cli.py +2 -1
  38. streamlit/web/server/browser_websocket_handler.py +3 -2
  39. streamlit/web/server/component_request_handler.py +7 -7
  40. streamlit/web/server/media_file_handler.py +2 -2
  41. streamlit/web/server/oauth_authlib_routes.py +3 -3
  42. streamlit/web/server/routes.py +2 -2
  43. streamlit/web/server/server.py +4 -4
  44. streamlit/web/server/upload_file_request_handler.py +4 -3
  45. streamlit/web/server/websocket_headers.py +1 -1
  46. {streamlit_nightly-1.45.1.dev20250505.dist-info → streamlit_nightly-1.45.1.dev20250507.dist-info}/METADATA +1 -1
  47. {streamlit_nightly-1.45.1.dev20250505.dist-info → streamlit_nightly-1.45.1.dev20250507.dist-info}/RECORD +51 -51
  48. {streamlit_nightly-1.45.1.dev20250505.data → streamlit_nightly-1.45.1.dev20250507.data}/scripts/streamlit.cmd +0 -0
  49. {streamlit_nightly-1.45.1.dev20250505.dist-info → streamlit_nightly-1.45.1.dev20250507.dist-info}/WHEEL +0 -0
  50. {streamlit_nightly-1.45.1.dev20250505.dist-info → streamlit_nightly-1.45.1.dev20250507.dist-info}/entry_points.txt +0 -0
  51. {streamlit_nightly-1.45.1.dev20250505.dist-info → streamlit_nightly-1.45.1.dev20250507.dist-info}/top_level.txt +0 -0
@@ -201,10 +201,6 @@ class SliderSerde:
201
201
 
202
202
 
203
203
  class SliderMixin:
204
- # For easier readability, all the arguments with un-changing types across these overload signatures have been
205
- # collapsed onto a single line.
206
-
207
- # fmt: off
208
204
  # If min/max/value/step are not provided, then we return an int.
209
205
  # if ONLY step is provided, then it must be an int and we return an int.
210
206
  @overload
@@ -213,11 +209,18 @@ class SliderMixin:
213
209
  label: str,
214
210
  min_value: None = None,
215
211
  max_value: None = None,
216
- value: None = None,
212
+ value: None = None,
217
213
  step: int | None = None,
218
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, *, disabled: bool = False, label_visibility: LabelVisibility = "visible"
219
- ) -> int:
220
- ...
214
+ format: str | None = None,
215
+ key: Key | None = None,
216
+ help: str | None = None,
217
+ on_change: WidgetCallback | None = None,
218
+ args: WidgetArgs | None = None,
219
+ kwargs: WidgetKwargs | None = None,
220
+ *,
221
+ disabled: bool = False,
222
+ label_visibility: LabelVisibility = "visible",
223
+ ) -> int: ...
221
224
 
222
225
  # If min-value or max_value is provided and a numeric type, and value (if provided)
223
226
  # is a singular numeric, return the same numeric type.
@@ -229,9 +232,16 @@ class SliderMixin:
229
232
  max_value: SliderNumericT | None = None,
230
233
  value: SliderNumericT | None = None,
231
234
  step: StepNumericT[SliderNumericT] | None = None,
232
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, *, disabled: bool = False, label_visibility: LabelVisibility = "visible"
233
- ) -> SliderNumericT:
234
- ...
235
+ format: str | None = None,
236
+ key: Key | None = None,
237
+ help: str | None = None,
238
+ on_change: WidgetCallback | None = None,
239
+ args: WidgetArgs | None = None,
240
+ kwargs: WidgetKwargs | None = None,
241
+ *,
242
+ disabled: bool = False,
243
+ label_visibility: LabelVisibility = "visible",
244
+ ) -> SliderNumericT: ...
235
245
 
236
246
  # If value is provided and a sequence of numeric type,
237
247
  # return a tuple of the same numeric type.
@@ -244,9 +254,15 @@ class SliderMixin:
244
254
  *,
245
255
  value: SliderNumericSpanT[SliderNumericT],
246
256
  step: StepNumericT[SliderNumericT] | None = None,
247
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, disabled: bool = False, label_visibility: LabelVisibility = "visible"
248
- ) -> tuple[SliderNumericT, SliderNumericT]:
249
- ...
257
+ format: str | None = None,
258
+ key: Key | None = None,
259
+ help: str | None = None,
260
+ on_change: WidgetCallback | None = None,
261
+ args: WidgetArgs | None = None,
262
+ kwargs: WidgetKwargs | None = None,
263
+ disabled: bool = False,
264
+ label_visibility: LabelVisibility = "visible",
265
+ ) -> tuple[SliderNumericT, SliderNumericT]: ...
250
266
 
251
267
  # If value is provided positionally and a sequence of numeric type,
252
268
  # return a tuple of the same numeric type.
@@ -257,11 +273,17 @@ class SliderMixin:
257
273
  min_value: SliderNumericT,
258
274
  max_value: SliderNumericT,
259
275
  value: SliderNumericSpanT[SliderNumericT],
260
- /,
261
276
  step: StepNumericT[SliderNumericT] | None = None,
262
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, *, disabled: bool = False, label_visibility: LabelVisibility = "visible"
263
- ) -> tuple[SliderNumericT, SliderNumericT]:
264
- ...
277
+ format: str | None = None,
278
+ key: Key | None = None,
279
+ help: str | None = None,
280
+ on_change: WidgetCallback | None = None,
281
+ args: WidgetArgs | None = None,
282
+ kwargs: WidgetKwargs | None = None,
283
+ *,
284
+ disabled: bool = False,
285
+ label_visibility: LabelVisibility = "visible",
286
+ ) -> tuple[SliderNumericT, SliderNumericT]: ...
265
287
 
266
288
  # If min-value is provided and a datelike type, and value (if provided)
267
289
  # is a singular datelike, return the same datelike type.
@@ -273,9 +295,16 @@ class SliderMixin:
273
295
  max_value: SliderDatelikeT | None = None,
274
296
  value: SliderDatelikeT | None = None,
275
297
  step: StepDatelikeT | None = None,
276
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, *, disabled: bool = False, label_visibility: LabelVisibility = "visible"
277
- ) -> SliderDatelikeT:
278
- ...
298
+ format: str | None = None,
299
+ key: Key | None = None,
300
+ help: str | None = None,
301
+ on_change: WidgetCallback | None = None,
302
+ args: WidgetArgs | None = None,
303
+ kwargs: WidgetKwargs | None = None,
304
+ *,
305
+ disabled: bool = False,
306
+ label_visibility: LabelVisibility = "visible",
307
+ ) -> SliderDatelikeT: ...
279
308
 
280
309
  # If max-value is provided and a datelike type, and value (if provided)
281
310
  # is a singular datelike, return the same datelike type.
@@ -288,9 +317,15 @@ class SliderMixin:
288
317
  max_value: SliderDatelikeT,
289
318
  value: SliderDatelikeT | None = None,
290
319
  step: StepDatelikeT | None = None,
291
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, disabled: bool = False, label_visibility: LabelVisibility = "visible"
292
- ) -> SliderDatelikeT:
293
- ...
320
+ format: str | None = None,
321
+ key: Key | None = None,
322
+ help: str | None = None,
323
+ on_change: WidgetCallback | None = None,
324
+ args: WidgetArgs | None = None,
325
+ kwargs: WidgetKwargs | None = None,
326
+ disabled: bool = False,
327
+ label_visibility: LabelVisibility = "visible",
328
+ ) -> SliderDatelikeT: ...
294
329
 
295
330
  # If value is provided and a datelike type, return the same datelike type.
296
331
  @overload
@@ -302,9 +337,15 @@ class SliderMixin:
302
337
  *,
303
338
  value: SliderDatelikeT,
304
339
  step: StepDatelikeT | None = None,
305
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, disabled: bool = False, label_visibility: LabelVisibility = "visible"
306
- ) -> SliderDatelikeT:
307
- ...
340
+ format: str | None = None,
341
+ key: Key | None = None,
342
+ help: str | None = None,
343
+ on_change: WidgetCallback | None = None,
344
+ args: WidgetArgs | None = None,
345
+ kwargs: WidgetKwargs | None = None,
346
+ disabled: bool = False,
347
+ label_visibility: LabelVisibility = "visible",
348
+ ) -> SliderDatelikeT: ...
308
349
 
309
350
  # If value is provided and a sequence of datelike type,
310
351
  # return a tuple of the same datelike type.
@@ -317,9 +358,15 @@ class SliderMixin:
317
358
  *,
318
359
  value: SliderDatelikeSpanT[SliderDatelikeT],
319
360
  step: StepDatelikeT | None = None,
320
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, disabled: bool = False, label_visibility: LabelVisibility = "visible"
321
- ) -> tuple[SliderDatelikeT, SliderDatelikeT]:
322
- ...
361
+ format: str | None = None,
362
+ key: Key | None = None,
363
+ help: str | None = None,
364
+ on_change: WidgetCallback | None = None,
365
+ args: WidgetArgs | None = None,
366
+ kwargs: WidgetKwargs | None = None,
367
+ disabled: bool = False,
368
+ label_visibility: LabelVisibility = "visible",
369
+ ) -> tuple[SliderDatelikeT, SliderDatelikeT]: ...
323
370
 
324
371
  # If value is provided positionally and a sequence of datelike type,
325
372
  # return a tuple of the same datelike type.
@@ -332,11 +379,16 @@ class SliderMixin:
332
379
  value: SliderDatelikeSpanT[SliderDatelikeT],
333
380
  /,
334
381
  step: StepDatelikeT | None = None,
335
- format: str | None = None, key: Key | None = None, help: str | None = None, on_change: WidgetCallback | None = None, args: WidgetArgs | None = None, kwargs: WidgetKwargs | None = None, *, disabled: bool = False, label_visibility: LabelVisibility = "visible"
336
- ) -> tuple[SliderDatelikeT, SliderDatelikeT]:
337
- ...
338
-
339
- # fmt: on
382
+ format: str | None = None,
383
+ key: Key | None = None,
384
+ help: str | None = None,
385
+ on_change: WidgetCallback | None = None,
386
+ args: WidgetArgs | None = None,
387
+ kwargs: WidgetKwargs | None = None,
388
+ *,
389
+ disabled: bool = False,
390
+ label_visibility: LabelVisibility = "visible",
391
+ ) -> tuple[SliderDatelikeT, SliderDatelikeT]: ...
340
392
 
341
393
  # https://github.com/python/mypy/issues/17614
342
394
  @gather_metrics("slider") # type: ignore[misc]
streamlit/errors.py CHANGED
@@ -49,7 +49,7 @@ class FragmentStorageKeyError(Error, KeyError):
49
49
  pass
50
50
 
51
51
 
52
- class FragmentHandledException(Exception):
52
+ class FragmentHandledException(Exception): # noqa: N818
53
53
  """An exception that is raised by the fragment
54
54
  when it has handled the exception itself.
55
55
  """
@@ -57,15 +57,15 @@ class FragmentHandledException(Exception):
57
57
  pass
58
58
 
59
59
 
60
- class NoStaticFiles(Error):
60
+ class NoStaticFiles(Error): # noqa: N818
61
61
  pass
62
62
 
63
63
 
64
- class NoSessionContext(Error):
64
+ class NoSessionContext(Error): # noqa: N818
65
65
  pass
66
66
 
67
67
 
68
- class MarkdownFormattedException(Error):
68
+ class MarkdownFormattedException(Error): # noqa: N818
69
69
  """Exceptions with Markdown in their description.
70
70
 
71
71
  Instances of this class can use markdown in their messages, which will get
@@ -199,7 +199,8 @@ class StreamlitInvalidSidebarStateError(LocalizableStreamlitException):
199
199
 
200
200
  def __init__(self, initial_sidebar_state: str):
201
201
  super().__init__(
202
- '`initial_sidebar_state` must be `"auto"` or `"expanded"` or `"collapsed"` (got `"{initial_sidebar_state}"`)',
202
+ '`initial_sidebar_state` must be `"auto"` or `"expanded"` or '
203
+ '`"collapsed"` (got `"{initial_sidebar_state}"`)',
203
204
  initial_sidebar_state=initial_sidebar_state,
204
205
  )
205
206
 
@@ -413,7 +414,9 @@ class StreamlitFragmentWidgetsNotAllowedOutsideError(LocalizableStreamlitExcepti
413
414
 
414
415
 
415
416
  class StreamlitInvalidFormCallbackError(LocalizableStreamlitException):
416
- """Exception raised a `on_change` callback is set on any element in a form except for the `st.form_submit_button`."""
417
+ """Exception raised a `on_change` callback is set on any element in a form except for
418
+ the `st.form_submit_button`.
419
+ """
417
420
 
418
421
  def __init__(self):
419
422
  super().__init__(
@@ -57,7 +57,7 @@ from streamlit.runtime.caching.storage import (
57
57
  CacheStorageManager,
58
58
  )
59
59
  from streamlit.runtime.caching.storage.cache_storage_protocol import (
60
- InvalidCacheStorageContext,
60
+ InvalidCacheStorageContextError,
61
61
  )
62
62
  from streamlit.runtime.caching.storage.dummy_cache_storage import (
63
63
  MemoryCacheStorageManager,
@@ -270,12 +270,11 @@ class DataCaches(CacheStatsProvider):
270
270
  )
271
271
  try:
272
272
  self.get_storage_manager().check_context(cache_context)
273
- except InvalidCacheStorageContext as e:
274
- _LOGGER.error(
273
+ except InvalidCacheStorageContextError:
274
+ _LOGGER.exception(
275
275
  "Cache params for function %s are incompatible with current "
276
276
  "cache storage manager.",
277
277
  function_name,
278
- exc_info=e,
279
278
  )
280
279
  raise
281
280
 
@@ -298,11 +297,10 @@ class DataCaches(CacheStatsProvider):
298
297
  def get_storage_manager(self) -> CacheStorageManager:
299
298
  if runtime.exists():
300
299
  return runtime.get_instance().cache_storage_manager
301
- else:
302
- # When running in "raw mode", we can't access the CacheStorageManager,
303
- # so we're falling back to InMemoryCache.
304
- _LOGGER.warning("No runtime found, using MemoryCacheStorageManager")
305
- return MemoryCacheStorageManager()
300
+ # When running in "raw mode", we can't access the CacheStorageManager,
301
+ # so we're falling back to InMemoryCache.
302
+ _LOGGER.warning("No runtime found, using MemoryCacheStorageManager")
303
+ return MemoryCacheStorageManager()
306
304
 
307
305
 
308
306
  # Singleton DataCaches instance
@@ -68,7 +68,7 @@ class CacheStorageKeyNotFoundError(CacheStorageError):
68
68
  """Raised when the key is not found in the cache storage."""
69
69
 
70
70
 
71
- class InvalidCacheStorageContext(CacheStorageError):
71
+ class InvalidCacheStorageContextError(CacheStorageError):
72
72
  """Raised if the cache storage manager is not able to work with
73
73
  provided CacheStorageContext.
74
74
  """
@@ -79,7 +79,7 @@ def _send_email(email: str) -> None:
79
79
  ).json()
80
80
  metrics_url = response_json.get("url", "")
81
81
  except Exception:
82
- _LOGGER.error("Failed to fetch metrics URL")
82
+ _LOGGER.exception("Failed to fetch metrics URL")
83
83
  return
84
84
 
85
85
  headers = {
@@ -150,7 +150,7 @@ class Credentials:
150
150
  with open(self._conf_file) as f:
151
151
  data = toml.load(f).get("general")
152
152
  if data is None:
153
- raise Exception
153
+ raise RuntimeError # noqa: TRY301
154
154
  self.activation = _verify_email(data.get("email"))
155
155
  except FileNotFoundError:
156
156
  if auto_resolve:
@@ -164,7 +164,7 @@ class Credentials:
164
164
  self.reset()
165
165
  self.activate(show_instructions=not auto_resolve)
166
166
  return
167
- raise Exception(
167
+ raise RuntimeError(
168
168
  textwrap.dedent(
169
169
  """
170
170
  Unable to load credentials from %s.
@@ -246,11 +246,11 @@ def _fragment(
246
246
  except (
247
247
  RerunException,
248
248
  StopException,
249
- ) as e:
249
+ ):
250
250
  # The wrapped_fragment function is executed
251
251
  # inside of a exec_func_with_error_handling call, so
252
252
  # there is a correct handler for these exceptions.
253
- raise e
253
+ raise
254
254
  except Exception as e:
255
255
  # render error here so that the delta path is correct
256
256
  # for full app runs, the error will be displayed by the
@@ -442,12 +442,12 @@ def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
442
442
  _LOGGER.debug("Failed to collect command telemetry", exc_info=ex)
443
443
  try:
444
444
  result = non_optional_func(*args, **kwargs)
445
- except RerunException as ex:
445
+ except RerunException:
446
446
  # Duplicated from below, because static analysis tools get confused
447
447
  # by deferring the rethrow.
448
448
  if tracking_activated and command_telemetry:
449
449
  command_telemetry.time = to_microseconds(timer() - exec_start)
450
- raise ex
450
+ raise
451
451
  finally:
452
452
  # Activate tracking again if command executes without any exceptions
453
453
  # we only want to do that if this command has set the
@@ -596,7 +596,7 @@ class Runtime:
596
596
  elif self._state == RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED:
597
597
  pass
598
598
  else:
599
- raise RuntimeError(f"Bad Runtime state at start: {self._state}")
599
+ raise RuntimeError(f"Bad Runtime state at start: {self._state}") # noqa: TRY301
600
600
 
601
601
  # Signal that we're started and ready to accept sessions
602
602
  async_objs.started.set_result(None)
@@ -39,7 +39,8 @@ class MessageSizeError(MarkdownFormattedException):
39
39
  # This needs to have zero indentation otherwise the markdown will render incorrectly.
40
40
  return (
41
41
  f"""
42
- **Data of size {len(failed_msg_str) / 1e6:.1f} MB exceeds the message size limit of {get_max_message_size_bytes() / 1e6} MB.**
42
+ **Data of size {len(failed_msg_str) / 1e6:.1f} MB exceeds the message size limit of
43
+ {get_max_message_size_bytes() / 1e6} MB.**
43
44
 
44
45
  This is often caused by a large chart or dataframe. Please decrease the amount of data sent
45
46
  to the browser, or increase the limit by setting the config option `server.maxMessageSize`.
@@ -297,7 +297,7 @@ class ScriptRunner:
297
297
 
298
298
  """
299
299
  if self._script_thread is not None:
300
- raise Exception("ScriptRunner was already started")
300
+ raise RuntimeError("ScriptRunner was already started")
301
301
 
302
302
  self._script_thread = threading.Thread(
303
303
  target=self._run_script_thread,
@@ -626,11 +626,11 @@ class ScriptRunner:
626
626
  " Usually this doesn't happen or no action is"
627
627
  " required, so its mainly for debugging."
628
628
  )
629
- except (RerunException, StopException) as e:
629
+ except (RerunException, StopException):
630
630
  # The wrapped_fragment function is executed
631
631
  # inside of a exec_func_with_error_handling call, so
632
632
  # there is a correct handler for these exceptions.
633
- raise e
633
+ raise
634
634
  except Exception: # noqa: S110
635
635
  # Ignore exceptions raised by fragments here as we don't
636
636
  # want to stop the execution of other fragments. The
@@ -107,6 +107,7 @@ class ScriptRunContext:
107
107
  current_fragment_id: str | None = None
108
108
  fragment_ids_this_run: list[str] | None = None
109
109
  new_fragment_ids: set[str] = field(default_factory=set)
110
+ in_fragment_callback: bool = False
110
111
  _active_script_hash: str = ""
111
112
  # we allow only one dialog to be open at the same time
112
113
  has_dialog_opened: bool = False
@@ -37,7 +37,9 @@ _LOGGER: Final = get_logger(__name__)
37
37
 
38
38
 
39
39
  class SecretErrorMessages:
40
- """SecretErrorMessages stores all error messages we use for secrets to allow customization for different environments.
40
+ """SecretErrorMessages stores all error messages we use for secrets to allow customization
41
+ for different environments.
42
+
41
43
  For example Streamlit Cloud can customize the message to be different than the open source.
42
44
 
43
45
  For internal use, may change in future releases without notice.
@@ -46,13 +48,15 @@ class SecretErrorMessages:
46
48
  def __init__(self):
47
49
  self.missing_attr_message = lambda attr_name: (
48
50
  f'st.secrets has no attribute "{attr_name}". '
49
- f"Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings on Streamlit Cloud? "
50
- f"More info: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
51
+ "Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings "
52
+ "on Streamlit Cloud? More info: "
53
+ "https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
51
54
  )
52
55
  self.missing_key_message = lambda key: (
53
56
  f'st.secrets has no key "{key}". '
54
- f"Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings on Streamlit Cloud? "
55
- f"More info: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
57
+ "Did you forget to add it to secrets.toml, mount it to secret directory, or the app settings "
58
+ "on Streamlit Cloud? More info: "
59
+ "https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/secrets-management"
56
60
  )
57
61
  self.no_secrets_found = lambda file_paths: (
58
62
  f"No secrets found. Valid paths for a secrets.toml file or secret directories are: {', '.join(file_paths)}"
@@ -272,7 +276,8 @@ class Secrets(Mapping[str, Any]):
272
276
  return secrets, found_secrets_file
273
277
 
274
278
  def _parse_directory(self, path: str) -> tuple[Mapping[str, Any], bool]:
275
- """Parse a directory for secrets. Directory style can be used to support Kubernetes secrets that are mounted to folders.
279
+ """Parse a directory for secrets. Directory style can be used to support Kubernetes secrets that are
280
+ mounted to folders.
276
281
 
277
282
  Example structure:
278
283
  - top_level_secret_folder
@@ -380,7 +385,9 @@ class Secrets(Mapping[str, Any]):
380
385
  return self._secrets
381
386
 
382
387
  def to_dict(self) -> dict[str, Any]:
383
- """Converts the secrets store into a nested dictionary, where nested AttrDict objects are also converted into dictionaries."""
388
+ """Converts the secrets store into a nested dictionary, where nested AttrDict objects are
389
+ also converted into dictionaries.
390
+ """
384
391
  secrets = self._parse()
385
392
  return _convert_to_dict(secrets)
386
393
 
@@ -58,17 +58,17 @@ class QueryParams(MutableMapping[str, str]):
58
58
  If the key is not present, raise KeyError.
59
59
  """
60
60
  self._ensure_single_query_api_used()
61
+ if key in EMBED_QUERY_PARAMS_KEYS:
62
+ raise KeyError(missing_key_error_message(key))
63
+
61
64
  try:
62
- if key in EMBED_QUERY_PARAMS_KEYS:
63
- raise KeyError(missing_key_error_message(key))
64
65
  value = self._query_params[key]
65
66
  if isinstance(value, list):
66
67
  if len(value) == 0:
67
68
  return ""
68
- else:
69
- # Return the last value to mimic Tornado's behavior
70
- # https://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.get_query_argument
71
- return value[-1]
69
+ # Return the last value to mimic Tornado's behavior
70
+ # https://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.get_query_argument
71
+ return value[-1]
72
72
  return value
73
73
  except KeyError:
74
74
  raise KeyError(missing_key_error_message(key))
@@ -97,9 +97,9 @@ class QueryParams(MutableMapping[str, str]):
97
97
 
98
98
  def __delitem__(self, key: str) -> None:
99
99
  self._ensure_single_query_api_used()
100
+ if key in EMBED_QUERY_PARAMS_KEYS:
101
+ raise KeyError(missing_key_error_message(key))
100
102
  try:
101
- if key in EMBED_QUERY_PARAMS_KEYS:
102
- raise KeyError(missing_key_error_message(key))
103
103
  del self._query_params[key]
104
104
  self._send_query_param_msg()
105
105
  except KeyError:
@@ -269,7 +269,14 @@ class WStates(MutableMapping[str, Any]):
269
269
 
270
270
  args = metadata.callback_args or ()
271
271
  kwargs = metadata.callback_kwargs or {}
272
- callback(*args, **kwargs)
272
+
273
+ ctx = get_script_run_ctx()
274
+ if ctx and metadata.fragment_id is not None:
275
+ ctx.in_fragment_callback = True
276
+ callback(*args, **kwargs)
277
+ ctx.in_fragment_callback = False
278
+ else:
279
+ callback(*args, **kwargs)
273
280
 
274
281
 
275
282
  def _missing_key_error_message(key: str) -> str:
streamlit/string_util.py CHANGED
@@ -72,7 +72,8 @@ def validate_emoji(maybe_emoji: str | None) -> str:
72
72
  return maybe_emoji
73
73
  else:
74
74
  raise StreamlitAPIException(
75
- f'The value "{maybe_emoji}" is not a valid emoji. Shortcodes are not allowed, please use a single character instead.'
75
+ f'The value "{maybe_emoji}" is not a valid emoji. Shortcodes are not allowed, '
76
+ "please use a single character instead."
76
77
  )
77
78
 
78
79
 
@@ -97,8 +98,9 @@ def validate_material_icon(maybe_material_icon: str | None) -> str:
97
98
 
98
99
  if not icon_match:
99
100
  raise StreamlitAPIException(
100
- f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is not a valid Material icon. '
101
- f"Please use a Material icon shortcode like **`:material{invisible_white_space}/thumb_up:`**"
101
+ f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is '
102
+ "not a valid Material icon. Please use a Material icon shortcode like "
103
+ f"**`:material{invisible_white_space}/thumb_up:`**"
102
104
  )
103
105
 
104
106
  pack_name, icon_name = icon_match.groups()
@@ -109,8 +111,9 @@ def validate_material_icon(maybe_material_icon: str | None) -> str:
109
111
  or not is_material_icon(icon_name)
110
112
  ):
111
113
  raise StreamlitAPIException(
112
- f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is not a valid Material icon.'
113
- f" Please use a Material icon shortcode like **`:material{invisible_white_space}/thumb_up:`**. "
114
+ f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is not a '
115
+ "valid Material icon. Please use a Material icon shortcode like "
116
+ f"**`:material{invisible_white_space}/thumb_up:`**."
114
117
  )
115
118
 
116
119
  return f":{pack_name}/{icon_name}:"
@@ -112,8 +112,8 @@ def _on_server_start(server: Server) -> None:
112
112
  # errors and display them here.
113
113
  try:
114
114
  secrets.load_if_toml_exists()
115
- except Exception as ex:
116
- _LOGGER.error("Failed to load secrets.toml file", exc_info=ex)
115
+ except Exception:
116
+ _LOGGER.exception("Failed to load secrets.toml file")
117
117
 
118
118
  def maybe_open_browser():
119
119
  if config.get_option("server.headless"):
streamlit/web/cli.py CHANGED
@@ -213,7 +213,8 @@ def main_run(target: str, args=None, **kwargs):
213
213
  if extension[1:] not in ACCEPTED_FILE_EXTENSIONS:
214
214
  if extension[1:] == "":
215
215
  raise click.BadArgumentUsage(
216
- "Streamlit requires raw Python (.py) files, but the provided file has no extension.\nFor more information, please see https://docs.streamlit.io"
216
+ "Streamlit requires raw Python (.py) files, but the provided file has no extension.\n"
217
+ "For more information, please see https://docs.streamlit.io"
217
218
  )
218
219
  else:
219
220
  raise click.BadArgumentUsage(
@@ -115,7 +115,8 @@ class BrowserWebSocketHandler(WebSocketHandler, SessionClient):
115
115
 
116
116
  else:
117
117
  _LOGGER.error(
118
- "Origin mismatch, the origin of websocket request is not the same origin of redirect_uri in secrets.toml",
118
+ "Origin mismatch, the origin of websocket request is not the "
119
+ "same origin of redirect_uri in secrets.toml",
119
120
  )
120
121
 
121
122
  return user_info
@@ -212,7 +213,7 @@ class BrowserWebSocketHandler(WebSocketHandler, SessionClient):
212
213
  if isinstance(payload, str):
213
214
  # Sanity check. (The frontend should only be sending us bytes;
214
215
  # Protobuf.ParseFromString does not accept str input.)
215
- raise RuntimeError(
216
+ raise TypeError( # noqa: TRY301
216
217
  "WebSocket received an unexpected `str` message. "
217
218
  "(We expect `bytes` only.)"
218
219
  )
@@ -55,9 +55,10 @@ class ComponentRequestHandler(tornado.web.RequestHandler):
55
55
  try:
56
56
  with open(abspath, "rb") as file:
57
57
  contents = file.read()
58
- except OSError as e:
59
- _LOGGER.error(
60
- "ComponentRequestHandler: GET %s read error", abspath, exc_info=e
58
+ except OSError:
59
+ sanitized_abspath = abspath.replace("\n", "").replace("\r", "")
60
+ _LOGGER.exception(
61
+ "ComponentRequestHandler: GET %s read error", sanitized_abspath
61
62
  )
62
63
  self.write("read error")
63
64
  self.set_status(404)
@@ -102,13 +103,12 @@ class ComponentRequestHandler(tornado.web.RequestHandler):
102
103
  # As of 2015-07-21 there is no bzip2 encoding defined at
103
104
  # http://www.iana.org/assignments/media-types/media-types.xhtml
104
105
  # So for that (and any other encoding), use octet-stream.
105
- elif encoding is not None:
106
+ if encoding is not None:
106
107
  return "application/octet-stream"
107
- elif mime_type is not None:
108
+ if mime_type is not None:
108
109
  return mime_type
109
110
  # if mime_type not detected, use application/octet-stream
110
- else:
111
- return "application/octet-stream"
111
+ return "application/octet-stream"
112
112
 
113
113
  @staticmethod
114
114
  def get_url(file_id: str) -> str:
@@ -87,7 +87,7 @@ class MediaFileHandler(tornado.web.StaticFileHandler):
87
87
  try:
88
88
  self._storage.get_file(absolute_path)
89
89
  except MediaFileStorageError:
90
- _LOGGER.error("MediaFileHandler: Missing file %s", absolute_path)
90
+ _LOGGER.exception("MediaFileHandler: Missing file %s", absolute_path)
91
91
  raise tornado.web.HTTPError(404, "not found")
92
92
 
93
93
  return absolute_path
@@ -121,7 +121,7 @@ class MediaFileHandler(tornado.web.StaticFileHandler):
121
121
  # abspath is the hash as used `get_absolute_path`
122
122
  media_file = cls._storage.get_file(abspath)
123
123
  except Exception:
124
- _LOGGER.error("MediaFileHandler: Missing file %s", abspath)
124
+ _LOGGER.exception("MediaFileHandler: Missing file %s", abspath)
125
125
  return None
126
126
 
127
127
  _LOGGER.debug(