64
64
65
65
try :
66
66
# pylint: disable=deprecated-class
67
- from typing import Optional , Hashable
67
+ from typing import Optional , Hashable , Dict
68
68
from typing_extensions import Protocol
69
69
70
70
class WriteableStream (Protocol ):
@@ -148,12 +148,85 @@ def _logRecordFactory(name, level, msg, args):
148
148
return LogRecord (name , level , _level_for (level ), msg , time .monotonic (), args )
149
149
150
150
151
+ class Formatter :
152
+ """
153
+ Responsible for converting a LogRecord to an output string to be
154
+ interpreted by a human or external system.
155
+
156
+ Only implements a sub-set of CPython logging.Formatter behavior,
157
+ but retains all the same arguments in order to match the API.
158
+
159
+ The only init arguments currently supported are: fmt, defaults and
160
+ style. All others are currently ignored
161
+
162
+ The only two styles currently supported are '%' and '{'. The default
163
+ style is '{'
164
+ """
165
+
166
+ def __init__ ( # pylint: disable=too-many-arguments
167
+ self ,
168
+ fmt : Optional [str ] = None ,
169
+ datefmt : Optional [str ] = None ,
170
+ style : str = "%" ,
171
+ validate : bool = True ,
172
+ defaults : Dict = None ,
173
+ ):
174
+ self .fmt = fmt
175
+ self .datefmt = datefmt
176
+ self .style = style
177
+ if self .style not in ("{" , "%" ):
178
+ raise ValueError (
179
+ "Only '%' and '{' formatting style are supported at this time."
180
+ )
181
+
182
+ self .validate = validate
183
+ self .defaults = defaults
184
+
185
+ def format (self , record : LogRecord ) -> str :
186
+ """
187
+ Format the given LogRecord into an output string
188
+ """
189
+ if self .fmt is None :
190
+ return record .msg
191
+
192
+ vals = {
193
+ "name" : record .name ,
194
+ "levelno" : record .levelno ,
195
+ "levelname" : record .levelname ,
196
+ "message" : record .msg ,
197
+ "created" : record .created ,
198
+ "args" : record .args ,
199
+ }
200
+ if "{asctime}" in self .fmt or "%(asctime)s" in self .fmt :
201
+ now = time .localtime ()
202
+ # pylint: disable=line-too-long
203
+ vals [
204
+ "asctime"
205
+ ] = f"{ now .tm_year } -{ now .tm_mon :02d} -{ now .tm_mday :02d} { now .tm_hour :02d} :{ now .tm_min :02d} :{ now .tm_sec :02d} "
206
+
207
+ if self .defaults :
208
+ for key , val in self .defaults .items ():
209
+ if key not in vals :
210
+ vals [key ] = val
211
+
212
+ if self .style not in ("{" , "%" ):
213
+ raise ValueError (
214
+ "Only '%' and '{' formatting style are supported at this time."
215
+ )
216
+
217
+ if self .style == "%" :
218
+ return self .fmt % vals
219
+
220
+ return self .fmt .format (** vals )
221
+
222
+
151
223
class Handler :
152
224
"""Base logging message handler."""
153
225
154
226
def __init__ (self , level : int = NOTSET ) -> None :
155
227
"""Create Handler instance"""
156
228
self .level = level
229
+ self .formatter = None
157
230
158
231
def setLevel (self , level : int ) -> None :
159
232
"""
@@ -167,7 +240,8 @@ def format(self, record: LogRecord) -> str:
167
240
168
241
:param record: The record (message object) to be logged
169
242
"""
170
-
243
+ if self .formatter :
244
+ return self .formatter .format (record )
171
245
return f"{ record .created :<0.3f} : { record .levelname } - { record .msg } "
172
246
173
247
def emit (self , record : LogRecord ) -> None :
@@ -182,6 +256,12 @@ def emit(self, record: LogRecord) -> None:
182
256
def flush (self ) -> None :
183
257
"""Placeholder for flush function in subclasses."""
184
258
259
+ def setFormatter (self , formatter : Formatter ) -> None :
260
+ """
261
+ Set the Formatter to be used by this Handler.
262
+ """
263
+ self .formatter = formatter
264
+
185
265
186
266
# pylint: disable=too-few-public-methods
187
267
class StreamHandler (Handler ):
0 commit comments