https://github.com/python/cpython/commit/3b4cd48d2988e74405838accde5edcc3b71bec48
commit: 3b4cd48d2988e74405838accde5edcc3b71bec48
branch: 3.11
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: serhiy-storchaka <storch...@gmail.com>
date: 2024-03-18T19:47:53+02:00
summary:

[3.11] gh-90535: Fix support of interval>1 in logging.TimedRotatingFileHandler 
(GH-116220) (GH-116893)

Fix support of interval values > 1 in logging.TimedRotatingFileHandler
for when='MIDNIGHT' and when='Wx'.
(cherry picked from commit 269051d20e65eda30734cbbbdb07d21df61978d6)

Co-authored-by: Serhiy Storchaka <storch...@gmail.com>

files:
A Misc/NEWS.d/next/Library/2024-03-01-20-23-57.gh-issue-90535.wXm-jC.rst
M Lib/logging/handlers.py
M Lib/test/test_logging.py

diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index d7c404e9ff6c0c..8c40fa04a4968e 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -334,7 +334,10 @@ def computeRollover(self, currentTime):
                         daysToWait = self.dayOfWeek - day
                     else:
                         daysToWait = 6 - day + self.dayOfWeek + 1
-                    result += daysToWait * (60 * 60 * 24)
+                    result += daysToWait * _MIDNIGHT
+                result += self.interval - _MIDNIGHT * 7
+            else:
+                result += self.interval - _MIDNIGHT
             if not self.utc:
                 dstNow = t[-1]
                 dstAtRollover = time.localtime(result)[-1]
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index ff03dd7bc13218..fbaafde881c9ee 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -6147,6 +6147,129 @@ def test(current, expected):
 
         fh.close()
 
+    # Run with US-style DST rules: DST begins 2 a.m. on second Sunday in
+    # March (M3.2.0) and ends 2 a.m. on first Sunday in November (M11.1.0).
+    @support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
+    def test_compute_rollover_MIDNIGHT_local_interval(self):
+        # DST begins at 2012-3-11T02:00:00 and ends at 2012-11-4T02:00:00.
+        DT = datetime.datetime
+        def test(current, expected):
+            actual = fh.computeRollover(current.timestamp())
+            diff = actual - expected.timestamp()
+            if diff:
+                self.assertEqual(diff, 0, datetime.timedelta(seconds=diff))
+
+        fh = logging.handlers.TimedRotatingFileHandler(
+            self.fn, encoding="utf-8", when='MIDNIGHT', utc=False, interval=3)
+
+        test(DT(2012, 3, 8, 23, 59, 59), DT(2012, 3, 11, 0, 0))
+        test(DT(2012, 3, 9, 0, 0), DT(2012, 3, 12, 0, 0))
+        test(DT(2012, 3, 9, 1, 0), DT(2012, 3, 12, 0, 0))
+        test(DT(2012, 3, 10, 23, 59, 59), DT(2012, 3, 13, 0, 0))
+        test(DT(2012, 3, 11, 0, 0), DT(2012, 3, 14, 0, 0))
+        test(DT(2012, 3, 11, 1, 0), DT(2012, 3, 14, 0, 0))
+
+        test(DT(2012, 11, 1, 23, 59, 59), DT(2012, 11, 4, 0, 0))
+        test(DT(2012, 11, 2, 0, 0), DT(2012, 11, 5, 0, 0))
+        test(DT(2012, 11, 2, 1, 0), DT(2012, 11, 5, 0, 0))
+        test(DT(2012, 11, 3, 23, 59, 59), DT(2012, 11, 6, 0, 0))
+        test(DT(2012, 11, 4, 0, 0), DT(2012, 11, 7, 0, 0))
+        test(DT(2012, 11, 4, 1, 0), DT(2012, 11, 7, 0, 0))
+
+        fh.close()
+
+        fh = logging.handlers.TimedRotatingFileHandler(
+            self.fn, encoding="utf-8", when='MIDNIGHT', utc=False, interval=3,
+            atTime=datetime.time(12, 0, 0))
+
+        test(DT(2012, 3, 8, 11, 59, 59), DT(2012, 3, 10, 12, 0))
+        test(DT(2012, 3, 8, 12, 0), DT(2012, 3, 11, 12, 0))
+        test(DT(2012, 3, 8, 13, 0), DT(2012, 3, 11, 12, 0))
+        test(DT(2012, 3, 10, 11, 59, 59), DT(2012, 3, 12, 12, 0))
+        test(DT(2012, 3, 10, 12, 0), DT(2012, 3, 13, 12, 0))
+        test(DT(2012, 3, 10, 13, 0), DT(2012, 3, 13, 12, 0))
+
+        test(DT(2012, 11, 1, 11, 59, 59), DT(2012, 11, 3, 12, 0))
+        test(DT(2012, 11, 1, 12, 0), DT(2012, 11, 4, 12, 0))
+        test(DT(2012, 11, 1, 13, 0), DT(2012, 11, 4, 12, 0))
+        test(DT(2012, 11, 3, 11, 59, 59), DT(2012, 11, 5, 12, 0))
+        test(DT(2012, 11, 3, 12, 0), DT(2012, 11, 6, 12, 0))
+        test(DT(2012, 11, 3, 13, 0), DT(2012, 11, 6, 12, 0))
+
+        fh.close()
+
+    # Run with US-style DST rules: DST begins 2 a.m. on second Sunday in
+    # March (M3.2.0) and ends 2 a.m. on first Sunday in November (M11.1.0).
+    @support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
+    def test_compute_rollover_W6_local_interval(self):
+        # DST begins at 2012-3-11T02:00:00 and ends at 2012-11-4T02:00:00.
+        DT = datetime.datetime
+        def test(current, expected):
+            actual = fh.computeRollover(current.timestamp())
+            diff = actual - expected.timestamp()
+            if diff:
+                self.assertEqual(diff, 0, datetime.timedelta(seconds=diff))
+
+        fh = logging.handlers.TimedRotatingFileHandler(
+            self.fn, encoding="utf-8", when='W6', utc=False, interval=3)
+
+        test(DT(2012, 2, 19, 23, 59, 59), DT(2012, 3, 5, 0, 0))
+        test(DT(2012, 2, 20, 0, 0), DT(2012, 3, 12, 0, 0))
+        test(DT(2012, 2, 20, 1, 0), DT(2012, 3, 12, 0, 0))
+        test(DT(2012, 3, 4, 23, 59, 59), DT(2012, 3, 19, 0, 0))
+        test(DT(2012, 3, 5, 0, 0), DT(2012, 3, 26, 0, 0))
+        test(DT(2012, 3, 5, 1, 0), DT(2012, 3, 26, 0, 0))
+
+        test(DT(2012, 10, 14, 23, 59, 59), DT(2012, 10, 29, 0, 0))
+        test(DT(2012, 10, 15, 0, 0), DT(2012, 11, 5, 0, 0))
+        test(DT(2012, 10, 15, 1, 0), DT(2012, 11, 5, 0, 0))
+        test(DT(2012, 10, 28, 23, 59, 59), DT(2012, 11, 12, 0, 0))
+        test(DT(2012, 10, 29, 0, 0), DT(2012, 11, 19, 0, 0))
+        test(DT(2012, 10, 29, 1, 0), DT(2012, 11, 19, 0, 0))
+
+        fh.close()
+
+        fh = logging.handlers.TimedRotatingFileHandler(
+            self.fn, encoding="utf-8", when='W6', utc=False, interval=3,
+            atTime=datetime.time(0, 0, 0))
+
+        test(DT(2012, 2, 25, 23, 59, 59), DT(2012, 3, 11, 0, 0))
+        test(DT(2012, 2, 26, 0, 0), DT(2012, 3, 18, 0, 0))
+        test(DT(2012, 2, 26, 1, 0), DT(2012, 3, 18, 0, 0))
+        test(DT(2012, 3, 10, 23, 59, 59), DT(2012, 3, 25, 0, 0))
+        test(DT(2012, 3, 11, 0, 0), DT(2012, 4, 1, 0, 0))
+        test(DT(2012, 3, 11, 1, 0), DT(2012, 4, 1, 0, 0))
+
+        test(DT(2012, 10, 20, 23, 59, 59), DT(2012, 11, 4, 0, 0))
+        test(DT(2012, 10, 21, 0, 0), DT(2012, 11, 11, 0, 0))
+        test(DT(2012, 10, 21, 1, 0), DT(2012, 11, 11, 0, 0))
+        test(DT(2012, 11, 3, 23, 59, 59), DT(2012, 11, 18, 0, 0))
+        test(DT(2012, 11, 4, 0, 0), DT(2012, 11, 25, 0, 0))
+        test(DT(2012, 11, 4, 1, 0), DT(2012, 11, 25, 0, 0))
+
+        fh.close()
+
+        fh = logging.handlers.TimedRotatingFileHandler(
+            self.fn, encoding="utf-8", when='W6', utc=False, interval=3,
+            atTime=datetime.time(12, 0, 0))
+
+        test(DT(2012, 2, 18, 11, 59, 59), DT(2012, 3, 4, 12, 0))
+        test(DT(2012, 2, 19, 12, 0), DT(2012, 3, 11, 12, 0))
+        test(DT(2012, 2, 19, 13, 0), DT(2012, 3, 11, 12, 0))
+        test(DT(2012, 3, 4, 11, 59, 59), DT(2012, 3, 18, 12, 0))
+        test(DT(2012, 3, 4, 12, 0), DT(2012, 3, 25, 12, 0))
+        test(DT(2012, 3, 4, 13, 0), DT(2012, 3, 25, 12, 0))
+
+        test(DT(2012, 10, 14, 11, 59, 59), DT(2012, 10, 28, 12, 0))
+        test(DT(2012, 10, 14, 12, 0), DT(2012, 11, 4, 12, 0))
+        test(DT(2012, 10, 14, 13, 0), DT(2012, 11, 4, 12, 0))
+        test(DT(2012, 10, 28, 11, 59, 59), DT(2012, 11, 11, 12, 0))
+        test(DT(2012, 10, 28, 12, 0), DT(2012, 11, 18, 12, 0))
+        test(DT(2012, 10, 28, 13, 0), DT(2012, 11, 18, 12, 0))
+
+        fh.close()
+
+
 def secs(**kw):
     return datetime.timedelta(**kw) // datetime.timedelta(seconds=1)
 
@@ -6158,40 +6281,49 @@ def secs(**kw):
                   # current time (epoch start) is a Thursday, W0 means Monday
                   ('W0', secs(days=4, hours=24)),
                  ):
-    def test_compute_rollover(self, when=when, exp=exp):
-        rh = logging.handlers.TimedRotatingFileHandler(
-            self.fn, encoding="utf-8", when=when, interval=1, backupCount=0, 
utc=True)
-        currentTime = 0.0
-        actual = rh.computeRollover(currentTime)
-        if exp != actual:
-            # Failures occur on some systems for MIDNIGHT and W0.
-            # Print detailed calculation for MIDNIGHT so we can try to see
-            # what's going on
-            if when == 'MIDNIGHT':
-                try:
-                    if rh.utc:
-                        t = time.gmtime(currentTime)
-                    else:
-                        t = time.localtime(currentTime)
-                    currentHour = t[3]
-                    currentMinute = t[4]
-                    currentSecond = t[5]
-                    # r is the number of seconds left between now and midnight
-                    r = logging.handlers._MIDNIGHT - ((currentHour * 60 +
-                                                       currentMinute) * 60 +
-                            currentSecond)
-                    result = currentTime + r
-                    print('t: %s (%s)' % (t, rh.utc), file=sys.stderr)
-                    print('currentHour: %s' % currentHour, file=sys.stderr)
-                    print('currentMinute: %s' % currentMinute, file=sys.stderr)
-                    print('currentSecond: %s' % currentSecond, file=sys.stderr)
-                    print('r: %s' % r, file=sys.stderr)
-                    print('result: %s' % result, file=sys.stderr)
-                except Exception as e:
-                    print('exception in diagnostic code: %s' % e, 
file=sys.stderr)
-        self.assertEqual(exp, actual)
-        rh.close()
-    setattr(TimedRotatingFileHandlerTest, "test_compute_rollover_%s" % when, 
test_compute_rollover)
+    for interval in 1, 3:
+        def test_compute_rollover(self, when=when, interval=interval, exp=exp):
+            rh = logging.handlers.TimedRotatingFileHandler(
+                self.fn, encoding="utf-8", when=when, interval=interval, 
backupCount=0, utc=True)
+            currentTime = 0.0
+            actual = rh.computeRollover(currentTime)
+            if when.startswith('W'):
+                exp += secs(days=7*(interval-1))
+            else:
+                exp *= interval
+            if exp != actual:
+                # Failures occur on some systems for MIDNIGHT and W0.
+                # Print detailed calculation for MIDNIGHT so we can try to see
+                # what's going on
+                if when == 'MIDNIGHT':
+                    try:
+                        if rh.utc:
+                            t = time.gmtime(currentTime)
+                        else:
+                            t = time.localtime(currentTime)
+                        currentHour = t[3]
+                        currentMinute = t[4]
+                        currentSecond = t[5]
+                        # r is the number of seconds left between now and 
midnight
+                        r = logging.handlers._MIDNIGHT - ((currentHour * 60 +
+                                                        currentMinute) * 60 +
+                                currentSecond)
+                        result = currentTime + r
+                        print('t: %s (%s)' % (t, rh.utc), file=sys.stderr)
+                        print('currentHour: %s' % currentHour, file=sys.stderr)
+                        print('currentMinute: %s' % currentMinute, 
file=sys.stderr)
+                        print('currentSecond: %s' % currentSecond, 
file=sys.stderr)
+                        print('r: %s' % r, file=sys.stderr)
+                        print('result: %s' % result, file=sys.stderr)
+                    except Exception as e:
+                        print('exception in diagnostic code: %s' % e, 
file=sys.stderr)
+            self.assertEqual(exp, actual)
+            rh.close()
+        name = "test_compute_rollover_%s" % when
+        if interval > 1:
+            name += "_interval"
+        test_compute_rollover.__name__ = name
+        setattr(TimedRotatingFileHandlerTest, name, test_compute_rollover)
 
 
 @unittest.skipUnless(win32evtlog, 'win32evtlog/win32evtlogutil/pywintypes 
required for this test.')
diff --git 
a/Misc/NEWS.d/next/Library/2024-03-01-20-23-57.gh-issue-90535.wXm-jC.rst 
b/Misc/NEWS.d/next/Library/2024-03-01-20-23-57.gh-issue-90535.wXm-jC.rst
new file mode 100644
index 00000000000000..9af4efabb6b5b2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-03-01-20-23-57.gh-issue-90535.wXm-jC.rst
@@ -0,0 +1,3 @@
+Fix support of *interval* values > 1 in
+:class:`logging.TimedRotatingFileHandler` for ``when='MIDNIGHT'`` and
+``when='Wx'``.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to