]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #28752: Restored the __reduce__() methods of datetime objects.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 21 Nov 2016 22:29:42 +0000 (00:29 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 21 Nov 2016 22:29:42 +0000 (00:29 +0200)
Lib/datetime.py
Lib/test/datetimetester.py
Misc/NEWS
Modules/_datetimemodule.c

index 36374aa94c871a7b658c3a2bcc42060d8a6e6e2d..754010968429c46908f7d56bc5d3a87cdc3b6e07 100644 (file)
@@ -932,7 +932,7 @@ class date:
 
     # Pickle support.
 
-    def _getstate(self, protocol=3):
+    def _getstate(self):
         yhi, ylo = divmod(self._year, 256)
         return bytes([yhi, ylo, self._month, self._day]),
 
@@ -940,8 +940,8 @@ class date:
         yhi, ylo, self._month, self._day = string
         self._year = yhi * 256 + ylo
 
-    def __reduce_ex__(self, protocol):
-        return (self.__class__, self._getstate(protocol))
+    def __reduce__(self):
+        return (self.__class__, self._getstate())
 
 _date_class = date  # so functions w/ args named "date" can get at the class
 
@@ -1348,6 +1348,9 @@ class time:
     def __reduce_ex__(self, protocol):
         return (time, self._getstate(protocol))
 
+    def __reduce__(self):
+        return self.__reduce_ex__(2)
+
 _time_class = time  # so functions w/ args named "time" can get at the class
 
 time.min = time(0, 0, 0)
@@ -1923,6 +1926,9 @@ class datetime(date):
     def __reduce_ex__(self, protocol):
         return (self.__class__, self._getstate(protocol))
 
+    def __reduce__(self):
+        return self.__reduce_ex__(2)
+
 
 datetime.min = datetime(1, 1, 1)
 datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
index 988c6f722e21b0f858d0a46e839ddd013c1fcee8..d65186db0ce5127ce9a3bcc0cfc1cf1d1a54067a 100644 (file)
@@ -1329,6 +1329,7 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
             green = pickler.dumps(orig, proto)
             derived = unpickler.loads(green)
             self.assertEqual(orig, derived)
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
     def test_compare(self):
         t1 = self.theclass(2, 3, 4)
@@ -1830,6 +1831,7 @@ class TestDateTime(TestDate):
             green = pickler.dumps(orig, proto)
             derived = unpickler.loads(green)
             self.assertEqual(orig, derived)
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
     def test_more_pickling(self):
         a = self.theclass(2003, 2, 7, 16, 48, 37, 444116)
@@ -2469,6 +2471,7 @@ class TestTime(HarmlessMixedComparison, unittest.TestCase):
             green = pickler.dumps(orig, proto)
             derived = unpickler.loads(green)
             self.assertEqual(orig, derived)
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
     def test_pickling_subclass_time(self):
         args = 20, 59, 16, 64**2
@@ -2829,6 +2832,7 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
             green = pickler.dumps(orig, proto)
             derived = unpickler.loads(green)
             self.assertEqual(orig, derived)
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
         # Try one with a tzinfo.
         tinfo = PicklableFixedOffset(-300, 'cookie')
@@ -2840,6 +2844,7 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
             self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
             self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
             self.assertEqual(derived.tzname(), 'cookie')
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
     def test_more_bool(self):
         # time is always True.
@@ -3043,6 +3048,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
             green = pickler.dumps(orig, proto)
             derived = unpickler.loads(green)
             self.assertEqual(orig, derived)
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
         # Try one with a tzinfo.
         tinfo = PicklableFixedOffset(-300, 'cookie')
@@ -3055,6 +3061,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
             self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
             self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
             self.assertEqual(derived.tzname(), 'cookie')
+        self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
 
     def test_extreme_hashes(self):
         # If an attempt is made to hash these via subtracting the offset
index 5e0610477742eb9f76531072a8c0ae86426f058a..de614eee4c6ca46ad5baed575d528fef97abc055 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -42,6 +42,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #28752: Restored the __reduce__() methods of datetime objects.
+
 - Issue #28727: Regular expression patterns, _sre.SRE_Pattern objects created
   by re.compile(), become comparable (only x==y and x!=y operators). This
   change should fix the issue #18383: don't duplicate warning filters when the
index d0ddcc2daa3f34984c6c1c816d110505185d60d9..c09cce9da725aaa80731085e9e372359a0640e71 100644 (file)
@@ -3955,15 +3955,21 @@ time_getstate(PyDateTime_Time *self, int proto)
 }
 
 static PyObject *
-time_reduce(PyDateTime_Time *self, PyObject *args)
+time_reduce_ex(PyDateTime_Time *self, PyObject *args)
 {
-    int proto = 0;
-    if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))
+    int proto;
+    if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
         return NULL;
 
     return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto));
 }
 
+static PyObject *
+time_reduce(PyDateTime_Time *self, PyObject *arg)
+{
+    return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2));
+}
+
 static PyMethodDef time_methods[] = {
 
     {"isoformat",   (PyCFunction)time_isoformat,        METH_VARARGS | METH_KEYWORDS,
@@ -3989,9 +3995,12 @@ static PyMethodDef time_methods[] = {
     {"replace",     (PyCFunction)time_replace,          METH_VARARGS | METH_KEYWORDS,
      PyDoc_STR("Return time with new specified fields.")},
 
-    {"__reduce_ex__", (PyCFunction)time_reduce,        METH_VARARGS,
+    {"__reduce_ex__", (PyCFunction)time_reduce_ex,        METH_VARARGS,
      PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
 
+    {"__reduce__", (PyCFunction)time_reduce,        METH_NOARGS,
+     PyDoc_STR("__reduce__() -> (cls, state)")},
+
     {NULL,      NULL}
 };
 
@@ -5420,15 +5429,21 @@ datetime_getstate(PyDateTime_DateTime *self, int proto)
 }
 
 static PyObject *
-datetime_reduce(PyDateTime_DateTime *self, PyObject *args)
+datetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args)
 {
-    int proto = 0;
-    if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))
+    int proto;
+    if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
         return NULL;
 
     return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto));
 }
 
+static PyObject *
+datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
+{
+    return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2));
+}
+
 static PyMethodDef datetime_methods[] = {
 
     /* Class methods: */
@@ -5503,9 +5518,12 @@ static PyMethodDef datetime_methods[] = {
     {"astimezone",  (PyCFunction)datetime_astimezone, METH_VARARGS | METH_KEYWORDS,
      PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
 
-    {"__reduce_ex__", (PyCFunction)datetime_reduce,     METH_VARARGS,
+    {"__reduce_ex__", (PyCFunction)datetime_reduce_ex,     METH_VARARGS,
      PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
 
+    {"__reduce__", (PyCFunction)datetime_reduce,     METH_NOARGS,
+     PyDoc_STR("__reduce__() -> (cls, state)")},
+
     {NULL,      NULL}
 };