[Python-checkins] python/nondist/sandbox/datetime datetime.c,1.32,1.33 obj_date.c,1.13,1.14 obj_datetime.c,1.7,1.8 test_both.py,1.17,1.18
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Mon, 02 Dec 2002 11:40:45 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv15411
Modified Files:
datetime.c obj_date.c obj_datetime.c test_both.py
Log Message:
Pickling works now, but doesn't meet its primary design goal for
date and datetime: since those types require 3 arguments, __reduce__
has to supply a 3-tuple of args for the constructor to chew on, which
__setstate__ then immediately overwrites. So instead of having a
pickle that's just a short string in these cases, we also get a
pointless 3-tuple buried in the pickle. Perhaps doing this right
requires defining Yet Another constructor function? I confess I'm
not a pickling professional <wink>.
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -C2 -d -r1.32 -r1.33
*** datetime.c 2 Dec 2002 18:10:32 -0000 1.32
--- datetime.c 2 Dec 2002 19:40:41 -0000 1.33
***************
*** 536,539 ****
--- 536,541 ----
}
+ static PyObject* three_ones = NULL; /* an argument tuple for __reduce__ */
+
#include "obj_delta.c"
#include "obj_date.c"
***************
*** 564,568 ****
/* date values */
d = PyDateTime_DateType.tp_dict;
- Py_INCREF(Py_True);
if (PyDict_SetItem(d, safepickle, Py_True) < 0)
return;
--- 566,569 ----
***************
*** 652,654 ****
--- 653,673 ----
us_per_week = PyLong_FromDouble(604800000000.0);
+ {
+ /* Build (1, 1, 1) so __reduce__ for date-like objects
+ * has something to pass to the type.
+ */
+ int i;
+ PyObject *one = PyInt_FromLong(1);
+
+ if (one == NULL)
+ return;
+ three_ones = PyTuple_New(3);
+ if (three_ones == NULL)
+ return;
+ for (i = 0; i < 3; ++i) {
+ Py_INCREF(one);
+ PyTuple_SetItem(three_ones, i, one);
+ }
+ Py_DECREF(one);
+ }
}
Index: obj_date.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_date.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** obj_date.c 2 Dec 2002 06:42:28 -0000 1.13
--- obj_date.c 2 Dec 2002 19:40:42 -0000 1.14
***************
*** 372,382 ****
}
! /* XXX Broken attempt to get pickles working. An attempt to pickle
! * XXX craps out in
! * XXX
! * XXX if base is self.__class__:
! * XXX raise TypeError, "can't pickle %s objects" % base.__name__
! * XXX
! * XXX in Python's copy_reg.py. How to fix?
*/
static PyObject *
--- 372,378 ----
}
! /* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
! * in the Python implementation, the C implementation also requires
! * __reduce__, and a __safe_for_unpickling__ attr in the type object.
*/
static PyObject *
***************
*** 402,405 ****
--- 398,419 ----
}
+ /* XXX This is a ridiculously inefficient way to pickle a short string. */
+ static PyObject *
+ date_reduce(PyDateTime_Date* self)
+ {
+ PyObject* result = NULL;
+ PyObject* state;
+
+ state = date_getstate(self);
+ if (state != NULL) {
+ result = Py_BuildValue("OOO",
+ self->ob_type,
+ three_ones,
+ state);
+ Py_DECREF(state);
+ }
+ return result;
+ }
+
static PyMethodDef date_methods[] = {
/* Class methods: */
***************
*** 428,435 ****
"Return the day of the week represented by the date.\n"
"Monday == 0 ... Sunday == 6"},
- {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
- PyDoc_STR("__getstate__() -> state")},
{"__setstate__", (PyCFunction)date_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
{NULL, NULL}
};
--- 442,451 ----
"Return the day of the week represented by the date.\n"
"Monday == 0 ... Sunday == 6"},
{"__setstate__", (PyCFunction)date_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
+ {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
+ NULL},
+ {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
+ PyDoc_STR("__getstate__() -> state")},
{NULL, NULL}
};
***************
*** 455,459 ****
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! "date", /* tp_name */
sizeof(PyDateTime_Date), /* tp_basicsize */
0, /* tp_itemsize */
--- 471,476 ----
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! /* XXX When this module is renamed to datetime, change tp_name. */
! "_datetime.date", /* tp_name */
sizeof(PyDateTime_Date), /* tp_basicsize */
0, /* tp_itemsize */
Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** obj_datetime.c 2 Dec 2002 06:42:28 -0000 1.7
--- obj_datetime.c 2 Dec 2002 19:40:42 -0000 1.8
***************
*** 372,382 ****
}
! /* XXX Broken attempt to get pickles working. An attempt to pickle
! * XXX craps out in
! * XXX
! * XXX if base is self.__class__:
! * XXX raise TypeError, "can't pickle %s objects" % base.__name__
! * XXX
! * XXX in Python's copy_reg.py. How to fix?
*/
static PyObject *
--- 372,378 ----
}
! /* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
! * in the Python implementation, the C implementation also requires
! * __reduce__, and a __safe_for_unpickling__ attr in the type object.
*/
static PyObject *
***************
*** 402,422 ****
}
static PyMethodDef datetime_methods[] = {
/* Class methods: */
! {"now", (PyCFunction)datetime_now, METH_O | METH_CLASS,
"Return a new datetime that represents the current time."},
! {"today", (PyCFunction)datetime_today, METH_O | METH_CLASS,
"Return a new datetime that represents the current date."},
/* Instance methods: */
! {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
"Return ctime() style string."},
{"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
"Return the day of the week represented by the datetime.\n"
"Monday == 1 ... Sunday == 7"},
- {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
- PyDoc_STR("__getstate__() -> state")},
{"__setstate__", (PyCFunction)datetime_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
{NULL, NULL}
};
--- 398,438 ----
}
+ /* XXX This is a ridiculously inefficient way to pickle a short string. */
+ static PyObject *
+ datetime_reduce(PyDateTime_DateTime* self)
+ {
+ PyObject* result = NULL;
+ PyObject* state;
+
+ state = datetime_getstate(self);
+ if (state != NULL) {
+ result = Py_BuildValue("OOO",
+ self->ob_type,
+ three_ones,
+ state);
+ Py_DECREF(state);
+ }
+ return result;
+ }
+
static PyMethodDef datetime_methods[] = {
/* Class methods: */
! {"now", (PyCFunction)datetime_now, METH_O | METH_CLASS,
"Return a new datetime that represents the current time."},
! {"today", (PyCFunction)datetime_today, METH_O | METH_CLASS,
"Return a new datetime that represents the current date."},
/* Instance methods: */
! {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
"Return ctime() style string."},
{"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
"Return the day of the week represented by the datetime.\n"
"Monday == 1 ... Sunday == 7"},
{"__setstate__", (PyCFunction)datetime_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
+ {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS,
+ NULL},
+ {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
+ PyDoc_STR("__getstate__() -> state")},
{NULL, NULL}
};
***************
*** 442,446 ****
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! "datetime", /* tp_name */
sizeof(PyDateTime_DateTime), /* tp_basicsize */
0, /* tp_itemsize */
--- 458,463 ----
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! /* XXX When this module is renamed to datetime, change tp_name. */
! "_datetime.datetime", /* tp_name */
sizeof(PyDateTime_DateTime), /* tp_basicsize */
0, /* tp_itemsize */
Index: test_both.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_both.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** test_both.py 2 Dec 2002 18:10:34 -0000 1.17
--- test_both.py 2 Dec 2002 19:40:42 -0000 1.18
***************
*** 18,24 ****
# Import the right implementation, under name "datetime".
! if 'c' in sys.argv:
print "Testing the C implementation."
import _datetime as datetime
else:
print "Testing the Python implementation."
--- 18,26 ----
# Import the right implementation, under name "datetime".
! TESTING_C = 'c' in sys.argv
! if TESTING_C:
print "Testing the C implementation."
import _datetime as datetime
+ import _datetime
else:
print "Testing the Python implementation."
***************
*** 409,414 ****
for pickler in pickle, cPickle:
for binary in 0, 1:
- # XXX Pickling fails in the C implementation.
- # XXX Needs to be fixed as for timedelta.
green = pickler.dumps(orig, binary)
derived = pickler.loads(green)
--- 411,414 ----
***************
*** 448,452 ****
self.theclass.now()):
# Verify dt -> string -> datetime identity.
! s = 'datetime.' + repr(dt)
dt2 = eval(s)
self.assertEqual(dt, dt2)
--- 448,460 ----
self.theclass.now()):
# Verify dt -> string -> datetime identity.
! s = repr(dt)
! if not TESTING_C:
! # XXX This hack is due to that the Python implementation of
! # XXX type datetime calls its name 'datetime', but that's a
! # XXX module object here. The C implementation calls its name
! # XXX '_datetime.datetime', so doesn't need a hack.
! # XXX This can get simpler when the Python implementation goes
! # XXX away.
! s = 'datetime.' + s
dt2 = eval(s)
self.assertEqual(dt, dt2)
***************
*** 621,626 ****
for pickler in pickle, cPickle:
for binary in 0, 1:
- # XXX Pickling fails in the C implementation.
- # XXX Needs to be fixed as for timedelta.
green = pickler.dumps(orig, binary)
derived = pickler.loads(green)
--- 629,632 ----