Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 506be28

Browse files
committed
The various datetime object __setstate__() methods are no longer public
(pickling no longer needs them, and immutable objects shouldn't have visible __setstate__() methods regardless). Rearranged the code to put the internal setstate functions in the constructor sections. Repaired the timedelta reduce() method, which was still producing stuff that required a public timedelta.__setstate__() when unpickling.
1 parent 96940c9 commit 506be28

2 files changed

Lines changed: 111 additions & 117 deletions

File tree

Misc/NEWS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Core and builtins
2424
See SF bug #667147.
2525

2626
- Fixed an invalid RuntimeWarning and an undetected error when trying
27-
to convert a long integer into a float which couldn't fit.
27+
to convert a long integer into a float which couldn't fit.
2828
See SF bug #676155.
2929

3030
Extension modules
@@ -126,6 +126,11 @@ Extension modules
126126
possible to have timestamps that differ by a second, yet where
127127
datetimes constructed from them are equal.
128128

129+
The pickle format of date, time and datetime objects has changed
130+
completely. The undocumented pickler and unpickler functions no
131+
longer exist. The undocumented __setstate__() methods no longer
132+
exist either.
133+
129134
Library
130135
-------
131136

Modules/datetimemodule.c

Lines changed: 105 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,7 @@ delta_getstate(PyDateTime_Delta *self)
19591959
GET_TD_MICROSECONDS(self));
19601960
}
19611961

1962+
/* __setstate__ isn't exposed. */
19621963
static PyObject *
19631964
delta_setstate(PyDateTime_Delta *self, PyObject *state)
19641965
{
@@ -1988,7 +1989,11 @@ delta_reduce(PyDateTime_Delta* self)
19881989
/* The funky "()" in the format string creates an empty
19891990
* tuple as the 2nd component of the result 3-tuple.
19901991
*/
1991-
result = Py_BuildValue("O()O", self->ob_type, state);
1992+
result = Py_BuildValue("O(iii)",
1993+
self->ob_type,
1994+
self->days,
1995+
self->seconds,
1996+
self->microseconds);
19921997
Py_DECREF(state);
19931998
}
19941999
return result;
@@ -2010,10 +2015,6 @@ static PyMemberDef delta_members[] = {
20102015
};
20112016

20122017
static PyMethodDef delta_methods[] = {
2013-
2014-
{"__setstate__", (PyCFunction)delta_setstate, METH_O,
2015-
PyDoc_STR("__setstate__(state)")},
2016-
20172018
{"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
20182019
PyDoc_STR("__getstate__() -> state")},
20192020

@@ -2145,7 +2146,35 @@ static PyGetSetDef date_getset[] = {
21452146

21462147
static char *date_kws[] = {"year", "month", "day", NULL};
21472148

2148-
static PyObject *date_setstate(PyDateTime_Date *self, PyObject *arg);
2149+
/* __setstate__ isn't exposed. */
2150+
static PyObject *
2151+
date_setstate(PyDateTime_Date *self, PyObject *arg)
2152+
{
2153+
PyObject *state;
2154+
int len;
2155+
unsigned char *pdata;
2156+
2157+
if (!PyTuple_Check(arg) || PyTuple_GET_SIZE(arg) != 1)
2158+
goto error;
2159+
state = PyTuple_GET_ITEM(arg, 0);
2160+
if (!PyString_Check(state))
2161+
goto error;
2162+
2163+
len = PyString_Size(state);
2164+
if (len != _PyDateTime_DATE_DATASIZE)
2165+
goto error;
2166+
2167+
pdata = (unsigned char*)PyString_AsString(state);
2168+
memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2169+
self->hashcode = -1;
2170+
2171+
Py_INCREF(Py_None);
2172+
return Py_None;
2173+
error:
2174+
PyErr_SetString(PyExc_TypeError,
2175+
"bad argument to date.__setstate__");
2176+
return NULL;
2177+
}
21492178

21502179
static PyObject *
21512180
date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
@@ -2541,35 +2570,6 @@ date_getstate(PyDateTime_Date *self)
25412570
_PyDateTime_DATE_DATASIZE));
25422571
}
25432572

2544-
static PyObject *
2545-
date_setstate(PyDateTime_Date *self, PyObject *arg)
2546-
{
2547-
PyObject *state;
2548-
int len;
2549-
unsigned char *pdata;
2550-
2551-
if (!PyTuple_Check(arg) || PyTuple_GET_SIZE(arg) != 1)
2552-
goto error;
2553-
state = PyTuple_GET_ITEM(arg, 0);
2554-
if (!PyString_Check(state))
2555-
goto error;
2556-
2557-
len = PyString_Size(state);
2558-
if (len != _PyDateTime_DATE_DATASIZE)
2559-
goto error;
2560-
2561-
pdata = (unsigned char*)PyString_AsString(state);
2562-
memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2563-
self->hashcode = -1;
2564-
2565-
Py_INCREF(Py_None);
2566-
return Py_None;
2567-
error:
2568-
PyErr_SetString(PyExc_TypeError,
2569-
"bad argument to date.__setstate__");
2570-
return NULL;
2571-
}
2572-
25732573
static PyObject *
25742574
date_reduce(PyDateTime_Date *self, PyObject *arg)
25752575
{
@@ -2627,9 +2627,6 @@ static PyMethodDef date_methods[] = {
26272627
{"replace", (PyCFunction)date_replace, METH_KEYWORDS,
26282628
PyDoc_STR("Return date with new specified fields.")},
26292629

2630-
{"__setstate__", (PyCFunction)date_setstate, METH_O,
2631-
PyDoc_STR("__setstate__(state)")},
2632-
26332630
{"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
26342631
PyDoc_STR("__getstate__() -> state")},
26352632

@@ -3012,7 +3009,41 @@ static PyGetSetDef time_getset[] = {
30123009
static char *time_kws[] = {"hour", "minute", "second", "microsecond",
30133010
"tzinfo", NULL};
30143011

3015-
static PyObject *time_setstate(PyDateTime_Time *self, PyObject *state);
3012+
/* __setstate__ isn't exposed. */
3013+
static PyObject *
3014+
time_setstate(PyDateTime_Time *self, PyObject *state)
3015+
{
3016+
PyObject *basestate;
3017+
PyObject *tzinfo = Py_None;
3018+
3019+
if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
3020+
&PyString_Type, &basestate,
3021+
&tzinfo))
3022+
return NULL;
3023+
if (PyString_Size(basestate) != _PyDateTime_TIME_DATASIZE ||
3024+
check_tzinfo_subclass(tzinfo) < 0) {
3025+
PyErr_SetString(PyExc_TypeError,
3026+
"bad argument to time.__setstate__");
3027+
return NULL;
3028+
}
3029+
if (tzinfo != Py_None && ! HASTZINFO(self)) {
3030+
PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
3031+
"add a non-None tzinfo to a time object that "
3032+
"doesn't have one already");
3033+
return NULL;
3034+
}
3035+
memcpy((char *)self->data,
3036+
PyString_AsString(basestate),
3037+
_PyDateTime_TIME_DATASIZE);
3038+
self->hashcode = -1;
3039+
if (HASTZINFO(self)) {
3040+
Py_INCREF(tzinfo);
3041+
Py_XDECREF(self->tzinfo);
3042+
self->tzinfo = tzinfo;
3043+
}
3044+
Py_INCREF(Py_None);
3045+
return Py_None;
3046+
}
30163047

30173048
static PyObject *
30183049
time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
@@ -3366,41 +3397,6 @@ time_getstate(PyDateTime_Time *self)
33663397
return result;
33673398
}
33683399

3369-
static PyObject *
3370-
time_setstate(PyDateTime_Time *self, PyObject *state)
3371-
{
3372-
PyObject *basestate;
3373-
PyObject *tzinfo = Py_None;
3374-
3375-
if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
3376-
&PyString_Type, &basestate,
3377-
&tzinfo))
3378-
return NULL;
3379-
if (PyString_Size(basestate) != _PyDateTime_TIME_DATASIZE ||
3380-
check_tzinfo_subclass(tzinfo) < 0) {
3381-
PyErr_SetString(PyExc_TypeError,
3382-
"bad argument to time.__setstate__");
3383-
return NULL;
3384-
}
3385-
if (tzinfo != Py_None && ! HASTZINFO(self)) {
3386-
PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
3387-
"add a non-None tzinfo to a time object that "
3388-
"doesn't have one already");
3389-
return NULL;
3390-
}
3391-
memcpy((char *)self->data,
3392-
PyString_AsString(basestate),
3393-
_PyDateTime_TIME_DATASIZE);
3394-
self->hashcode = -1;
3395-
if (HASTZINFO(self)) {
3396-
Py_INCREF(tzinfo);
3397-
Py_XDECREF(self->tzinfo);
3398-
self->tzinfo = tzinfo;
3399-
}
3400-
Py_INCREF(Py_None);
3401-
return Py_None;
3402-
}
3403-
34043400
static PyObject *
34053401
time_reduce(PyDateTime_Time *self, PyObject *arg)
34063402
{
@@ -3428,9 +3424,6 @@ static PyMethodDef time_methods[] = {
34283424
{"replace", (PyCFunction)time_replace, METH_KEYWORDS,
34293425
PyDoc_STR("Return time with new specified fields.")},
34303426

3431-
{"__setstate__", (PyCFunction)time_setstate, METH_O,
3432-
PyDoc_STR("__setstate__(state)")},
3433-
34343427
{"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
34353428
PyDoc_STR("__getstate__() -> state")},
34363429

@@ -3559,7 +3552,41 @@ static char *datetime_kws[] = {
35593552
"microsecond", "tzinfo", NULL
35603553
};
35613554

3562-
static PyObject *datetime_setstate(PyDateTime_DateTime *self, PyObject *state);
3555+
/* __setstate__ isn't exposed. */
3556+
static PyObject *
3557+
datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
3558+
{
3559+
PyObject *basestate;
3560+
PyObject *tzinfo = Py_None;
3561+
3562+
if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
3563+
&PyString_Type, &basestate,
3564+
&tzinfo))
3565+
return NULL;
3566+
if (PyString_Size(basestate) != _PyDateTime_DATETIME_DATASIZE ||
3567+
check_tzinfo_subclass(tzinfo) < 0) {
3568+
PyErr_SetString(PyExc_TypeError,
3569+
"bad argument to datetime.__setstate__");
3570+
return NULL;
3571+
}
3572+
if (tzinfo != Py_None && ! HASTZINFO(self)) {
3573+
PyErr_SetString(PyExc_ValueError, "datetime.__setstate__ "
3574+
"can't add a non-None tzinfo to a datetime "
3575+
"object that doesn't have one already");
3576+
return NULL;
3577+
}
3578+
memcpy((char *)self->data,
3579+
PyString_AsString(basestate),
3580+
_PyDateTime_DATETIME_DATASIZE);
3581+
self->hashcode = -1;
3582+
if (HASTZINFO(self)) {
3583+
Py_INCREF(tzinfo);
3584+
Py_XDECREF(self->tzinfo);
3585+
self->tzinfo = tzinfo;
3586+
}
3587+
Py_INCREF(Py_None);
3588+
return Py_None;
3589+
}
35633590

35643591
static PyObject *
35653592
datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
@@ -4370,41 +4397,6 @@ datetime_getstate(PyDateTime_DateTime *self)
43704397
return result;
43714398
}
43724399

4373-
static PyObject *
4374-
datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
4375-
{
4376-
PyObject *basestate;
4377-
PyObject *tzinfo = Py_None;
4378-
4379-
if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4380-
&PyString_Type, &basestate,
4381-
&tzinfo))
4382-
return NULL;
4383-
if (PyString_Size(basestate) != _PyDateTime_DATETIME_DATASIZE ||
4384-
check_tzinfo_subclass(tzinfo) < 0) {
4385-
PyErr_SetString(PyExc_TypeError,
4386-
"bad argument to datetime.__setstate__");
4387-
return NULL;
4388-
}
4389-
if (tzinfo != Py_None && ! HASTZINFO(self)) {
4390-
PyErr_SetString(PyExc_ValueError, "datetime.__setstate__ "
4391-
"can't add a non-None tzinfo to a datetime "
4392-
"object that doesn't have one already");
4393-
return NULL;
4394-
}
4395-
memcpy((char *)self->data,
4396-
PyString_AsString(basestate),
4397-
_PyDateTime_DATETIME_DATASIZE);
4398-
self->hashcode = -1;
4399-
if (HASTZINFO(self)) {
4400-
Py_INCREF(tzinfo);
4401-
Py_XDECREF(self->tzinfo);
4402-
self->tzinfo = tzinfo;
4403-
}
4404-
Py_INCREF(Py_None);
4405-
return Py_None;
4406-
}
4407-
44084400
static PyObject *
44094401
datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
44104402
{
@@ -4477,9 +4469,6 @@ static PyMethodDef datetime_methods[] = {
44774469
{"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
44784470
PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
44794471

4480-
{"__setstate__", (PyCFunction)datetime_setstate, METH_O,
4481-
PyDoc_STR("__setstate__(state)")},
4482-
44834472
{"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
44844473
PyDoc_STR("__getstate__() -> state")},
44854474

0 commit comments

Comments
 (0)