17
17
except ImportError :
18
18
TEMPLATES_DIRS : Sequence [Path ] = ()
19
19
else :
20
- TEMPLATES_DIRS = tuple (mkdocstrings_handlers .__path__ ) # type: ignore[arg-type]
20
+ TEMPLATES_DIRS = tuple (mkdocstrings_handlers .__path__ )
21
21
22
22
23
23
if TYPE_CHECKING :
24
24
from jinja2 .runtime import Context
25
25
26
26
27
27
class LoggerAdapter (logging .LoggerAdapter ):
28
- """A logger adapter to prefix messages."""
28
+ """A logger adapter to prefix messages.
29
+
30
+ This adapter also adds an additional parameter to logging methods
31
+ called `once`: if `True`, the message will only be logged once.
32
+
33
+ Examples:
34
+ In Python code:
35
+
36
+ >>> logger = get_logger("myplugin")
37
+ >>> logger.debug("This is a debug message.")
38
+ >>> logger.info("This is an info message.", once=True)
39
+
40
+ In Jinja templates (logger available in context as `log`):
41
+
42
+ ```jinja
43
+ {{ log.debug("This is a debug message.") }}
44
+ {{ log.info("This is an info message.", once=True) }}
45
+ ```
46
+ """
29
47
30
48
def __init__ (self , prefix : str , logger : logging .Logger ):
31
49
"""Initialize the object.
@@ -36,6 +54,7 @@ def __init__(self, prefix: str, logger: logging.Logger):
36
54
"""
37
55
super ().__init__ (logger , {})
38
56
self .prefix = prefix
57
+ self ._logged : set [tuple [LoggerAdapter , str ]] = set ()
39
58
40
59
def process (self , msg : str , kwargs : MutableMapping [str , Any ]) -> tuple [str , Any ]:
41
60
"""Process the message.
@@ -49,11 +68,32 @@ def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> tuple[str, Any]
49
68
"""
50
69
return f"{ self .prefix } : { msg } " , kwargs
51
70
71
+ def log (self , level : int , msg : object , * args : object , ** kwargs : object ) -> None :
72
+ """Log a message.
73
+
74
+ Arguments:
75
+ level: The logging level.
76
+ msg: The message.
77
+ *args: Additional arguments passed to parent method.
78
+ **kwargs: Additional keyword arguments passed to parent method.
79
+ """
80
+ if kwargs .pop ("once" , False ):
81
+ if (key := (self , str (msg ))) in self ._logged :
82
+ return
83
+ self ._logged .add (key )
84
+ super ().log (level , msg , * args , ** kwargs ) # type: ignore[arg-type]
85
+
52
86
53
87
class TemplateLogger :
54
88
"""A wrapper class to allow logging in templates.
55
89
56
- Attributes:
90
+ The logging methods provided by this class all accept
91
+ two parameters:
92
+
93
+ - `msg`: The message to log.
94
+ - `once`: If `True`, the message will only be logged once.
95
+
96
+ Methods:
57
97
debug: Function to log a DEBUG message.
58
98
info: Function to log an INFO message.
59
99
warning: Function to log a WARNING message.
@@ -85,18 +125,19 @@ def get_template_logger_function(logger_func: Callable) -> Callable:
85
125
"""
86
126
87
127
@pass_context
88
- def wrapper (context : Context , msg : str | None = None ) -> str :
128
+ def wrapper (context : Context , msg : str | None = None , ** kwargs : Any ) -> str :
89
129
"""Log a message.
90
130
91
131
Arguments:
92
132
context: The template context, automatically provided by Jinja.
93
133
msg: The message to log.
134
+ **kwargs: Additional arguments passed to the logger function.
94
135
95
136
Returns:
96
137
An empty string.
97
138
"""
98
139
template_path = get_template_path (context )
99
- logger_func (f"{ template_path } : { msg or 'Rendering' } " )
140
+ logger_func (f"{ template_path } : { msg or 'Rendering' } " , ** kwargs )
100
141
return ""
101
142
102
143
return wrapper
0 commit comments