From 1d5d3d3bcd2b041d0d3084076a863d2b19f179db Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Tue, 30 Apr 2024 10:27:10 +0200 Subject: [PATCH] Add util.logging.FallbackHandler --- CHANGELOG.md | 1 + src/sensai/util/logging.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfe0639d..a7712b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ * Add line number to default format (`LOG_DEFAULT_FORMAT`) * Add function `is_enabled` to check whether a log handler is registered * Add context manager `LoggingDisabledContext` to temporarily disable logging + * Add `FallbackHandler` to support logging to a fallback destination (if no other handlers are defined) * `util.io`: * `ResultWriter`: * Allow to disable an instance such that no results are written (constructor parameter `enabled`) diff --git a/src/sensai/util/logging.py b/src/sensai/util/logging.py index 901ac4db..d09330ad 100644 --- a/src/sensai/util/logging.py +++ b/src/sensai/util/logging.py @@ -361,3 +361,23 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, traceback): lg.disable(self._previous_level) + + +# noinspection PyShadowingBuiltins +class FallbackHandler(Handler): + """ + A log handler which applies the given handler only if the root logger has no defined handlers (or no handlers other than + this fallback handler itself) + """ + def __init__(self, handler: Handler, level=NOTSET): + """ + :param handler: the handler to which messages shall be passed on + :param level: the minimum level to output; if NOTSET, pass on everything + """ + super().__init__(level=level) + self._handler = handler + + def emit(self, record): + root_handlers = getLogger().handlers + if len(root_handlers) == 0 or (len(root_handlers) == 1 and root_handlers[0] == self): + self._handler.emit(record)