]> granicus.if.org Git - python/commitdiff
New functions alloc_{time,datetime}. Got rid of all setstate-like
authorTim Peters <tim.peters@gmail.com>
Sat, 1 Feb 2003 04:40:04 +0000 (04:40 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 1 Feb 2003 04:40:04 +0000 (04:40 +0000)
functions.  Reworked {time,datetime}_new() to do what their corresponding
setstates used to do in their state-tuple-input paths, but directly,
without constructing an object with throwaway state first.  Tightened
the "is this a state tuple input?" paths to check the presumed state
string-length too, and to raise an exception if the optional second state
element isn't a tzinfo instance (IOW, check these paths for type errors
as carefully as the normal paths).

Modules/datetimemodule.c

index ba2b737d4933f2517b18ec40382851de94d24126..944c0bbea924d9d04044cc57125a4cfeb2dbecb7 100644 (file)
@@ -1224,6 +1224,42 @@ diff_to_bool(int diff, int op)
        return result;
 }
 
+/* ---------------------------------------------------------------------------
+ * Basic object allocation.  These allocate Python objects of the right
+ * size and type, and do the Python object-initialization bit.  If there's
+ * not enough memory, they return NULL after setting MemoryError.  All
+ * data members remain uninitialized trash.
+ */
+static PyDateTime_Time *
+alloc_time(int aware)
+{
+       PyDateTime_Time *self;
+
+       self = (PyDateTime_Time *)
+               PyObject_MALLOC(aware ?
+                               sizeof(PyDateTime_Time) :
+                               sizeof(_PyDateTime_BaseTime));
+       if (self == NULL)
+               return (PyDateTime_Time *)PyErr_NoMemory();
+       PyObject_INIT(self, &PyDateTime_TimeType);
+       return self;
+}
+
+static PyDateTime_DateTime *
+alloc_datetime(int aware)
+{
+       PyDateTime_DateTime *self;
+
+       self = (PyDateTime_DateTime *)
+               PyObject_MALLOC(aware ?
+                               sizeof(PyDateTime_DateTime) :
+                               sizeof(_PyDateTime_BaseDateTime));
+       if (self == NULL)
+               return (PyDateTime_DateTime *)PyErr_NoMemory();
+       PyObject_INIT(self, &PyDateTime_DateTimeType);
+       return self;
+}
+
 /* ---------------------------------------------------------------------------
  * Helpers for setting object fields.  These work on pointers to the
  * appropriate base class.
@@ -1263,22 +1299,20 @@ new_datetime(int year, int month, int day, int hour, int minute,
        PyDateTime_DateTime *self;
        char aware = tzinfo != Py_None;
 
-       self = (PyDateTime_DateTime *)PyObject_MALLOC(aware ?
-                                       sizeof(PyDateTime_DateTime) :
-                                       sizeof(_PyDateTime_BaseDateTime));
-       if (self == NULL)
-               return PyErr_NoMemory();
-       self->hastzinfo = aware;
-       set_date_fields((PyDateTime_Date *)self, year, month, day);
-       DATE_SET_HOUR(self, hour);
-       DATE_SET_MINUTE(self, minute);
-       DATE_SET_SECOND(self, second);
-       DATE_SET_MICROSECOND(self, usecond);
-       if (aware) {
-               Py_INCREF(tzinfo);
-               self->tzinfo = tzinfo;
+       self = alloc_datetime(aware);
+       if (self != NULL) {
+               self->hastzinfo = aware;
+               set_date_fields((PyDateTime_Date *)self, year, month, day);
+               DATE_SET_HOUR(self, hour);
+               DATE_SET_MINUTE(self, minute);
+               DATE_SET_SECOND(self, second);
+               DATE_SET_MICROSECOND(self, usecond);
+               if (aware) {
+                       Py_INCREF(tzinfo);
+                       self->tzinfo = tzinfo;
+               }
        }
-       return (PyObject *)PyObject_INIT(self, &PyDateTime_DateTimeType);
+       return (PyObject *)self;
 }
 
 /* Create a time instance with no range checking. */
@@ -1288,22 +1322,20 @@ new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
        PyDateTime_Time *self;
        char aware = tzinfo != Py_None;
 
-       self = (PyDateTime_Time *)PyObject_MALLOC(aware ?
-                               sizeof(PyDateTime_Time) :
-                               sizeof(_PyDateTime_BaseTime));
-       if (self == NULL)
-               return PyErr_NoMemory();
-       self->hastzinfo = aware;
-       self->hashcode = -1;
-       TIME_SET_HOUR(self, hour);
-       TIME_SET_MINUTE(self, minute);
-       TIME_SET_SECOND(self, second);
-       TIME_SET_MICROSECOND(self, usecond);
-       if (aware) {
-               Py_INCREF(tzinfo);
-               self->tzinfo = tzinfo;
+       self = alloc_time(aware);
+       if (self != NULL) {
+               self->hastzinfo = aware;
+               self->hashcode = -1;
+               TIME_SET_HOUR(self, hour);
+               TIME_SET_MINUTE(self, minute);
+               TIME_SET_SECOND(self, second);
+               TIME_SET_MICROSECOND(self, usecond);
+               if (aware) {
+                       Py_INCREF(tzinfo);
+                       self->tzinfo = tzinfo;
+               }
        }
-       return (PyObject *)PyObject_INIT(self, &PyDateTime_TimeType);
+       return (PyObject *)self;
 }
 
 /* Create a timedelta instance.  Normalize the members iff normalize is
@@ -2108,60 +2140,29 @@ static PyGetSetDef date_getset[] = {
 
 static char *date_kws[] = {"year", "month", "day", NULL};
 
-/* __setstate__ isn't exposed. */
-static PyObject *
-date_setstate(PyDateTime_Date *self, PyObject *arg)
-{
-       PyObject *state;
-       int len;
-       unsigned char *pdata;
-
-       if (!PyTuple_Check(arg) || PyTuple_GET_SIZE(arg) != 1)
-               goto error;
-       state = PyTuple_GET_ITEM(arg, 0);
-       if (!PyString_Check(state))
-               goto error;
-
-       len = PyString_Size(state);
-       if (len != _PyDateTime_DATE_DATASIZE)
-               goto error;
-
-       pdata = (unsigned char*)PyString_AsString(state);
-       memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
-       self->hashcode = -1;
-
-       Py_INCREF(Py_None);
-       return Py_None;
- error:
-       PyErr_SetString(PyExc_TypeError,
-                       "bad argument to date.__setstate__");
-       return NULL;
-}
-
 static PyObject *
 date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
        PyObject *self = NULL;
+       PyObject *state;
        int year;
        int month;
        int day;
 
        /* Check for invocation from pickle with __getstate__ state */
        if (PyTuple_GET_SIZE(args) == 1 &&
-           PyString_Check(PyTuple_GET_ITEM(args, 0)))
+           PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+           PyString_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE)
        {
-               self = new_date(1, 1, 1);
-               if (self != NULL) {
-                       PyObject *res = date_setstate(
-                               (PyDateTime_Date *)self, args);
-                       if (res == Py_None)
-                               Py_DECREF(res);
-                       else {
-                               Py_DECREF(self);
-                               self = NULL;
-                       }
+               PyDateTime_Date *me;
+
+               me = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
+               if (me != NULL) {
+                       char *pdata = PyString_AS_STRING(state);
+                       memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
+                       me->hashcode = -1;
                }
-               return self;
+               return (PyObject *)me;
        }
 
        if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
@@ -2969,46 +2970,11 @@ static PyGetSetDef time_getset[] = {
 static char *time_kws[] = {"hour", "minute", "second", "microsecond",
                           "tzinfo", NULL};
 
-/* __setstate__ isn't exposed. */
-static PyObject *
-time_setstate(PyDateTime_Time *self, PyObject *state)
-{
-       PyObject *basestate;
-       PyObject *tzinfo = Py_None;
-
-       if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
-                              &PyString_Type, &basestate,
-                              &tzinfo))
-               return NULL;
-       if (PyString_Size(basestate) !=  _PyDateTime_TIME_DATASIZE ||
-           check_tzinfo_subclass(tzinfo) < 0) {
-               PyErr_SetString(PyExc_TypeError,
-                               "bad argument to time.__setstate__");
-               return NULL;
-       }
-       if (tzinfo != Py_None && ! HASTZINFO(self)) {
-               PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
-                               "add a non-None tzinfo to a time object that "
-                               "doesn't have one already");
-               return NULL;
-       }
-       memcpy((char *)self->data,
-              PyString_AsString(basestate),
-              _PyDateTime_TIME_DATASIZE);
-       self->hashcode = -1;
-       if (HASTZINFO(self)) {
-               Py_INCREF(tzinfo);
-               Py_XDECREF(self->tzinfo);
-               self->tzinfo = tzinfo;
-       }
-       Py_INCREF(Py_None);
-       return Py_None;
-}
-
 static PyObject *
 time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
        PyObject *self = NULL;
+       PyObject *state;
        int hour = 0;
        int minute = 0;
        int second = 0;
@@ -3018,22 +2984,34 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
        /* Check for invocation from pickle with __getstate__ state */
        if (PyTuple_GET_SIZE(args) >= 1 &&
            PyTuple_GET_SIZE(args) <= 2 &&
-           PyString_Check(PyTuple_GET_ITEM(args, 0)))
+           PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+           PyString_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE)
        {
-               if (PyTuple_GET_SIZE(args) == 2)
+               PyDateTime_Time *me;
+               char aware;
+
+               if (PyTuple_GET_SIZE(args) == 2) {
                        tzinfo = PyTuple_GET_ITEM(args, 1);
-               self = new_time(0, 0, 0, 0, tzinfo);
-               if (self != NULL) {
-                       PyObject *res = time_setstate(
-                               (PyDateTime_Time *)self, args);
-                       if (res == Py_None)
-                               Py_DECREF(res);
-                       else {
-                               Py_DECREF(self);
-                               self = NULL;
+                       if (check_tzinfo_subclass(tzinfo) < 0) {
+                               PyErr_SetString(PyExc_TypeError, "bad "
+                                       "tzinfo state arg");
+                               return NULL;
                        }
                }
-               return self;
+               aware = (char)(tzinfo != Py_None);
+               me = alloc_time(aware);
+               if (me != NULL) {
+                       char *pdata = PyString_AS_STRING(state);
+
+                       memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
+                       me->hashcode = -1;
+                       me->hastzinfo = aware;
+                       if (aware) {
+                               Py_INCREF(tzinfo);
+                               me->tzinfo = tzinfo;
+                       }
+               }
+               return (PyObject *)me;
        }
 
        if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
@@ -3508,46 +3486,11 @@ static char *datetime_kws[] = {
        "microsecond", "tzinfo", NULL
 };
 
-/* __setstate__ isn't exposed. */
-static PyObject *
-datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
-{
-       PyObject *basestate;
-       PyObject *tzinfo = Py_None;
-
-       if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
-                              &PyString_Type, &basestate,
-                              &tzinfo))
-               return NULL;
-       if (PyString_Size(basestate) !=  _PyDateTime_DATETIME_DATASIZE ||
-           check_tzinfo_subclass(tzinfo) < 0) {
-               PyErr_SetString(PyExc_TypeError,
-                               "bad argument to datetime.__setstate__");
-               return NULL;
-       }
-       if (tzinfo != Py_None && ! HASTZINFO(self)) {
-               PyErr_SetString(PyExc_ValueError, "datetime.__setstate__ "
-                               "can't add a non-None tzinfo to a datetime "
-                               "object that doesn't have one already");
-               return NULL;
-       }
-       memcpy((char *)self->data,
-              PyString_AsString(basestate),
-              _PyDateTime_DATETIME_DATASIZE);
-       self->hashcode = -1;
-       if (HASTZINFO(self)) {
-               Py_INCREF(tzinfo);
-               Py_XDECREF(self->tzinfo);
-               self->tzinfo = tzinfo;
-       }
-       Py_INCREF(Py_None);
-       return Py_None;
-}
-
 static PyObject *
 datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
        PyObject *self = NULL;
+       PyObject *state;
        int year;
        int month;
        int day;
@@ -3560,22 +3503,34 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
        /* Check for invocation from pickle with __getstate__ state */
        if (PyTuple_GET_SIZE(args) >= 1 &&
            PyTuple_GET_SIZE(args) <= 2 &&
-           PyString_Check(PyTuple_GET_ITEM(args, 0)))
+           PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+           PyString_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE)
        {
-               if (PyTuple_GET_SIZE(args) == 2)
+               PyDateTime_DateTime *me;
+               char aware;
+
+               if (PyTuple_GET_SIZE(args) == 2) {
                        tzinfo = PyTuple_GET_ITEM(args, 1);
-               self = new_datetime(1, 1, 1, 0, 0, 0, 0, tzinfo);
-               if (self != NULL) {
-                       PyObject *res = datetime_setstate(
-                               (PyDateTime_DateTime *)self, args);
-                       if (res == Py_None)
-                               Py_DECREF(res);
-                       else {
-                               Py_DECREF(self);
-                               self = NULL;
+                       if (check_tzinfo_subclass(tzinfo) < 0) {
+                               PyErr_SetString(PyExc_TypeError, "bad "
+                                       "tzinfo state arg");
+                               return NULL;
+                       }
+               }
+               aware = (char)(tzinfo != Py_None);
+               me = alloc_datetime(aware);
+               if (me != NULL) {
+                       char *pdata = PyString_AS_STRING(state);
+
+                       memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
+                       me->hashcode = -1;
+                       me->hastzinfo = aware;
+                       if (aware) {
+                               Py_INCREF(tzinfo);
+                               me->tzinfo = tzinfo;
                        }
                }
-               return self;
+               return (PyObject *)me;
        }
 
        if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetime_kws,