From ea05e925358f8daef3d7aaa7ddf754206cb7271b Mon Sep 17 00:00:00 2001 From: Dave Astels Date: Thu, 4 Mar 2021 15:32:48 -0500 Subject: [PATCH 1/3] Add a NullLogger class for efficient disabling of logging This implements the "Null Object" pattern. It allows logging to be completely and efficiently disabled without having to sprinkle "if logger" guards on every logger call (which can be error prone during maintenance). --- adafruit_logging.py | 52 ++++++++++++++++++++++++++++++---- examples/logging_simpletest.py | 18 ++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/adafruit_logging.py b/adafruit_logging.py index e9f7c4b..bb08e1f 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -95,14 +95,22 @@ def emit(self, level, msg): # pylint:disable=undefined-variable logger_cache = dict() +null_logger = None def getLogger(name): + global null_logger """Create or retrieve a logger by name. - :param name: the name of the logger to create/retrieve + :param name: the name of the logger to create/retrieve None will cause the + NullLogger instance to be returned. """ + if not name or name == "": + if not null_logger: + null_logger = NullLogger() + return null_logger + if name not in logger_cache: logger_cache[name] = Logger() return logger_cache[name] @@ -112,11 +120,7 @@ class Logger: """Provide a logging api.""" def __init__(self): - """Create an instance. - - :param handler: what to use to output messages. Defaults to a PrintHandler. - - """ + """Create an instance.""" self._level = NOTSET self._handler = PrintHandler() @@ -201,3 +205,39 @@ def critical(self, format_string, *args): """ self.log(CRITICAL, format_string, *args) + + +class NullLogger: + """Provide an empty logger. + This can be used in place of a real logger to more efficiently disable logging.""" + + def __init__(self): + """Dummy implementation.""" + + def setLevel(self, value): + """Dummy implementation.""" + + def getEffectiveLevel(self): + """Dummy implementation.""" + return NOTSET + + def addHandler(self, hldr): + """Dummy implementation.""" + + def log(self, level, format_string, *args): + """Dummy implementation.""" + + def debug(self, format_string, *args): + """Dummy implementation.""" + + def info(self, format_string, *args): + """Dummy implementation.""" + + def warning(self, format_string, *args): + """Dummy implementation.""" + + def error(self, format_string, *args): + """Dummy implementation.""" + + def critical(self, format_string, *args): + """Dummy implementation.""" diff --git a/examples/logging_simpletest.py b/examples/logging_simpletest.py index c5ac6c2..d7205dd 100644 --- a/examples/logging_simpletest.py +++ b/examples/logging_simpletest.py @@ -6,8 +6,26 @@ import adafruit_logging as logging +# This should produce an error output + logger = logging.getLogger("test") logger.setLevel(logging.ERROR) logger.info("Info message") logger.error("Error message") + +# This should produce no output + +null_logger = logging.getLogger(None) + +null_logger.setLevel(logging.ERROR) +null_logger.info("Info message") +null_logger.error("Error message") + +# This should produce no output + +null_logger = logging.getLogger("") + +null_logger.setLevel(logging.ERROR) +null_logger.info("Info message") +null_logger.error("Error message") From 377a5d8038bc730aa976dd477d929c102d4c8d14 Mon Sep 17 00:00:00 2001 From: Dave Astels Date: Thu, 4 Mar 2021 15:34:49 -0500 Subject: [PATCH 2/3] Pylint tweaks for the global manipulation --- adafruit_logging.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/adafruit_logging.py b/adafruit_logging.py index bb08e1f..a095315 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -97,15 +97,15 @@ def emit(self, level, msg): logger_cache = dict() null_logger = None - +# pylint:disable=global-statement def getLogger(name): - global null_logger """Create or retrieve a logger by name. :param name: the name of the logger to create/retrieve None will cause the NullLogger instance to be returned. """ + global null_logger if not name or name == "": if not null_logger: null_logger = NullLogger() @@ -116,6 +116,9 @@ def getLogger(name): return logger_cache[name] +# pylint:enable=global-statement + + class Logger: """Provide a logging api.""" From 055a8c030563571ba9c45de627da82250ec269ad Mon Sep 17 00:00:00 2001 From: Dave Astels Date: Thu, 4 Mar 2021 15:37:46 -0500 Subject: [PATCH 3/3] Make pylint happy --- examples/logging_simpletest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/logging_simpletest.py b/examples/logging_simpletest.py index d7205dd..3286bce 100644 --- a/examples/logging_simpletest.py +++ b/examples/logging_simpletest.py @@ -2,7 +2,9 @@ # SPDX-License-Identifier: MIT # pylint:disable=undefined-variable,wildcard-import,no-name-in-module -# pylint:disable=no-member +# pylint:disable=no-member,invalid-name + +"""Briefly exercise the logger and null logger.""" import adafruit_logging as logging