@@ -52,13 +52,15 @@ class BaseRotatingHandler(logging.FileHandler):
5252 Not meant to be instantiated directly. Instead, use RotatingFileHandler
5353 or TimedRotatingFileHandler.
5454 """
55- def __init__ (self , filename , mode , encoding = None , delay = 0 ):
55+ def __init__ (self , filename , mode , encoding = None , delay = False ):
5656 """
5757 Use the specified filename for streamed logging
5858 """
5959 logging .FileHandler .__init__ (self , filename , mode , encoding , delay )
6060 self .mode = mode
6161 self .encoding = encoding
62+ self .namer = None
63+ self .rotator = None
6264
6365 def emit (self , record ):
6466 """
@@ -76,12 +78,50 @@ def emit(self, record):
7678 except :
7779 self .handleError (record )
7880
81+ def rotation_filename (self , default_name ):
82+ """
83+ Modify the filename of a log file when rotating.
84+
85+ This is provided so that a custom filename can be provided.
86+
87+ The default implementation calls the 'namer' attribute of the
88+ handler, if it's callable, passing the default name to
89+ it. If the attribute isn't callable (the default is None), the name
90+ is returned unchanged.
91+
92+ :param default_name: The default name for the log file.
93+ """
94+ if not callable (self .namer ):
95+ result = default_name
96+ else :
97+ result = self .namer (default_name )
98+ return result
99+
100+ def rotate (self , source , dest ):
101+ """
102+ When rotating, rotate the current log.
103+
104+ The default implementation calls the 'rotator' attribute of the
105+ handler, if it's callable, passing the source and dest arguments to
106+ it. If the attribute isn't callable (the default is None), the source
107+ is simply renamed to the destination.
108+
109+ :param source: The source filename. This is normally the base
110+ filename, e.g. 'test.log'
111+ :param dest: The destination filename. This is normally
112+ what the source is rotated to, e.g. 'test.log.1'.
113+ """
114+ if not callable (self .rotator ):
115+ os .rename (source , dest )
116+ else :
117+ self .rotator (source , dest )
118+
79119class RotatingFileHandler (BaseRotatingHandler ):
80120 """
81121 Handler for logging to a set of files, which switches from one file
82122 to the next when the current file reaches a certain size.
83123 """
84- def __init__ (self , filename , mode = 'a' , maxBytes = 0 , backupCount = 0 , encoding = None , delay = 0 ):
124+ def __init__ (self , filename , mode = 'a' , maxBytes = 0 , backupCount = 0 , encoding = None , delay = False ):
85125 """
86126 Open the specified file and use it as the stream for logging.
87127
@@ -122,16 +162,17 @@ def doRollover(self):
122162 self .stream = None
123163 if self .backupCount > 0 :
124164 for i in range (self .backupCount - 1 , 0 , - 1 ):
125- sfn = "%s.%d" % (self .baseFilename , i )
126- dfn = "%s.%d" % (self .baseFilename , i + 1 )
165+ sfn = self .rotation_filename ("%s.%d" % (self .baseFilename , i ))
166+ dfn = self .rotation_filename ("%s.%d" % (self .baseFilename ,
167+ i + 1 ))
127168 if os .path .exists (sfn ):
128169 if os .path .exists (dfn ):
129170 os .remove (dfn )
130171 os .rename (sfn , dfn )
131- dfn = self .baseFilename + ".1"
172+ dfn = self .rotation_filename ( self . baseFilename + ".1" )
132173 if os .path .exists (dfn ):
133174 os .remove (dfn )
134- os . rename (self .baseFilename , dfn )
175+ self . rotate (self .baseFilename , dfn )
135176 self .mode = 'w'
136177 self .stream = self ._open ()
137178
@@ -179,19 +220,19 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None,
179220 if self .when == 'S' :
180221 self .interval = 1 # one second
181222 self .suffix = "%Y-%m-%d_%H-%M-%S"
182- self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$"
223+ self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)? $"
183224 elif self .when == 'M' :
184225 self .interval = 60 # one minute
185226 self .suffix = "%Y-%m-%d_%H-%M"
186- self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$"
227+ self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}(\.\w+)? $"
187228 elif self .when == 'H' :
188229 self .interval = 60 * 60 # one hour
189230 self .suffix = "%Y-%m-%d_%H"
190- self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$"
231+ self .extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}(\.\w+)? $"
191232 elif self .when == 'D' or self .when == 'MIDNIGHT' :
192233 self .interval = 60 * 60 * 24 # one day
193234 self .suffix = "%Y-%m-%d"
194- self .extMatch = r"^\d{4}-\d{2}-\d{2}$"
235+ self .extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)? $"
195236 elif self .when .startswith ('W' ):
196237 self .interval = 60 * 60 * 24 * 7 # one week
197238 if len (self .when ) != 2 :
@@ -200,7 +241,7 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None,
200241 raise ValueError ("Invalid day specified for weekly rollover: %s" % self .when )
201242 self .dayOfWeek = int (self .when [1 ])
202243 self .suffix = "%Y-%m-%d"
203- self .extMatch = r"^\d{4}-\d{2}-\d{2}$"
244+ self .extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)? $"
204245 else :
205246 raise ValueError ("Invalid rollover interval specified: %s" % self .when )
206247
@@ -323,10 +364,11 @@ def doRollover(self):
323364 timeTuple = time .gmtime (t )
324365 else :
325366 timeTuple = time .localtime (t )
326- dfn = self .baseFilename + "." + time .strftime (self .suffix , timeTuple )
367+ dfn = self .rotation_filename (self .baseFilename + "." +
368+ time .strftime (self .suffix , timeTuple ))
327369 if os .path .exists (dfn ):
328370 os .remove (dfn )
329- os . rename (self .baseFilename , dfn )
371+ self . rotate (self .baseFilename , dfn )
330372 if self .backupCount > 0 :
331373 for s in self .getFilesToDelete ():
332374 os .remove (s )
@@ -367,7 +409,7 @@ class WatchedFileHandler(logging.FileHandler):
367409 This handler is based on a suggestion and patch by Chad J.
368410 Schroeder.
369411 """
370- def __init__ (self , filename , mode = 'a' , encoding = None , delay = 0 ):
412+ def __init__ (self , filename , mode = 'a' , encoding = None , delay = False ):
371413 logging .FileHandler .__init__ (self , filename , mode , encoding , delay )
372414 if not os .path .exists (self .baseFilename ):
373415 self .dev , self .ino = - 1 , - 1
0 commit comments