mirror of https://github.com/python/cpython
Closed #9556: Allowed specifying a time-of-day for a TimedRotatingFileHandler to rotate.
This commit is contained in:
parent
8a9e38e715
commit
a713079ed8
|
@ -296,7 +296,7 @@ The :class:`TimedRotatingFileHandler` class, located in the
|
|||
timed intervals.
|
||||
|
||||
|
||||
.. class:: TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)
|
||||
.. class:: TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)
|
||||
|
||||
Returns a new instance of the :class:`TimedRotatingFileHandler` class. The
|
||||
specified file is opened and used as the stream for logging. On rotating it also
|
||||
|
@ -346,6 +346,12 @@ timed intervals.
|
|||
If *delay* is true, then file opening is deferred until the first call to
|
||||
:meth:`emit`.
|
||||
|
||||
If *atTime* is not ``None``, it must be a ``datetime.time`` instance which
|
||||
specifies the time of day when rollover occurs, for the cases where rollover
|
||||
is set to happen "at midnight" or "on a particular weekday".
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
*atTime* parameter was added.
|
||||
|
||||
.. method:: doRollover()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
|
||||
# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
|
@ -18,7 +18,7 @@
|
|||
Additional handlers for the logging package for Python. The core package is
|
||||
based on PEP 282 and comments thereto in comp.lang.python.
|
||||
|
||||
Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
|
||||
Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
|
||||
|
||||
To use, simply 'import logging.handlers' and log away!
|
||||
"""
|
||||
|
@ -196,11 +196,12 @@ class TimedRotatingFileHandler(BaseRotatingHandler):
|
|||
If backupCount is > 0, when rollover is done, no more than backupCount
|
||||
files are kept - the oldest ones are deleted.
|
||||
"""
|
||||
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
|
||||
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
|
||||
BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
|
||||
self.when = when.upper()
|
||||
self.backupCount = backupCount
|
||||
self.utc = utc
|
||||
self.atTime = atTime
|
||||
# Calculate the real rollover interval, which is just the number of
|
||||
# seconds between rollovers. Also set the filename suffix used when
|
||||
# a rollover occurs. Current 'when' events supported:
|
||||
|
@ -270,9 +271,22 @@ class TimedRotatingFileHandler(BaseRotatingHandler):
|
|||
currentHour = t[3]
|
||||
currentMinute = t[4]
|
||||
currentSecond = t[5]
|
||||
# r is the number of seconds left between now and midnight
|
||||
r = _MIDNIGHT - ((currentHour * 60 + currentMinute) * 60 +
|
||||
currentSecond)
|
||||
currentDay = t[6]
|
||||
# r is the number of seconds left between now and the next rotation
|
||||
if self.atTime is None:
|
||||
rotate_ts = _MIDNIGHT
|
||||
else:
|
||||
rotate_ts = ((self.atTime.hour * 60 + self.atTime.minute)*60 +
|
||||
self.atTime.second)
|
||||
|
||||
r = rotate_ts - ((currentHour * 60 + currentMinute) * 60 +
|
||||
currentSecond)
|
||||
if r < 0:
|
||||
# Rotate time is before the current time (for example when
|
||||
# self.rotateAt is 13:45 and it now 14:15), rotation is
|
||||
# tomorrow.
|
||||
r += _MIDNIGHT
|
||||
currentDay = (currentDay + 1) % 7
|
||||
result = currentTime + r
|
||||
# If we are rolling over on a certain day, add in the number of days until
|
||||
# the next rollover, but offset by 1 since we just calculated the time
|
||||
|
@ -290,7 +304,7 @@ class TimedRotatingFileHandler(BaseRotatingHandler):
|
|||
# This is because the above time calculation takes us to midnight on this
|
||||
# day, i.e. the start of the next day.
|
||||
if self.when.startswith('W'):
|
||||
day = t[6] # 0 is Monday
|
||||
day = currentDay # 0 is Monday
|
||||
if day != self.dayOfWeek:
|
||||
if day < self.dayOfWeek:
|
||||
daysToWait = self.dayOfWeek - day
|
||||
|
|
|
@ -3949,6 +3949,48 @@ class TimedRotatingFileHandlerTest(BaseFileTest):
|
|||
assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
|
||||
self.fn, 'W7', delay=True)
|
||||
|
||||
def test_compute_rollover_daily_attime(self):
|
||||
currentTime = 0
|
||||
atTime = datetime.time(12, 0, 0)
|
||||
rh = logging.handlers.TimedRotatingFileHandler(
|
||||
self.fn, when='MIDNIGHT', interval=1, backupCount=0, utc=True,
|
||||
atTime=atTime)
|
||||
|
||||
actual = rh.computeRollover(currentTime)
|
||||
self.assertEqual(actual, currentTime + 12 * 60 * 60)
|
||||
|
||||
actual = rh.computeRollover(currentTime + 13 * 60 * 60)
|
||||
self.assertEqual(actual, currentTime + 36 * 60 * 60)
|
||||
|
||||
rh.close()
|
||||
|
||||
def test_compute_rollover_weekly_attime(self):
|
||||
currentTime = 0
|
||||
atTime = datetime.time(12, 0, 0)
|
||||
|
||||
wday = datetime.datetime.fromtimestamp(currentTime).weekday()
|
||||
for day in range(7):
|
||||
rh = logging.handlers.TimedRotatingFileHandler(
|
||||
self.fn, when='W%d' % day, interval=1, backupCount=0, utc=True,
|
||||
atTime=atTime)
|
||||
|
||||
if wday > day:
|
||||
expected = (7 - wday + day)
|
||||
else:
|
||||
expected = (day - wday)
|
||||
expected *= 24 * 60 * 60
|
||||
expected += 12 * 60 * 60
|
||||
actual = rh.computeRollover(currentTime)
|
||||
self.assertEqual(actual, expected)
|
||||
if day == wday:
|
||||
# goes into following week
|
||||
expected += 7 * 24 * 60 * 60
|
||||
actual = rh.computeRollover(currentTime + 13 * 60 * 60)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
rh.close()
|
||||
|
||||
|
||||
def secs(**kw):
|
||||
return datetime.timedelta(**kw) // datetime.timedelta(seconds=1)
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #9556: Allowed specifying a time-of-day for a TimedRotatingFileHandler
|
||||
to rotate.
|
||||
|
||||
- Issue #14971: unittest test discovery no longer gets confused when a function
|
||||
has a different __name__ than its name in the TestCase class dictionary.
|
||||
|
||||
|
|
Loading…
Reference in New Issue