]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-84976: Re-introduce `datetime.py` and fix reprs
authorPaul Ganssle <git@m.ganssle.io>
Thu, 23 Mar 2023 15:36:22 +0000 (11:36 -0400)
committerT. Wouters <thomas@python.org>
Wed, 3 May 2023 09:09:45 +0000 (03:09 -0600)
Without the change to the reprs, pure-python classes would have a repr
of `datetime._pydatetime.time`, etc.

Lib/_pydatetime.py
Lib/datetime.py [new file with mode: 0644]
Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst [new file with mode: 0644]

index b0eb1c216a689dfb56cc891d88e82b2e3349a51a..f4fc2c58e5e2937ee5cbcf0d12569a65d8d9629b 100644 (file)
@@ -16,6 +16,13 @@ from operator import index as _index
 def _cmp(x, y):
     return 0 if x == y else 1 if x > y else -1
 
+def _get_class_module(self):
+    module_name = self.__class__.__module__
+    if module_name == '_pydatetime':
+        return 'datetime'
+    else:
+        return module_name
+
 MINYEAR = 1
 MAXYEAR = 9999
 _MAXORDINAL = 3652059  # date.max.toordinal()
@@ -706,7 +713,7 @@ class timedelta:
             args.append("microseconds=%d" % self._microseconds)
         if not args:
             args.append('0')
-        return "%s.%s(%s)" % (self.__class__.__module__,
+        return "%s.%s(%s)" % (_get_class_module(self),
                               self.__class__.__qualname__,
                               ', '.join(args))
 
@@ -1016,7 +1023,7 @@ class date:
         >>> repr(dt)
         'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
         """
-        return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
+        return "%s.%s(%d, %d, %d)" % (_get_class_module(self),
                                       self.__class__.__qualname__,
                                       self._year,
                                       self._month,
@@ -1510,7 +1517,7 @@ class time:
             s = ", %d" % self._second
         else:
             s = ""
-        s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
+        s= "%s.%s(%d, %d%s)" % (_get_class_module(self),
                                 self.__class__.__qualname__,
                                 self._hour, self._minute, s)
         if self._tzinfo is not None:
@@ -2065,7 +2072,7 @@ class datetime(date):
             del L[-1]
         if L[-1] == 0:
             del L[-1]
-        s = "%s.%s(%s)" % (self.__class__.__module__,
+        s = "%s.%s(%s)" % (_get_class_module(self),
                            self.__class__.__qualname__,
                            ", ".join(map(str, L)))
         if self._tzinfo is not None:
@@ -2372,10 +2379,10 @@ class timezone(tzinfo):
         if self is self.utc:
             return 'datetime.timezone.utc'
         if self._name is None:
-            return "%s.%s(%r)" % (self.__class__.__module__,
+            return "%s.%s(%r)" % (_get_class_module(self),
                                   self.__class__.__qualname__,
                                   self._offset)
-        return "%s.%s(%r, %r)" % (self.__class__.__module__,
+        return "%s.%s(%r, %r)" % (_get_class_module(self),
                                   self.__class__.__qualname__,
                                   self._offset, self._name)
 
@@ -2638,26 +2645,3 @@ _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
 # small dst() may get within its bounds; and it doesn't even matter if some
 # perverse time zone returns a negative dst()).  So a breaking case must be
 # pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
-
-try:
-    from _datetime import *
-except ImportError:
-    pass
-else:
-    # Clean up unused names
-    del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
-         _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
-         _check_date_fields, _check_time_fields,
-         _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
-         _date_class, _days_before_month, _days_before_year, _days_in_month,
-         _format_time, _format_offset, _index, _is_leap, _isoweek1monday, _math,
-         _ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord,
-         _divide_and_round, _parse_isoformat_date, _parse_isoformat_time,
-         _parse_hh_mm_ss_ff, _IsoCalendarDate, _isoweek_to_gregorian,
-         _find_isoformat_datetime_separator, _FRACTION_CORRECTION,
-         _is_ascii_digit)
-    # XXX Since import * above excludes names that start with _,
-    # docstring does not get overwritten. In the future, it may be
-    # appropriate to maintain a single module level docstring and
-    # remove the following line.
-    from _datetime import __doc__
diff --git a/Lib/datetime.py b/Lib/datetime.py
new file mode 100644 (file)
index 0000000..bad8beb
--- /dev/null
@@ -0,0 +1,9 @@
+try:
+    from _datetime import *
+    from _datetime import __doc__
+except ImportError:
+    from _pydatetime import *
+    from _pydatetime import __doc__
+
+__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
+           "MINYEAR", "MAXYEAR")
diff --git a/Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst b/Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst
new file mode 100644 (file)
index 0000000..8658627
--- /dev/null
@@ -0,0 +1,5 @@
+Create a new ``Lib/_pydatetime.py`` file that defines the Python version of
+the ``datetime`` module, and make ``datetime`` import the contents of the
+new library only if the C implementation is missing. Currently, the full
+Python implementation is defined and then deleted if the C implementation is
+not available, slowing down ``import datetime`` unnecessarily.