[Python-checkins] GH-103944: Remove last use of `utcfromtimestamp` (#103995)

pganssle webhook-mailer at python.org
Wed May 3 11:17:40 EDT 2023


https://github.com/python/cpython/commit/38dc3f28dde92b4fa6284a57f4e554991a3d9276
commit: 38dc3f28dde92b4fa6284a57f4e554991a3d9276
branch: main
author: Paul Ganssle <1377457+pganssle at users.noreply.github.com>
committer: pganssle <1377457+pganssle at users.noreply.github.com>
date: 2023-05-03T11:17:27-04:00
summary:

GH-103944: Remove last use of `utcfromtimestamp` (#103995)

* Remove last use of `utcfromtimestamp`

This was a weirdly valid use of `utcfromtimestamp` in the sense that the "timestamps" in TZif files are not epoch times, but actually something more properly thought of as "number of seconds since 1970 in the local time zone", so even though we didn't want UTC time, `utcfromtimestamp` was still a good way to get the thing we wanted. Since we're deprecating `utcfromtimestamp`, it's just as valid to use `timedelta` arithmetic here.

We may be able to avoid the question entirely by switching these tests over to using `ZoneInfo` in the future.

* Fix a few missing DeprecationWarnings in tests

In one test, we simply turn off DeprecationWarning rather than asserting about it, because whether the error condition happens before or after the warning seems to differ between the Python and C versions.

files:
M Lib/test/datetimetester.py

diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index fb07d2a5ad9b..55e061950ff2 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -2,18 +2,19 @@
 
 See https://www.zope.dev/Members/fdrake/DateTimeWiki/TestCases
 """
-import io
-import itertools
 import bisect
 import copy
 import decimal
-import sys
+import io
+import itertools
 import os
 import pickle
 import random
 import re
 import struct
+import sys
 import unittest
+import warnings
 
 from array import array
 
@@ -51,11 +52,12 @@
                   for proto in range(pickle.HIGHEST_PROTOCOL + 1)]
 assert len(pickle_choices) == pickle.HIGHEST_PROTOCOL + 1
 
+EPOCH_NAIVE = datetime(1970, 1, 1, 0, 0)  # For calculating transitions
+
 # An arbitrary collection of objects of non-datetime types, for testing
 # mixed-type comparisons.
 OTHERSTUFF = (10, 34.5, "abc", {}, [], ())
 
-
 # XXX Copied from test_float.
 INF = float("inf")
 NAN = float("nan")
@@ -2626,9 +2628,10 @@ def test_utcfromtimestamp_limits(self):
         for test_name, ts in test_cases:
             with self.subTest(test_name, ts=ts):
                 with self.assertRaises((ValueError, OverflowError)):
-                    # converting a Python int to C time_t can raise a
-                    # OverflowError, especially on 32-bit platforms.
-                    self.theclass.utcfromtimestamp(ts)
+                    with self.assertWarns(DeprecationWarning):
+                        # converting a Python int to C time_t can raise a
+                        # OverflowError, especially on 32-bit platforms.
+                        self.theclass.utcfromtimestamp(ts)
 
     def test_insane_fromtimestamp(self):
         # It's possible that some platform maps time_t to double,
@@ -2645,8 +2648,9 @@ def test_insane_utcfromtimestamp(self):
         # exempt such platforms (provided they return reasonable
         # results!).
         for insane in -1e200, 1e200:
-            self.assertRaises(OverflowError, self.theclass.utcfromtimestamp,
-                              insane)
+            with self.assertWarns(DeprecationWarning):
+                self.assertRaises(OverflowError, self.theclass.utcfromtimestamp,
+                                  insane)
 
     @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
     def test_negative_float_fromtimestamp(self):
@@ -3005,7 +3009,7 @@ def __new__(cls, *args, **kwargs):
         for name, meth_name, kwargs in test_cases:
             with self.subTest(name):
                 constr = getattr(DateTimeSubclass, meth_name)
-                if constr == "utcnow":
+                if meth_name == "utcnow":
                     with self.assertWarns(DeprecationWarning):
                         dt = constr(**kwargs)
                 else:
@@ -4733,8 +4737,10 @@ def test_tzinfo_utcfromtimestamp(self):
         # Try with and without naming the keyword; for whatever reason,
         # utcfromtimestamp() doesn't accept a tzinfo argument.
         off42 = FixedOffset(42, "42")
-        self.assertRaises(TypeError, meth, ts, off42)
-        self.assertRaises(TypeError, meth, ts, tzinfo=off42)
+        with warnings.catch_warnings(category=DeprecationWarning):
+            warnings.simplefilter("ignore", category=DeprecationWarning)
+            self.assertRaises(TypeError, meth, ts, off42)
+            self.assertRaises(TypeError, meth, ts, tzinfo=off42)
 
     def test_tzinfo_timetuple(self):
         # TestDateTime tested most of this.  datetime adds a twist to the
@@ -6102,15 +6108,14 @@ def stats(cls, start_year=1):
     def transitions(self):
         for (_, prev_ti), (t, ti) in pairs(zip(self.ut, self.ti)):
             shift = ti[0] - prev_ti[0]
-            # TODO: Remove this use of utcfromtimestamp
-            yield datetime.utcfromtimestamp(t), shift
+            yield (EPOCH_NAIVE + timedelta(seconds=t)), shift
 
     def nondst_folds(self):
         """Find all folds with the same value of isdst on both sides of the transition."""
         for (_, prev_ti), (t, ti) in pairs(zip(self.ut, self.ti)):
             shift = ti[0] - prev_ti[0]
             if shift < ZERO and ti[1] == prev_ti[1]:
-                yield datetime.utcfromtimestamp(t), -shift, prev_ti[2], ti[2]
+                yield _utcfromtimestamp(datetime, t,), -shift, prev_ti[2], ti[2]
 
     @classmethod
     def print_all_nondst_folds(cls, same_abbr=False, start_year=1):



More information about the Python-checkins mailing list