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 – Whether to mute stderr as well as stdout

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

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

  • watch_loggers – Names of the loggers to watch for error_log_level (default: root logger only)

>>> 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

_buffer: StringIO | None[source]#

In-memory buffer holding captured output when replay_on_error is enabled

_devnull: IO[Any] | None[source]#

Sink swallowing the output when replay_on_error is disabled, closed on exit

_abc_impl = <_abc._abc_data object>[source]#
_detector: ErrorLevelDetector | None[source]#

Logging handler watching for error-level records

_watched: list[Logger][source]#

Loggers the detector is currently attached to

attach_detector(level: int) → None[source]#

Watch the loggers for records at level or above, so a failure that is only logged also replays the output.

detach_detector() → bool[source]#

Stop watching the loggers.

Returns:

Whether a record at the watched level was logged meanwhile.

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.