edq.core.log
1import argparse 2import logging 3import typing 4 5_logger = logging.getLogger(__name__) 6 7DEFAULT_LOGGING_LEVEL: str = logging.getLevelName(logging.INFO) 8DEFAULT_LOGGING_FORMAT: str = '%(asctime)s [%(levelname)-8s] - %(filename)s:%(lineno)s -- %(message)s' 9 10LEVELS: typing.List[str] = [ 11 'TRACE', 12 logging.getLevelName(logging.DEBUG), 13 logging.getLevelName(logging.INFO), 14 logging.getLevelName(logging.WARNING), 15 logging.getLevelName(logging.ERROR), 16 logging.getLevelName(logging.CRITICAL), 17] 18 19def init(level: str = DEFAULT_LOGGING_LEVEL, log_format: str = DEFAULT_LOGGING_FORMAT, 20 warn_loggers: typing.Union[typing.List[str], None] = None, 21 **kwargs: typing.Any) -> None: 22 """ 23 Initialize or re-initialize the logging infrastructure. 24 The list of warning loggers is a list of identifiers for loggers (usually third-party) to move up to warning on init. 25 """ 26 27 # Add trace. 28 _add_logging_level('TRACE', logging.DEBUG - 5) 29 30 logging.basicConfig(level = level, format = log_format, force = True) 31 32 if (warn_loggers is not None): 33 for warn_logger in warn_loggers: 34 logging.getLogger(warn_logger).setLevel(logging.WARNING) 35 36 _logger.trace("Logging initialized with level '%s'.", level) # type: ignore[attr-defined] 37 38def set_cli_args(parser: argparse.ArgumentParser, extra_state: typing.Dict[str, typing.Any]) -> None: 39 """ 40 Set common CLI arguments. 41 This is a sibling to init_from_args(), as the arguments set here can be interpreted there. 42 """ 43 44 group = parser.add_argument_group('logging options') 45 46 group.add_argument('--debug', dest = 'debug', 47 action = 'store_true', default = False, 48 help = 'Set the logging level to debug (overrides --log-level and --quiet) (default: %(default)s).') 49 50 group.add_argument('--log-level', dest = 'log_level', 51 action = 'store', type = str, default = logging.getLevelName(logging.INFO), 52 choices = LEVELS, 53 help = 'Set the logging level (default: %(default)s).') 54 55 group.add_argument('--quiet', dest = 'quiet', 56 action = 'store_true', default = False, 57 help = 'Set the logging level to warning (overrides --log-level) (default: %(default)s).') 58 59def init_from_args( 60 parser: argparse.ArgumentParser, 61 args: argparse.Namespace, 62 extra_state: typing.Dict[str, typing.Any]) -> None: 63 """ 64 Take in args from a parser that was passed to set_cli_args(), 65 and call init() with the appropriate arguments. 66 """ 67 68 level = args.log_level 69 70 if (args.quiet): 71 level = logging.getLevelName(logging.WARNING) 72 73 if (args.debug): 74 level = logging.getLevelName(logging.DEBUG) 75 76 init(level) 77 78def _add_logging_level(level_name: str, level_number: int, method_name: typing.Union[str, None] = None) -> None: 79 """ 80 Add a new logging level. 81 82 See https://stackoverflow.com/questions/2183233/how-to-add-a-custom-loglevel-to-pythons-logging-facility/35804945#35804945 . 83 """ 84 85 if (method_name is None): 86 method_name = level_name.lower() 87 88 # Level has already been defined. 89 if hasattr(logging, level_name): 90 return 91 92 def log_for_level(self: typing.Any, message: str, *args: typing.Any, **kwargs: typing.Any) -> None: 93 if self.isEnabledFor(level_number): 94 self._log(level_number, message, args, **kwargs) 95 96 def log_to_root(message: str, *args: typing.Any, **kwargs: typing.Any) -> None: 97 logging.log(level_number, message, *args, **kwargs) 98 99 logging.addLevelName(level_number, level_name) 100 setattr(logging, level_name, level_number) 101 setattr(logging.getLoggerClass(), method_name, log_for_level) 102 setattr(logging, method_name, log_to_root) 103 104# Load the default logging when this module is loaded. 105init()
DEFAULT_LOGGING_LEVEL: str =
'INFO'
DEFAULT_LOGGING_FORMAT: str =
'%(asctime)s [%(levelname)-8s] - %(filename)s:%(lineno)s -- %(message)s'
LEVELS: List[str] =
['TRACE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
def
init( level: str = 'INFO', log_format: str = '%(asctime)s [%(levelname)-8s] - %(filename)s:%(lineno)s -- %(message)s', warn_loggers: Optional[List[str]] = None, **kwargs: Any) -> None:
20def init(level: str = DEFAULT_LOGGING_LEVEL, log_format: str = DEFAULT_LOGGING_FORMAT, 21 warn_loggers: typing.Union[typing.List[str], None] = None, 22 **kwargs: typing.Any) -> None: 23 """ 24 Initialize or re-initialize the logging infrastructure. 25 The list of warning loggers is a list of identifiers for loggers (usually third-party) to move up to warning on init. 26 """ 27 28 # Add trace. 29 _add_logging_level('TRACE', logging.DEBUG - 5) 30 31 logging.basicConfig(level = level, format = log_format, force = True) 32 33 if (warn_loggers is not None): 34 for warn_logger in warn_loggers: 35 logging.getLogger(warn_logger).setLevel(logging.WARNING) 36 37 _logger.trace("Logging initialized with level '%s'.", level) # type: ignore[attr-defined]
Initialize or re-initialize the logging infrastructure. The list of warning loggers is a list of identifiers for loggers (usually third-party) to move up to warning on init.
def
set_cli_args(parser: argparse.ArgumentParser, extra_state: Dict[str, Any]) -> None:
39def set_cli_args(parser: argparse.ArgumentParser, extra_state: typing.Dict[str, typing.Any]) -> None: 40 """ 41 Set common CLI arguments. 42 This is a sibling to init_from_args(), as the arguments set here can be interpreted there. 43 """ 44 45 group = parser.add_argument_group('logging options') 46 47 group.add_argument('--debug', dest = 'debug', 48 action = 'store_true', default = False, 49 help = 'Set the logging level to debug (overrides --log-level and --quiet) (default: %(default)s).') 50 51 group.add_argument('--log-level', dest = 'log_level', 52 action = 'store', type = str, default = logging.getLevelName(logging.INFO), 53 choices = LEVELS, 54 help = 'Set the logging level (default: %(default)s).') 55 56 group.add_argument('--quiet', dest = 'quiet', 57 action = 'store_true', default = False, 58 help = 'Set the logging level to warning (overrides --log-level) (default: %(default)s).')
Set common CLI arguments. This is a sibling to init_from_args(), as the arguments set here can be interpreted there.
def
init_from_args( parser: argparse.ArgumentParser, args: argparse.Namespace, extra_state: Dict[str, Any]) -> None:
60def init_from_args( 61 parser: argparse.ArgumentParser, 62 args: argparse.Namespace, 63 extra_state: typing.Dict[str, typing.Any]) -> None: 64 """ 65 Take in args from a parser that was passed to set_cli_args(), 66 and call init() with the appropriate arguments. 67 """ 68 69 level = args.log_level 70 71 if (args.quiet): 72 level = logging.getLevelName(logging.WARNING) 73 74 if (args.debug): 75 level = logging.getLevelName(logging.DEBUG) 76 77 init(level)
Take in args from a parser that was passed to set_cli_args(), and call init() with the appropriate arguments.