Coverage for src/markdown_exec/logger.py: 75.00%

20 statements  

« prev     ^ index     » next       coverage.py v7.2.3, created at 2023-04-16 20:19 +0200

1"""This module contains logging utilities. 

2 

3We provide the [`patch_loggers`][markdown_exec.logger.patch_loggers] 

4function so dependant libraries can patch loggers as they see fit. 

5 

6For example, to fit in the MkDocs logging configuration 

7and prefix each log message with the module name: 

8 

9```python 

10import logging 

11from markdown_exec.logger import patch_loggers 

12 

13 

14class LoggerAdapter(logging.LoggerAdapter): 

15 def __init__(self, prefix, logger): 

16 super().__init__(logger, {}) 

17 self.prefix = prefix 

18 

19 def process(self, msg, kwargs): 

20 return f"{self.prefix}: {msg}", kwargs 

21 

22 

23def get_logger(name): 

24 logger = logging.getLogger(f"mkdocs.plugins.{name}") 

25 return LoggerAdapter(name.split(".", 1)[0], logger) 

26 

27 

28patch_loggers(get_logger) 

29``` 

30""" 

31 

32from __future__ import annotations 

33 

34import logging 

35from typing import Any, Callable 

36 

37 

38class _Logger: 

39 _default_logger: Any = logging.getLogger 

40 _instances: dict[str, _Logger] = {} 

41 

42 def __init__(self, name: str) -> None: 

43 # default logger that can be patched by third-party 

44 self._logger = self.__class__._default_logger(name) 

45 # register instance 

46 self._instances[name] = self 

47 

48 def __getattr__(self, name: str) -> Any: 

49 # forward everything to the logger 

50 return getattr(self._logger, name) 

51 

52 @classmethod 

53 def _patch_loggers(cls, get_logger_func: Callable) -> None: 

54 # patch current instances 

55 for name, instance in cls._instances.items(): 

56 instance._logger = get_logger_func(name) 

57 # future instances will be patched as well 

58 cls._default_logger = get_logger_func 

59 

60 

61def get_logger(name: str) -> _Logger: 

62 """Create and return a new logger instance. 

63 

64 Parameters: 

65 name: The logger name. 

66 

67 Returns: 

68 The logger. 

69 """ 

70 return _Logger(name) 

71 

72 

73def patch_loggers(get_logger_func: Callable[[str], Any]) -> None: 

74 """Patch loggers. 

75 

76 Parameters: 

77 get_logger_func: A function accepting a name as parameter and returning a logger. 

78 """ 

79 _Logger._patch_loggers(get_logger_func)