[Python-checkins] gh-72346: Added isdst deprecation warning to email.utils.localtime (GH-91450)

zware webhook-mailer at python.org
Sun Mar 19 20:20:26 EDT 2023


https://github.com/python/cpython/commit/5e6661bce968173fa45b74fa2111098645ff609c
commit: 5e6661bce968173fa45b74fa2111098645ff609c
branch: main
author: Alan Williams <astropiloto at gmail.com>
committer: zware <zachary.ware at gmail.com>
date: 2023-03-19T19:20:20-05:00
summary:

gh-72346: Added isdst deprecation warning to email.utils.localtime (GH-91450)

files:
A Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-72346.pC7gnM.rst
M Doc/library/email.utils.rst
M Doc/whatsnew/3.12.rst
M Lib/email/utils.py
M Lib/test/test_email/test_utils.py

diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst
index 0e266b6a4578..345b64001c1a 100644
--- a/Doc/library/email.utils.rst
+++ b/Doc/library/email.utils.rst
@@ -13,19 +13,17 @@ module:
 
 .. function:: localtime(dt=None)
 
-    Return local time as an aware datetime object.  If called without
-    arguments, return current time.  Otherwise *dt* argument should be a
-    :class:`~datetime.datetime` instance, and it is converted to the local time
-    zone according to the system time zone database.  If *dt* is naive (that
-    is, ``dt.tzinfo`` is ``None``), it is assumed to be in local time.  In this
-    case, a positive or zero value for *isdst* causes ``localtime`` to presume
-    initially that summer time (for example, Daylight Saving Time) is or is not
-    (respectively) in effect for the specified time.  A negative value for
-    *isdst* causes the ``localtime`` to attempt to divine whether summer time
-    is in effect for the specified time.
-
-    .. versionadded:: 3.3
+   Return local time as an aware datetime object.  If called without
+   arguments, return current time.  Otherwise *dt* argument should be a
+   :class:`~datetime.datetime` instance, and it is converted to the local time
+   zone according to the system time zone database.  If *dt* is naive (that
+   is, ``dt.tzinfo`` is ``None``), it is assumed to be in local time.  The
+   *isdst* parameter is ignored.
 
+   .. versionadded:: 3.3
+
+   .. deprecated-removed:: 3.12 3.14
+      The *isdst* parameter.
 
 .. function:: make_msgid(idstring=None, domain=None)
 
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index a36e68528c4f..cdd26cd19e72 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -565,6 +565,9 @@ Pending Removal in Python 3.14
 * Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
   bases using the C API.
 
+* Deprecated the *isdst* parameter in :func:`email.utils.localtime`.
+  (Contributed by Alan Williams in :gh:`72346`.)
+
 * ``__package__`` and ``__cached__`` will cease to be set or taken
   into consideration by the import system (:gh:`97879`).
 
diff --git a/Lib/email/utils.py b/Lib/email/utils.py
index cfdfeb3f1a86..4d014bacd618 100644
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -331,41 +331,23 @@ def collapse_rfc2231_value(value, errors='replace',
 # better than not having it.
 #
 
-def localtime(dt=None, isdst=-1):
+def localtime(dt=None, isdst=None):
     """Return local time as an aware datetime object.
 
     If called without arguments, return current time.  Otherwise *dt*
     argument should be a datetime instance, and it is converted to the
     local time zone according to the system time zone database.  If *dt* is
     naive (that is, dt.tzinfo is None), it is assumed to be in local time.
-    In this case, a positive or zero value for *isdst* causes localtime to
-    presume initially that summer time (for example, Daylight Saving Time)
-    is or is not (respectively) in effect for the specified time.  A
-    negative value for *isdst* causes the localtime() function to attempt
-    to divine whether summer time is in effect for the specified time.
+    The isdst parameter is ignored.
 
     """
+    if isdst is not None:
+        import warnings
+        warnings._deprecated(
+            "The 'isdst' parameter to 'localtime'",
+            message='{name} is deprecated and slated for removal in Python {remove}',
+            remove=(3, 14),
+            )
     if dt is None:
-        return datetime.datetime.now(datetime.timezone.utc).astimezone()
-    if dt.tzinfo is not None:
-        return dt.astimezone()
-    # We have a naive datetime.  Convert to a (localtime) timetuple and pass to
-    # system mktime together with the isdst hint.  System mktime will return
-    # seconds since epoch.
-    tm = dt.timetuple()[:-1] + (isdst,)
-    seconds = time.mktime(tm)
-    localtm = time.localtime(seconds)
-    try:
-        delta = datetime.timedelta(seconds=localtm.tm_gmtoff)
-        tz = datetime.timezone(delta, localtm.tm_zone)
-    except AttributeError:
-        # Compute UTC offset and compare with the value implied by tm_isdst.
-        # If the values match, use the zone name implied by tm_isdst.
-        delta = dt - datetime.datetime(*time.gmtime(seconds)[:6])
-        dst = time.daylight and localtm.tm_isdst > 0
-        gmtoff = -(time.altzone if dst else time.timezone)
-        if delta == datetime.timedelta(seconds=gmtoff):
-            tz = datetime.timezone(delta, time.tzname[dst])
-        else:
-            tz = datetime.timezone(delta)
-    return dt.replace(tzinfo=tz)
+        dt = datetime.datetime.now()
+    return dt.astimezone()
diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py
index 78afb358035e..25fa48c5ee21 100644
--- a/Lib/test/test_email/test_utils.py
+++ b/Lib/test/test_email/test_utils.py
@@ -83,14 +83,14 @@ def test_localtime_is_tz_aware_daylight_false(self):
     def test_localtime_daylight_true_dst_false(self):
         test.support.patch(self, time, 'daylight', True)
         t0 = datetime.datetime(2012, 3, 12, 1, 1)
-        t1 = utils.localtime(t0, isdst=-1)
+        t1 = utils.localtime(t0)
         t2 = utils.localtime(t1)
         self.assertEqual(t1, t2)
 
     def test_localtime_daylight_false_dst_false(self):
         test.support.patch(self, time, 'daylight', False)
         t0 = datetime.datetime(2012, 3, 12, 1, 1)
-        t1 = utils.localtime(t0, isdst=-1)
+        t1 = utils.localtime(t0)
         t2 = utils.localtime(t1)
         self.assertEqual(t1, t2)
 
@@ -98,7 +98,7 @@ def test_localtime_daylight_false_dst_false(self):
     def test_localtime_daylight_true_dst_true(self):
         test.support.patch(self, time, 'daylight', True)
         t0 = datetime.datetime(2012, 3, 12, 1, 1)
-        t1 = utils.localtime(t0, isdst=1)
+        t1 = utils.localtime(t0)
         t2 = utils.localtime(t1)
         self.assertEqual(t1, t2)
 
@@ -106,7 +106,7 @@ def test_localtime_daylight_true_dst_true(self):
     def test_localtime_daylight_false_dst_true(self):
         test.support.patch(self, time, 'daylight', False)
         t0 = datetime.datetime(2012, 3, 12, 1, 1)
-        t1 = utils.localtime(t0, isdst=1)
+        t1 = utils.localtime(t0)
         t2 = utils.localtime(t1)
         self.assertEqual(t1, t2)
 
@@ -157,6 +157,11 @@ def test_variable_tzname(self):
         t1 = utils.localtime(t0)
         self.assertEqual(t1.tzname(), 'EET')
 
+    def test_isdst_deprecation(self):
+        with self.assertWarns(DeprecationWarning):
+            t0 = datetime.datetime(1990, 1, 1)
+            t1 = utils.localtime(t0, isdst=True)
+
 # Issue #24836: The timezone files are out of date (pre 2011k)
 # on Mac OS X Snow Leopard.
 @test.support.requires_mac_ver(10, 7)
diff --git a/Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-72346.pC7gnM.rst b/Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-72346.pC7gnM.rst
new file mode 100644
index 000000000000..149ddd706c35
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-72346.pC7gnM.rst
@@ -0,0 +1 @@
+Added deprecation warning to *isdst* parameter of :func:`email.utils.localtime`.



More information about the Python-checkins mailing list