49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
|
from typing import Union
|
||
|
import logging
|
||
|
|
||
|
LOGGING_FORMATTER = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
|
||
|
|
||
|
|
||
|
def add_root_logger_handler(
|
||
|
logger: logging.Logger,
|
||
|
formatter: logging.Formatter = LOGGING_FORMATTER,
|
||
|
) -> None:
|
||
|
"""
|
||
|
Recursively climb logger parent tree to add handler with given formatter to
|
||
|
top level logger.
|
||
|
Will raise UserWarning if it reaches RootLogger to prevent session modification
|
||
|
|
||
|
:param logger: Logger object to find top level parent from
|
||
|
:param formatter: Formatter object to describe logging statements
|
||
|
"""
|
||
|
if isinstance(logger.parent, logging.RootLogger):
|
||
|
if len(logger.handlers) == 0:
|
||
|
handler = logging.StreamHandler()
|
||
|
handler.setFormatter(formatter)
|
||
|
logger.addHandler(handler)
|
||
|
elif isinstance(logger, logging.RootLogger) or logger.parent is None:
|
||
|
raise UserWarning(
|
||
|
"Failure in add_root_logger_handler, "
|
||
|
"protecting root logger from modification"
|
||
|
)
|
||
|
else:
|
||
|
add_root_logger_handler(logger=logger.parent, formatter=formatter)
|
||
|
|
||
|
class AbstractLoggingClass:
|
||
|
"""
|
||
|
Base class to ensure logging is setup
|
||
|
"""
|
||
|
|
||
|
def __init__(self, loglevel: Union[int, str] = logging.WARNING) -> None:
|
||
|
"""
|
||
|
Set up logging and fetch class level logger for use by subclasses
|
||
|
|
||
|
:param loglevel: Verbosity of logging statements
|
||
|
"""
|
||
|
module_logger = logging.getLogger(self.__class__.__module__)
|
||
|
add_root_logger_handler(module_logger)
|
||
|
self.logger = module_logger.getChild(self.__class__.__name__)
|
||
|
if loglevel is not None:
|
||
|
self.logger.setLevel(loglevel)
|
||
|
|