[Python-checkins] bpo-30302 Make timedelta.__repr__ more informative. (#1493)

Victor Stinner webhook-mailer at python.org
Tue Jul 25 17:51:39 EDT 2017


https://github.com/python/cpython/commit/cc5a65cd9025280ea67ef4bbc2a8bfe31ced6c30
commit: cc5a65cd9025280ea67ef4bbc2a8bfe31ced6c30
branch: master
author: Utkarsh Upadhyay <mail at musicallyut.in>
committer: Victor Stinner <victor.stinner at gmail.com>
date: 2017-07-25T23:51:33+02:00
summary:

bpo-30302 Make timedelta.__repr__ more informative. (#1493)

files:
A Misc/NEWS.d/next/Library/2017-06-30-23-05-47.bpo-30302.itwK_k.rst
M Doc/library/datetime.rst
M Lib/datetime.py
M Lib/test/datetimetester.py
M Lib/test/test_datetime.py
M Modules/_datetimemodule.c

diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
index e757e5d685b..625e1590a87 100644
--- a/Doc/library/datetime.rst
+++ b/Doc/library/datetime.rst
@@ -287,11 +287,12 @@ Supported operations:
 |                                | ``[D day[s], ][H]H:MM:SS[.UUUUUU]``, where D  |
 |                                | is negative for negative ``t``. (5)           |
 +--------------------------------+-----------------------------------------------+
-| ``repr(t)``                    | Returns a string in the form                  |
-|                                | ``datetime.timedelta(D[, S[, U]])``, where D  |
-|                                | is negative for negative ``t``. (5)           |
+| ``repr(t)``                    | Returns a string representation of the        |
+|                                | :class:`timedelta` object as a constructor    |
+|                                | call with canonical attribute values.         |
 +--------------------------------+-----------------------------------------------+
 
+
 Notes:
 
 (1)
diff --git a/Lib/datetime.py b/Lib/datetime.py
index b95536fb7af..76a6f957e08 100644
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -454,20 +454,18 @@ def __new__(cls, days=0, seconds=0, microseconds=0,
         return self
 
     def __repr__(self):
-        if self._microseconds:
-            return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
-                                          self.__class__.__qualname__,
-                                          self._days,
-                                          self._seconds,
-                                          self._microseconds)
+        args = []
+        if self._days:
+            args.append("days=%d" % self._days)
         if self._seconds:
-            return "%s.%s(%d, %d)" % (self.__class__.__module__,
-                                      self.__class__.__qualname__,
-                                      self._days,
-                                      self._seconds)
-        return "%s.%s(%d)" % (self.__class__.__module__,
+            args.append("seconds=%d" % self._seconds)
+        if self._microseconds:
+            args.append("microseconds=%d" % self._microseconds)
+        if not args:
+            args.append('0')
+        return "%s.%s(%s)" % (self.__class__.__module__,
                               self.__class__.__qualname__,
-                              self._days)
+                              ', '.join(args))
 
     def __str__(self):
         mm, ss = divmod(self._seconds, 60)
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index b25e6c17136..22008884b54 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -658,11 +658,21 @@ def test_str(self):
     def test_repr(self):
         name = 'datetime.' + self.theclass.__name__
         self.assertEqual(repr(self.theclass(1)),
-                         "%s(1)" % name)
+                         "%s(days=1)" % name)
         self.assertEqual(repr(self.theclass(10, 2)),
-                         "%s(10, 2)" % name)
+                         "%s(days=10, seconds=2)" % name)
         self.assertEqual(repr(self.theclass(-10, 2, 400000)),
-                         "%s(-10, 2, 400000)" % name)
+                         "%s(days=-10, seconds=2, microseconds=400000)" % name)
+        self.assertEqual(repr(self.theclass(seconds=60)),
+                         "%s(seconds=60)" % name)
+        self.assertEqual(repr(self.theclass()),
+                         "%s(0)" % name)
+        self.assertEqual(repr(self.theclass(microseconds=100)),
+                         "%s(microseconds=100)" % name)
+        self.assertEqual(repr(self.theclass(days=1, microseconds=100)),
+                         "%s(days=1, microseconds=100)" % name)
+        self.assertEqual(repr(self.theclass(seconds=1, microseconds=100)),
+                         "%s(seconds=1, microseconds=100)" % name)
 
     def test_roundtrip(self):
         for td in (timedelta(days=999999999, hours=23, minutes=59,
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index d659f369d54..bb22871f2b1 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -50,6 +50,8 @@ def tearDownClass(cls_):
         cls.tearDownClass = tearDownClass
     all_test_classes.extend(test_classes)
 
+    all_test_classes.extend(test_classes)
+
 def test_main():
     run_unittest(*all_test_classes)
 
diff --git a/Misc/NEWS.d/next/Library/2017-06-30-23-05-47.bpo-30302.itwK_k.rst b/Misc/NEWS.d/next/Library/2017-06-30-23-05-47.bpo-30302.itwK_k.rst
new file mode 100644
index 00000000000..927250d04c4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-06-30-23-05-47.bpo-30302.itwK_k.rst
@@ -0,0 +1 @@
+Use keywords in the ``repr`` of ``datetime.timedelta``.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 3439040d2d9..28805d18da8 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -2284,21 +2284,50 @@ delta_bool(PyDateTime_Delta *self)
 static PyObject *
 delta_repr(PyDateTime_Delta *self)
 {
-    if (GET_TD_MICROSECONDS(self) != 0)
-        return PyUnicode_FromFormat("%s(%d, %d, %d)",
-                                    Py_TYPE(self)->tp_name,
-                                    GET_TD_DAYS(self),
-                                    GET_TD_SECONDS(self),
-                                    GET_TD_MICROSECONDS(self));
-    if (GET_TD_SECONDS(self) != 0)
-        return PyUnicode_FromFormat("%s(%d, %d)",
-                                    Py_TYPE(self)->tp_name,
-                                    GET_TD_DAYS(self),
-                                    GET_TD_SECONDS(self));
-
-    return PyUnicode_FromFormat("%s(%d)",
-                                Py_TYPE(self)->tp_name,
-                                GET_TD_DAYS(self));
+    PyObject *args = PyUnicode_FromString("");
+
+    if (args == NULL) {
+        return NULL;
+    }
+
+    const char *sep = "";
+
+    if (GET_TD_DAYS(self) != 0) {
+        Py_SETREF(args, PyUnicode_FromFormat("days=%d", GET_TD_DAYS(self)));
+        if (args == NULL) {
+            return NULL;
+        }
+        sep = ", ";
+    }
+
+    if (GET_TD_SECONDS(self) != 0) {
+        Py_SETREF(args, PyUnicode_FromFormat("%U%sseconds=%d", args, sep,
+                                             GET_TD_SECONDS(self)));
+        if (args == NULL) {
+            return NULL;
+        }
+        sep = ", ";
+    }
+
+    if (GET_TD_MICROSECONDS(self) != 0) {
+        Py_SETREF(args, PyUnicode_FromFormat("%U%smicroseconds=%d", args, sep,
+                                             GET_TD_MICROSECONDS(self)));
+        if (args == NULL) {
+            return NULL;
+        }
+    }
+
+    if (PyUnicode_GET_LENGTH(args) == 0) {
+        Py_SETREF(args, PyUnicode_FromString("0"));
+        if (args == NULL) {
+            return NULL;
+        }
+    }
+
+    PyObject *repr = PyUnicode_FromFormat("%s(%S)", Py_TYPE(self)->tp_name,
+                                          args);
+    Py_DECREF(args);
+    return repr;
 }
 
 static PyObject *



More information about the Python-checkins mailing list