diff --git a/src/corelibs/logging_handling/log.py b/src/corelibs/logging_handling/log.py index bc5b32b..105bc9a 100644 --- a/src/corelibs/logging_handling/log.py +++ b/src/corelibs/logging_handling/log.py @@ -392,6 +392,24 @@ class LogParent: except IndexError: return LoggingLevel.NOTSET + def any_handler_is_minimum_level(self, log_level: LoggingLevel) -> bool: + """ + if any handler is set to minimum level + + Arguments: + log_level {LoggingLevel} -- _description_ + + Returns: + bool -- _description_ + """ + for handler in self.handlers.values(): + try: + if LoggingLevel.from_any(handler.level).includes(log_level): + return True + except (IndexError, AttributeError): + continue + return False + @staticmethod def validate_log_level(log_level: Any) -> bool: """ diff --git a/test-run/logging_handling/log.py b/test-run/logging_handling/log.py index e1bd095..34268d2 100644 --- a/test-run/logging_handling/log.py +++ b/test-run/logging_handling/log.py @@ -108,6 +108,16 @@ def main(): log.set_log_level(Log.CONSOLE_HANDLER, LoggingLevel.ERROR) log.logger.warning('[NORMAL] Invisible Warning test: %s', log.logger.name) log.logger.error('[NORMAL] Visible Error test: %s', log.logger.name) + log.logger.debug('[NORMAL] Visible Debug test: %s', log.logger.name) + print(f"*** Any handler is minimum level ERROR: {log.any_handler_is_minimum_level(LoggingLevel.ERROR)}") + print(f"*** Any handler is minimum level DEBUG: {log.any_handler_is_minimum_level(LoggingLevel.DEBUG)}") + for handler in log.handlers.values(): + print( + f"*** Setting handler {handler} is level {LoggingLevel.from_any(handler.level).name} -> " + f"*** INC {LoggingLevel.from_any(handler.level).includes(LoggingLevel.DEBUG)}") + + print(f"*** WARNING includes ERROR: {LoggingLevel.WARNING.includes(LoggingLevel.ERROR)}") + print(f"*** ERROR includes WARNING: {LoggingLevel.ERROR.includes(LoggingLevel.WARNING)}") log.set_log_level(Log.CONSOLE_HANDLER, LoggingLevel.DEBUG) log.debug('Current logging format: %s', log.log_settings['console_format_type']) @@ -115,6 +125,8 @@ def main(): log.info('Does hit show less') log.update_console_formatter(ConsoleFormat.TIME | ConsoleFormat.LINENO) log.info('Does hit show less B') + print(f"*** Any handler is minimum level ERROR: {log.any_handler_is_minimum_level(LoggingLevel.ERROR)}") + print(f"*** Any handler is minimum level DEBUG: {log.any_handler_is_minimum_level(LoggingLevel.DEBUG)}") if __name__ == "__main__": diff --git a/tests/unit/logging_handling/log_testing/test_log_2_basic_handling.py b/tests/unit/logging_handling/log_testing/test_log_2_basic_handling.py index faf0ce5..d4baa6f 100644 --- a/tests/unit/logging_handling/log_testing/test_log_2_basic_handling.py +++ b/tests/unit/logging_handling/log_testing/test_log_2_basic_handling.py @@ -438,4 +438,81 @@ class TestLogLevelHandling: level = log_instance.get_log_level("file_handler") assert level == LoggingLevel.DEBUG + +class DummyHandler: + """Dummy log level handler""" + def __init__(self, level: LoggingLevel): + self.level = level + + +@pytest.fixture +def log_instance_level() -> Log: + """ + Minimal log instance with dummy handlers + + Returns: + Log -- _description_ + """ + log = Log( + log_path=Path("/tmp/test.log"), + log_name="test", + log_settings={ + "log_level_console": LoggingLevel.DEBUG, + "log_level_file": LoggingLevel.DEBUG, + "console_enabled": False, + "console_color_output_enabled": False, + "console_format_type": None, + "per_run_log": False, + "add_start_info": False, + "add_end_info": False, + "log_queue": None, + } + ) + return log + + +def test_any_handler_is_minimum_level_true(log_instance_level: Log): + """Test any_handler_is_minimum_level returns True when a handler meets the level""" + # Handler with DEBUG level, should include INFO + log_instance_level.handlers = { + "h1": DummyHandler(LoggingLevel.DEBUG) + } + assert log_instance_level.any_handler_is_minimum_level(LoggingLevel.INFO) is True + + +def test_any_handler_is_minimum_level_false(log_instance_level: Log): + """Test any_handler_is_minimum_level returns False when no handler meets the level""" + # Handler with WARNING level, should include ERROR + log_instance_level.handlers = { + "h1": DummyHandler(LoggingLevel.WARNING) + } + assert log_instance_level.any_handler_is_minimum_level(LoggingLevel.ERROR) is True + + +def test_any_handler_is_minimum_level_multiple(log_instance_level: Log): + """Test any_handler_is_minimum_level with multiple handlers""" + # Multiple handlers, one matches + log_instance_level.handlers = { + "h1": DummyHandler(LoggingLevel.ERROR), + "h2": DummyHandler(LoggingLevel.DEBUG) + } + assert log_instance_level.any_handler_is_minimum_level(LoggingLevel.INFO) is True + # None matches + log_instance_level.handlers = { + "h1": DummyHandler(LoggingLevel.ERROR), + "h2": DummyHandler(LoggingLevel.CRITICAL) + } + assert log_instance_level.any_handler_is_minimum_level(LoggingLevel.DEBUG) is False + + +def test_any_handler_is_minimum_level_handles_exceptions(log_instance_level: Log): + """Test any_handler_is_minimum_level handles exceptions gracefully""" + # Handler with missing level attribute + class BadHandler: + pass + log_instance_level.handlers = { + "h1": BadHandler() + } + # Should not raise, just return False + assert log_instance_level.any_handler_is_minimum_level(LoggingLevel.DEBUG) is False # __END__