stouputils.ctx.muffle module#

class ErrorLevelDetector(level: int)[source]#

Bases: Handler

Logging handler that only remembers whether a record at/above its level was emitted.

Used by Muffle to decide whether captured output should be replayed, since some libraries log their failures instead of raising.

triggered: bool[source]#

Whether a record at/above the configured level has been seen

class Muffle(
mute_stderr: bool = False,
replay_on_error: bool = False,
error_log_level: int | None = None,
watch_loggers: Sequence[str] | None = None,
)[source]#

Bases: AbstractBothContextManager[Muffle]

Context manager that temporarily silences output. (No thread-safety guaranteed)

Alternative to @silent

By default the output is sent to devnull and lost. When replay_on_error is enabled, the output is captured in memory instead and only written back to the original stream if an error occurs inside the block. An “error” is either an exception propagating out of the block, or - when error_log_level is set - any logging record at/above that level emitted by the watched loggers (handy for libraries that log their failures instead of raising).

Parameters:
  • mute_stderr (bool) – Whether to mute stderr as well as stdout

  • replay_on_error (bool) – Capture output in memory and replay it if an error occurs

  • error_log_level (int | None) – Also treat log records at/above this level as an error (e.g. logging.ERROR)

  • watch_loggers (Sequence[str] | None) – Names of the loggers to watch for error_log_level (default: root logger only)

Examples

>>> with Muffle():
...     print("This will not be printed")
>>> # Replays the captured output because an exception escapes the block
>>> try:
...     with Muffle(replay_on_error=True):
...         print("Context that explains the failure below")
...         raise ValueError("boom")
... except ValueError:
...     pass
Context that explains the failure below
>>> # Stays silent because nothing went wrong
>>> import logging
>>> with Muffle(replay_on_error=True, error_log_level=logging.ERROR):
...     print("This will not be printed")
mute_stderr: bool[source]#

Attribute remembering if stderr should be muted

replay_on_error: bool[source]#

Attribute remembering if captured output should be replayed on error

error_log_level: int | None[source]#

Attribute remembering the logging level that counts as an error (if any)

watch_loggers: Sequence[str] | None[source]#

Attribute remembering which loggers to watch for error records

original_stdout: IO[Any][source]#

Attribute remembering original stdout

original_stderr: IO[Any][source]#

Attribute remembering original stderr

_abc_impl = <_abc._abc_data object>[source]#
_buffer: StringIO | None[source]#

In-memory buffer holding captured output when replay_on_error is enabled

_detector: ErrorLevelDetector | None[source]#

Logging handler watching for error-level records

_watched: list[Logger][source]#

Loggers the detector is currently attached to

static write_safely(
stream: IO[Any],
text: str,
) None[source]#

Write text to a stream, replacing characters the stream’s encoding cannot represent.

Captured output may contain unicode (e.g. Rich panels) that a narrow console encoding (such as cp1252 on Windows) cannot encode, which would otherwise raise UnicodeEncodeError.