diff -r 37e9e49f2293 Include/datetime.h --- a/Include/datetime.h Tue Aug 14 19:39:41 2012 +0200 +++ b/Include/datetime.h Tue Aug 14 20:06:45 2012 +0200 @@ -7,6 +7,43 @@ extern "C" { #endif +typedef struct { + /* Forward declarations. */ + PyObject *PyDateTime_DateType; + PyObject *PyDateTime_DateTimeType; + PyObject *PyDateTime_DeltaType; + PyObject *PyDateTime_TimeType; + PyObject *PyDateTime_TZInfoType; + PyObject *PyDateTime_TimeZoneType; + /* + * Cached Python objects; these are set by the module init function. + */ + PyObject *us_per_us; /* 1 */ + PyObject *us_per_ms; /* 1000 */ + PyObject *us_per_second; /* 1000000 */ + PyObject *us_per_minute; /* 1e6 * 60 as Python int */ + PyObject *us_per_hour; /* 1e6 * 3600 as Python long */ + PyObject *us_per_day; /* 1e6 * 3600 * 24 as Python long */ + PyObject *us_per_week; /* 1e6*3600*24*7 as Python long */ + PyObject *seconds_per_day; /* 3600*24 as Python int */ + /* The interned UTC timezone instance */ + PyObject *PyDateTime_TimeZone_UTC; + /* The interned Epoch datetime instance */ + PyObject *PyDateTime_Epoch; +} _datetimemodulestate; + +#define _datetimemodulestate(o) ((_datetimemodulestate *)PyModule_GetState(o)) + +static struct PyModuleDef _datetimemodule; + +#ifdef Py_DEBUG +PyObject* _Get_State(struct PyModuleDef*); +#define _datetimemodulestate_global ((_datetimemodulestate *) \ + _Get_State(&_datetimemodule)) +#else +#define _datetimemodulestate_global ((_datetimemodulestate *) \ + PyModule_GetState(PyState_FindModule(&_datetimemodule))) +#endif /* Fields are packed into successive bytes, each viewed as unsigned and * big-endian, unless otherwise noted: * @@ -170,20 +207,30 @@ #ifdef Py_BUILD_CORE /* Macros for type checking when building the Python core. */ -#define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType) -#define PyDate_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DateType) +#define PyDate_Check(op) PyObject_TypeCheck(op, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateType) +#define PyDate_CheckExact(op) (Py_TYPE(op) == \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateType) -#define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType) -#define PyDateTime_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DateTimeType) +#define PyDateTime_Check(op) PyObject_TypeCheck(op, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateTimeType) +#define PyDateTime_CheckExact(op) (Py_TYPE(op) == \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateTimeType) -#define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType) -#define PyTime_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TimeType) +#define PyTime_Check(op) PyObject_TypeCheck(op, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TimeType) +#define PyTime_CheckExact(op) (Py_TYPE(op) == \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TimeType) -#define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType) -#define PyDelta_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DeltaType) +#define PyDelta_Check(op) PyObject_TypeCheck(op, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DeltaType) +#define PyDelta_CheckExact(op) (Py_TYPE(op) == \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DeltaType) -#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) -#define PyTZInfo_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TZInfoType) +#define PyTZInfo_Check(op) PyObject_TypeCheck(op, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TZInfoType) +#define PyTZInfo_CheckExact(op) (Py_TYPE(op) == \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TZInfoType) #else diff -r 37e9e49f2293 Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c Tue Aug 14 19:39:41 2012 +0200 +++ b/Modules/_datetimemodule.c Tue Aug 14 20:06:45 2012 +0200 @@ -96,13 +96,74 @@ */ #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) -/* Forward declarations. */ -static PyTypeObject PyDateTime_DateType; -static PyTypeObject PyDateTime_DateTimeType; -static PyTypeObject PyDateTime_DeltaType; -static PyTypeObject PyDateTime_TimeType; -static PyTypeObject PyDateTime_TZInfoType; -static PyTypeObject PyDateTime_TimeZoneType; +#ifdef Py_DEBUG +PyObject* +_Get_State(struct PyModuleDef* def) +{ + PyObject *module = PyState_FindModule(def); + assert(module); + PyObject *state = PyModule_GetState(module); + assert(state); + return state; +} +#endif + +typedef struct +{ + PyObject_HEAD + PyObject *offset; + PyObject *name; +} PyDateTime_TimeZone; + +static int +_datetimemodule_clear(PyObject *m) +{ + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_DateTimeType); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_DeltaType); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_TimeType); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_TimeZoneType); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_DateType); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_TZInfoType); + Py_CLEAR(_datetimemodulestate(m)->us_per_us); + Py_CLEAR(_datetimemodulestate(m)->us_per_ms); + Py_CLEAR(_datetimemodulestate(m)->us_per_second); + Py_CLEAR(_datetimemodulestate(m)->us_per_minute); + Py_CLEAR(_datetimemodulestate(m)->us_per_hour); + Py_CLEAR(_datetimemodulestate(m)->us_per_day); + Py_CLEAR(_datetimemodulestate(m)->us_per_week); + Py_CLEAR(_datetimemodulestate(m)->seconds_per_day); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_TimeZone_UTC); + Py_CLEAR(_datetimemodulestate(m)->PyDateTime_Epoch); + return 0; +} + +static int +_datetimemodule_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(_datetimemodulestate(m)->PyDateTime_DateTimeType); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_DeltaType); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_TimeType); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_TimeZoneType); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_DateType); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_TZInfoType); + Py_VISIT(_datetimemodulestate(m)->us_per_us); + Py_VISIT(_datetimemodulestate(m)->us_per_ms); + Py_VISIT(_datetimemodulestate(m)->us_per_second); + Py_VISIT(_datetimemodulestate(m)->us_per_minute); + Py_VISIT(_datetimemodulestate(m)->us_per_hour); + Py_VISIT(_datetimemodulestate(m)->us_per_day); + Py_VISIT(_datetimemodulestate(m)->us_per_week); + Py_VISIT(_datetimemodulestate(m)->seconds_per_day); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_TimeZone_UTC); + Py_VISIT(_datetimemodulestate(m)->PyDateTime_Epoch); + return 0; +} + +static void +_datetimemodule_free(void *m) +{ + _datetimemodule_clear((PyObject *)m); +} /* --------------------------------------------------------------------------- * Math utilities. @@ -666,7 +727,8 @@ } #define new_date(year, month, day) \ - new_date_ex(year, month, day, &PyDateTime_DateType) + new_date_ex(year, month, day, \ + (PyTypeObject *)(_datetimemodulestate_global->PyDateTime_DateType)) /* Create a datetime instance with no range checking. */ static PyObject * @@ -688,13 +750,14 @@ Py_INCREF(tzinfo); self->tzinfo = tzinfo; } + Py_INCREF(type); } return (PyObject *)self; } #define new_datetime(y, m, d, hh, mm, ss, us, tzinfo) \ new_datetime_ex(y, m, d, hh, mm, ss, us, tzinfo, \ - &PyDateTime_DateTimeType) + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateTimeType) /* Create a time instance with no range checking. */ static PyObject * @@ -716,12 +779,14 @@ Py_INCREF(tzinfo); self->tzinfo = tzinfo; } + Py_INCREF(type); } return (PyObject *)self; } -#define new_time(hh, mm, ss, us, tzinfo) \ - new_time_ex(hh, mm, ss, us, tzinfo, &PyDateTime_TimeType) +#define new_time(hh, mm, ss, us, tzinfo) \ + new_time_ex(hh, mm, ss, us, tzinfo, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TimeType) /* Create a timedelta instance. Normalize the members iff normalize is * true. Passing false is a speed optimization, if you know for sure @@ -753,21 +818,9 @@ return (PyObject *) self; } -#define new_delta(d, s, us, normalize) \ - new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType) - - -typedef struct -{ - PyObject_HEAD - PyObject *offset; - PyObject *name; -} PyDateTime_TimeZone; - -/* The interned UTC timezone instance */ -static PyObject *PyDateTime_TimeZone_UTC; -/* The interned Epoch datetime instance */ -static PyObject *PyDateTime_Epoch; +#define new_delta(d, s, us, normalize)\ + new_delta_ex(d, s, us, normalize, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DeltaType) /* Create new timezone instance checking offset range. This function does not check the name argument. Caller must assure @@ -777,7 +830,7 @@ create_timezone(PyObject *offset, PyObject *name) { PyDateTime_TimeZone *self; - PyTypeObject *type = &PyDateTime_TimeZoneType; + PyTypeObject *type = (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TimeZoneType; assert(offset != NULL); assert(PyDelta_Check(offset)); @@ -804,8 +857,8 @@ assert(name == NULL || PyUnicode_Check(name)); if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) { - Py_INCREF(PyDateTime_TimeZone_UTC); - return PyDateTime_TimeZone_UTC; + Py_INCREF(_datetimemodulestate_global->PyDateTime_TimeZone_UTC); + return _datetimemodulestate_global->PyDateTime_TimeZone_UTC; } if (GET_TD_MICROSECONDS(offset) != 0 || GET_TD_SECONDS(offset) % 60 != 0) { PyErr_Format(PyExc_ValueError, "offset must be a timedelta" @@ -1394,20 +1447,6 @@ } /* --------------------------------------------------------------------------- - * Cached Python objects; these are set by the module init function. - */ - -/* Conversion factors. */ -static PyObject *us_per_us = NULL; /* 1 */ -static PyObject *us_per_ms = NULL; /* 1000 */ -static PyObject *us_per_second = NULL; /* 1000000 */ -static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */ -static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */ -static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */ -static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */ -static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */ - -/* --------------------------------------------------------------------------- * Class implementations. */ @@ -1432,7 +1471,7 @@ x1 = PyLong_FromLong(GET_TD_DAYS(self)); if (x1 == NULL) goto Done; - x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */ + x2 = PyNumber_Multiply(x1, _datetimemodulestate_global->seconds_per_day); /* days in seconds */ if (x2 == NULL) goto Done; Py_DECREF(x1); @@ -1450,7 +1489,7 @@ /* x1 = */ x2 = NULL; /* x3 has days+seconds in seconds */ - x1 = PyNumber_Multiply(x3, us_per_second); /* us */ + x1 = PyNumber_Multiply(x3, _datetimemodulestate_global->us_per_second); /* us */ if (x1 == NULL) goto Done; Py_DECREF(x3); @@ -1483,7 +1522,7 @@ PyObject *num = NULL; PyObject *result = NULL; - tuple = PyNumber_Divmod(pyus, us_per_second); + tuple = PyNumber_Divmod(pyus, _datetimemodulestate_global->us_per_second); if (tuple == NULL) goto Done; @@ -1508,7 +1547,7 @@ Py_INCREF(num); Py_DECREF(tuple); - tuple = PyNumber_Divmod(num, seconds_per_day); + tuple = PyNumber_Divmod(num, _datetimemodulestate_global->seconds_per_day); if (tuple == NULL) goto Done; Py_DECREF(num); @@ -1551,7 +1590,8 @@ } #define microseconds_to_delta(pymicros) \ - microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType) + microseconds_to_delta_ex(pymicros, \ + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DeltaType) static PyObject * multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta) @@ -2120,31 +2160,31 @@ goto Done if (us) { - y = accum("microseconds", x, us, us_per_us, &leftover_us); + y = accum("microseconds", x, us, _datetimemodulestate_global->us_per_us, &leftover_us); CLEANUP; } if (ms) { - y = accum("milliseconds", x, ms, us_per_ms, &leftover_us); + y = accum("milliseconds", x, ms, _datetimemodulestate_global->us_per_ms, &leftover_us); CLEANUP; } if (second) { - y = accum("seconds", x, second, us_per_second, &leftover_us); + y = accum("seconds", x, second, _datetimemodulestate_global->us_per_second, &leftover_us); CLEANUP; } if (minute) { - y = accum("minutes", x, minute, us_per_minute, &leftover_us); + y = accum("minutes", x, minute, _datetimemodulestate_global->us_per_minute, &leftover_us); CLEANUP; } if (hour) { - y = accum("hours", x, hour, us_per_hour, &leftover_us); + y = accum("hours", x, hour, _datetimemodulestate_global->us_per_hour, &leftover_us); CLEANUP; } if (day) { - y = accum("days", x, day, us_per_day, &leftover_us); + y = accum("days", x, day, _datetimemodulestate_global->us_per_day, &leftover_us); CLEANUP; } if (week) { - y = accum("weeks", x, week, us_per_week, &leftover_us); + y = accum("weeks", x, week, _datetimemodulestate_global->us_per_week, &leftover_us); CLEANUP; } if (leftover_us) { @@ -2293,84 +2333,40 @@ static char delta_doc[] = PyDoc_STR("Difference between two datetime values."); -static PyNumberMethods delta_as_number = { - delta_add, /* nb_add */ - delta_subtract, /* nb_subtract */ - delta_multiply, /* nb_multiply */ - delta_remainder, /* nb_remainder */ - delta_divmod, /* nb_divmod */ - 0, /* nb_power */ - (unaryfunc)delta_negative, /* nb_negative */ - (unaryfunc)delta_positive, /* nb_positive */ - (unaryfunc)delta_abs, /* nb_absolute */ - (inquiry)delta_bool, /* nb_bool */ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - 0, /*nb_int*/ - 0, /*nb_reserved*/ - 0, /*nb_float*/ - 0, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - delta_divide, /* nb_floor_divide */ - delta_truedivide, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ +static PyType_Slot PyDateTime_DeltaType_slots[] = { + {Py_tp_doc, delta_doc}, + {Py_tp_repr, delta_repr}, + {Py_nb_add, delta_add}, + {Py_nb_subtract, delta_subtract}, + {Py_nb_multiply, delta_multiply}, + {Py_nb_remainder, delta_remainder}, + {Py_nb_divmod, delta_divmod}, + {Py_nb_negative, delta_negative}, + {Py_nb_positive, delta_positive}, + {Py_nb_absolute, delta_abs}, + {Py_nb_bool, delta_bool}, + {Py_nb_floor_divide, delta_divide}, + {Py_nb_true_divide, delta_truedivide}, + {Py_tp_hash, (hashfunc)delta_hash}, + {Py_tp_str, (reprfunc)delta_str}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_richcompare, delta_richcompare}, + {Py_tp_methods, delta_methods}, + {Py_tp_members, delta_members}, + {Py_tp_new, delta_new}, + {Py_tp_is_gc, }, + {0, 0}, }; -static PyTypeObject PyDateTime_DeltaType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.timedelta", /* tp_name */ - sizeof(PyDateTime_Delta), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)delta_repr, /* tp_repr */ - &delta_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)delta_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)delta_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - delta_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - delta_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - delta_methods, /* tp_methods */ - delta_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - delta_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Spec PyDateTime_DeltaType_spec = { + "datetime.timedelta", + sizeof(PyDateTime_Delta), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyDateTime_DeltaType_slots, }; + /* * PyDateTime_Date implementation. */ @@ -2875,61 +2871,30 @@ static char date_doc[] = PyDoc_STR("date(year, month, day) --> date object"); -static PyNumberMethods date_as_number = { - date_add, /* nb_add */ - date_subtract, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ +static PyType_Slot PyDateTime_DateType_slots[] = { + {Py_tp_doc, date_doc}, + {Py_tp_repr, (reprfunc)date_repr}, + {Py_nb_add, date_add}, + {Py_nb_subtract, date_subtract}, + {Py_tp_hash, (hashfunc)date_hash}, + {Py_tp_str, (reprfunc)date_str}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_richcompare, date_richcompare}, + {Py_tp_methods, date_methods}, + {Py_tp_getset, date_getset}, + {Py_tp_new, date_new}, + {Py_tp_is_gc, }, + {0, 0}, }; - -static PyTypeObject PyDateTime_DateType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.date", /* tp_name */ - sizeof(PyDateTime_Date), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)date_repr, /* tp_repr */ - &date_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)date_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)date_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - date_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - date_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - date_methods, /* tp_methods */ - 0, /* tp_members */ - date_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - date_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Spec PyDateTime_DateType_spec = { + "datetime.date", + sizeof(PyDateTime_Date), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyDateTime_DateType_slots, }; + /* * PyDateTime_TZInfo implementation. */ @@ -3144,48 +3109,24 @@ static char tzinfo_doc[] = PyDoc_STR("Abstract base class for time zone info objects."); -static PyTypeObject PyDateTime_TZInfoType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.tzinfo", /* tp_name */ - sizeof(PyDateTime_TZInfo), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - tzinfo_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - tzinfo_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot PyDateTime_TZInfoType_slots[] = { + {Py_tp_doc, tzinfo_doc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_methods, tzinfo_methods}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_is_gc, }, + {0, 0}, }; +static PyType_Spec PyDateTime_TZInfoType_spec = { + "datetime.tzinfo", + sizeof(PyDateTime_TZInfo), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyDateTime_TZInfoType_slots, +}; + + static char *timezone_kws[] = {"offset", "name", NULL}; static PyObject * @@ -3194,9 +3135,10 @@ PyObject *offset; PyObject *name = NULL; if (PyArg_ParseTupleAndKeywords(args, kw, "O!|O!:timezone", timezone_kws, - &PyDateTime_DeltaType, &offset, - &PyUnicode_Type, &name)) + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DeltaType, + &offset, &PyUnicode_Type, &name)){ return new_timezone(offset, name); + } return NULL; } @@ -3204,9 +3146,13 @@ static void timezone_dealloc(PyDateTime_TimeZone *self) { + PyTypeObject *type = Py_TYPE(self); Py_CLEAR(self->offset); Py_CLEAR(self->name); - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)timezone_dealloc) { + Py_DECREF(type); + } } static PyObject * @@ -3245,7 +3191,7 @@ to use Py_TYPE(self)->tp_name here. */ const char *type_name = Py_TYPE(self)->tp_name; - if (((PyObject *)self) == PyDateTime_TimeZone_UTC) + if (((PyObject *)self) == _datetimemodulestate_global->PyDateTime_TimeZone_UTC) return PyUnicode_FromFormat("%s.utc", type_name); if (self->name == NULL) @@ -3365,51 +3311,32 @@ static char timezone_doc[] = PyDoc_STR("Fixed offset from UTC implementation of tzinfo."); -static PyTypeObject PyDateTime_TimeZoneType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.timezone", /* tp_name */ - sizeof(PyDateTime_TimeZone), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)timezone_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)timezone_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)timezone_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)timezone_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - timezone_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)timezone_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - timezone_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyDateTime_TZInfoType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - timezone_new, /* tp_new */ +static PyType_Slot PyDateTime_TimeZoneType_slots[] = { + {Py_tp_doc, timezone_doc}, + {Py_tp_dealloc, (destructor)timezone_dealloc}, + {Py_tp_repr, (reprfunc)timezone_repr}, + {Py_tp_hash, (hashfunc)timezone_hash}, + {Py_tp_str, (reprfunc)timezone_str}, + {Py_tp_richcompare, (richcmpfunc)timezone_richcompare}, + {Py_tp_methods, timezone_methods}, + {Py_tp_new, timezone_new}, + {Py_tp_free, }, + {0, 0}, +}; + +static PyType_Spec PyDateTime_TimeZoneType_spec = { + "datetime.timezone", + sizeof(PyDateTime_TimeZone), + 0, + Py_TPFLAGS_DEFAULT, + PyDateTime_TimeZoneType_slots, }; /* * PyDateTime_Time implementation. */ + /* Accessor properties. */ @@ -3503,6 +3430,7 @@ Py_INCREF(tzinfo); me->tzinfo = tzinfo; } + Py_INCREF(type); } return (PyObject *)me; } @@ -3527,10 +3455,14 @@ static void time_dealloc(PyDateTime_Time *self) { + PyTypeObject *type = Py_TYPE(self); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)time_dealloc) { + Py_DECREF(type); + } } /* @@ -3883,61 +3815,31 @@ All arguments are optional. tzinfo may be None, or an instance of\n\ a tzinfo subclass. The remaining arguments may be ints or longs.\n"); -static PyNumberMethods time_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)time_bool, /* nb_bool */ +static PyType_Slot PyDateTime_TimeType_slots[] = { + {Py_tp_doc, time_doc}, + {Py_tp_dealloc, (destructor)time_dealloc}, + {Py_tp_repr, (reprfunc)time_repr}, + {Py_nb_bool, time_bool}, + {Py_tp_hash, (hashfunc)time_hash}, + {Py_tp_str, (reprfunc)time_str}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_richcompare, time_richcompare}, + {Py_tp_methods, time_methods}, + {Py_tp_getset, time_getset}, + {Py_tp_alloc, time_alloc}, + {Py_tp_new, time_new}, + {Py_tp_is_gc, }, + {0, 0}, }; - -static PyTypeObject PyDateTime_TimeType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.time", /* tp_name */ - sizeof(PyDateTime_Time), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)time_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)time_repr, /* tp_repr */ - &time_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)time_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)time_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - time_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - time_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - time_methods, /* tp_methods */ - 0, /* tp_members */ - time_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - time_alloc, /* tp_alloc */ - time_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Spec PyDateTime_TimeType_spec = { + "datetime.time", + sizeof(PyDateTime_Time), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyDateTime_TimeType_slots, }; + /* * PyDateTime_DateTime implementation. */ @@ -4040,6 +3942,7 @@ Py_INCREF(tzinfo); me->tzinfo = tzinfo; } + Py_INCREF(type); } return (PyObject *)me; } @@ -4245,8 +4148,8 @@ PyObject *result = NULL; if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords, - &PyDateTime_DateType, &date, - &PyDateTime_TimeType, &time)) { + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_DateType, &date, + (PyTypeObject *)_datetimemodulestate_global->PyDateTime_TimeType, &time)) { PyObject *tzinfo = Py_None; if (HASTZINFO(time)) @@ -4271,10 +4174,14 @@ static void datetime_dealloc(PyDateTime_DateTime *self) { + PyTypeObject *type = Py_TYPE(self); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)datetime_dealloc) { + Py_DECREF(type); + } } /* @@ -4699,7 +4606,8 @@ PyObject *nameo = NULL; const char *zone = NULL; - delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch); + delta = datetime_subtract((PyObject *)utc_time, + _datetimemodulestate_global->PyDateTime_Epoch); if (delta == NULL) return NULL; one_second = new_delta(0, 1, 0, 0); @@ -4849,7 +4757,7 @@ if (HASTZINFO(self) && self->tzinfo != Py_None) { PyObject *delta; - delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch); + delta = datetime_subtract((PyObject *)self, _datetimemodulestate_global->PyDateTime_Epoch); if (delta == NULL) return NULL; result = delta_total_seconds(delta); @@ -5066,78 +4974,42 @@ The year, month and day arguments are required. tzinfo may be None, or an\n\ instance of a tzinfo subclass. The remaining arguments may be ints or longs.\n"); -static PyNumberMethods datetime_as_number = { - datetime_add, /* nb_add */ - datetime_subtract, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ -}; - -static PyTypeObject PyDateTime_DateTimeType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.datetime", /* tp_name */ - sizeof(PyDateTime_DateTime), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)datetime_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)datetime_repr, /* tp_repr */ - &datetime_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)datetime_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)datetime_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - datetime_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - datetime_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - datetime_methods, /* tp_methods */ - 0, /* tp_members */ - datetime_getset, /* tp_getset */ - &PyDateTime_DateType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - datetime_alloc, /* tp_alloc */ - datetime_new, /* tp_new */ - 0, /* tp_free */ -}; - /* --------------------------------------------------------------------------- * Module methods and initialization. */ - -static PyMethodDef module_methods[] = { - {NULL, NULL} + +static PyType_Slot PyDateTime_DateTimeType_slots[] = { + {Py_tp_doc, datetime_doc}, + {Py_tp_dealloc, (destructor)datetime_dealloc}, + {Py_tp_repr, (reprfunc)datetime_repr}, + {Py_nb_add, datetime_add}, + {Py_nb_subtract, datetime_subtract}, + {Py_tp_hash, (hashfunc)datetime_hash}, + {Py_tp_str, (reprfunc)datetime_str}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_richcompare, datetime_richcompare}, + {Py_tp_methods, datetime_methods}, + {Py_tp_getset, datetime_getset}, + {Py_tp_alloc, datetime_alloc}, + {Py_tp_new, datetime_new}, + {Py_tp_is_gc, }, + {0, 0}, }; -/* C API. Clients get at this via PyDateTime_IMPORT, defined in - * datetime.h. - */ +static PyType_Spec PyDateTime_DateTimeType_spec = { + "datetime.datetime", + sizeof(PyDateTime_DateTime), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyDateTime_DateTimeType_slots, +}; + static PyDateTime_CAPI CAPI = { - &PyDateTime_DateType, - &PyDateTime_DateTimeType, - &PyDateTime_TimeType, - &PyDateTime_DeltaType, - &PyDateTime_TZInfoType, + NULL, + NULL, + NULL, + NULL, + NULL, new_date_ex, new_datetime_ex, new_time_ex, @@ -5146,18 +5018,20 @@ date_fromtimestamp }; - - -static struct PyModuleDef datetimemodule = { +static PyMethodDef module_methods[] = { + {NULL, NULL} +}; + +static struct PyModuleDef _datetimemodule = { PyModuleDef_HEAD_INIT, "_datetime", "Fast implementation of the datetime type.", - -1, + sizeof(_datetimemodulestate), module_methods, NULL, - NULL, - NULL, - NULL + _datetimemodule_traverse, + _datetimemodule_clear, + _datetimemodule_free }; PyMODINIT_FUNC @@ -5168,68 +5042,127 @@ PyObject *x; PyObject *delta; - m = PyModule_Create(&datetimemodule); - if (m == NULL) + m = PyState_FindModule(&_datetimemodule); + if(!m){ + m = PyModule_Create(&_datetimemodule); + if (m == NULL) + return NULL; + } else { + Py_INCREF(m); + return m; + } + + PyState_AddModule(m, &_datetimemodule); + + _datetimemodulestate(m)->PyDateTime_DateType = + PyType_FromSpec(&PyDateTime_DateType_spec); + if (_datetimemodulestate(m)->PyDateTime_DateType == NULL) + goto fail; + + _datetimemodulestate(m)->PyDateTime_TZInfoType = + PyType_FromSpec(&PyDateTime_TZInfoType_spec); + if (_datetimemodulestate(m)->PyDateTime_TZInfoType == NULL) + goto fail; + + _datetimemodulestate(m)->PyDateTime_TimeZoneType = + PyType_FromSpecWithBases( + &PyDateTime_TimeZoneType_spec, + PyTuple_Pack(1, _datetimemodulestate(m)->PyDateTime_TZInfoType) + ); + if (_datetimemodulestate(m)->PyDateTime_TimeZoneType == NULL) + goto fail; + + _datetimemodulestate(m)->PyDateTime_DateTimeType = + PyType_FromSpecWithBases( + &PyDateTime_DateTimeType_spec, + PyTuple_Pack(1, _datetimemodulestate(m)->PyDateTime_DateType) + ); + if (_datetimemodulestate(m)->PyDateTime_DateTimeType == NULL) + goto fail; + + _datetimemodulestate(m)->PyDateTime_DeltaType = + PyType_FromSpec(&PyDateTime_DeltaType_spec); + if (_datetimemodulestate(m)->PyDateTime_DeltaType == NULL) + goto fail; + + _datetimemodulestate(m)->PyDateTime_TimeType = + PyType_FromSpec(&PyDateTime_TimeType_spec); + if (_datetimemodulestate(m)->PyDateTime_TimeType == NULL) + goto fail; + + /* C API. Clients get at this via PyDateTime_IMPORT, defined in + * datetime.h. Now created per module, as TypeObjects are no longer static. + */ + CAPI.DateType = (PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DateType; + CAPI.DateTimeType = (PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DateTimeType; + CAPI.TimeType = (PyTypeObject *)_datetimemodulestate(m)->PyDateTime_TimeType; + CAPI.DeltaType = (PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DeltaType; + CAPI.TZInfoType = (PyTypeObject *)_datetimemodulestate(m)->PyDateTime_TZInfoType; + + /* timedelta values */ + d = ((PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DeltaType)->tp_dict; + + x = new_delta(0, 0, 1, 0); + + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) return NULL; - - if (PyType_Ready(&PyDateTime_DateType) < 0) + Py_DECREF(x); + + x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) return NULL; - if (PyType_Ready(&PyDateTime_DateTimeType) < 0) + Py_DECREF(x); + + x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) return NULL; - if (PyType_Ready(&PyDateTime_DeltaType) < 0) + Py_DECREF(x); + + /* date values */ + d = ((PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DateType)->tp_dict; + + x = new_date(1, 1, 1); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) return NULL; - if (PyType_Ready(&PyDateTime_TimeType) < 0) + Py_DECREF(x); + + x = new_date(MAXYEAR, 12, 31); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) return NULL; - if (PyType_Ready(&PyDateTime_TZInfoType) < 0) + Py_DECREF(x); + + x = new_delta(1, 0, 0, 0); + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) return NULL; - if (PyType_Ready(&PyDateTime_TimeZoneType) < 0) + Py_DECREF(x); + + /* time values */ + d = ((PyTypeObject *)_datetimemodulestate(m)->PyDateTime_TimeType)->tp_dict; + + x = new_time(0, 0, 0, 0, Py_None); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) return NULL; - - /* timedelta values */ - d = PyDateTime_DeltaType.tp_dict; + Py_DECREF(x); + + x = new_time(23, 59, 59, 999999, Py_None); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) + return NULL; + Py_DECREF(x); x = new_delta(0, 0, 1, 0); if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) return NULL; Py_DECREF(x); - x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); + /* datetime values */ + d = ((PyTypeObject *)_datetimemodulestate(m)->PyDateTime_DateTimeType)->tp_dict; + + x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None); if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) return NULL; Py_DECREF(x); - x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - /* date values */ - d = PyDateTime_DateType.tp_dict; - - x = new_date(1, 1, 1); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_date(MAXYEAR, 12, 31); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(1, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - /* time values */ - d = PyDateTime_TimeType.tp_dict; - - x = new_time(0, 0, 0, 0, Py_None); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_time(23, 59, 59, 999999, Py_None); + x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None); if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) return NULL; Py_DECREF(x); @@ -5239,26 +5172,8 @@ return NULL; Py_DECREF(x); - /* datetime values */ - d = PyDateTime_DateTimeType.tp_dict; - - x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - /* timezone values */ - d = PyDateTime_TimeZoneType.tp_dict; + d = ((PyTypeObject *)_datetimemodulestate(m)->PyDateTime_TimeZoneType)->tp_dict; delta = new_delta(0, 0, 0, 0); if (delta == NULL) @@ -5267,7 +5182,7 @@ Py_DECREF(delta); if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0) return NULL; - PyDateTime_TimeZone_UTC = x; + _datetimemodulestate(m)->PyDateTime_TimeZone_UTC = x; delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) @@ -5288,33 +5203,33 @@ Py_DECREF(x); /* Epoch */ - PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, - PyDateTime_TimeZone_UTC); - if (PyDateTime_Epoch == NULL) + _datetimemodulestate(m)->PyDateTime_Epoch = \ + new_datetime(1970, 1, 1, 0, 0, 0, 0, + _datetimemodulestate(m)->PyDateTime_TimeZone_UTC); + if (_datetimemodulestate(m)->PyDateTime_Epoch == NULL) return NULL; /* module initialization */ PyModule_AddIntConstant(m, "MINYEAR", MINYEAR); PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR); - Py_INCREF(&PyDateTime_DateType); - PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType); - - Py_INCREF(&PyDateTime_DateTimeType); - PyModule_AddObject(m, "datetime", - (PyObject *)&PyDateTime_DateTimeType); - - Py_INCREF(&PyDateTime_TimeType); - PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType); - - Py_INCREF(&PyDateTime_DeltaType); - PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType); - - Py_INCREF(&PyDateTime_TZInfoType); - PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); - - Py_INCREF(&PyDateTime_TimeZoneType); - PyModule_AddObject(m, "timezone", (PyObject *) &PyDateTime_TimeZoneType); + Py_INCREF(_datetimemodulestate(m)->PyDateTime_DateType); + PyModule_AddObject(m, "date", _datetimemodulestate(m)->PyDateTime_DateType); + + Py_INCREF(_datetimemodulestate(m)->PyDateTime_DateTimeType); + PyModule_AddObject(m, "datetime", _datetimemodulestate(m)->PyDateTime_DateTimeType); + + Py_INCREF(_datetimemodulestate(m)->PyDateTime_TimeType); + PyModule_AddObject(m, "time", _datetimemodulestate(m)->PyDateTime_TimeType); + + Py_INCREF(_datetimemodulestate(m)->PyDateTime_DeltaType); + PyModule_AddObject(m, "timedelta", _datetimemodulestate(m)->PyDateTime_DeltaType); + + Py_INCREF(_datetimemodulestate(m)->PyDateTime_TZInfoType); + PyModule_AddObject(m, "tzinfo", _datetimemodulestate(m)->PyDateTime_TZInfoType); + + Py_INCREF(_datetimemodulestate(m)->PyDateTime_TimeZoneType); + PyModule_AddObject(m, "timezone", _datetimemodulestate(m)->PyDateTime_TimeZoneType); x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); if (x == NULL) @@ -5339,24 +5254,36 @@ assert(DI100Y == 25 * DI4Y - 1); assert(DI100Y == days_before_year(100+1)); - us_per_us = PyLong_FromLong(1); - us_per_ms = PyLong_FromLong(1000); - us_per_second = PyLong_FromLong(1000000); - us_per_minute = PyLong_FromLong(60000000); - seconds_per_day = PyLong_FromLong(24 * 3600); - if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL || - us_per_minute == NULL || seconds_per_day == NULL) + _datetimemodulestate(m)->us_per_us = PyLong_FromLong(1); + _datetimemodulestate(m)->us_per_ms = PyLong_FromLong(1000); + _datetimemodulestate(m)->us_per_second = PyLong_FromLong(1000000); + _datetimemodulestate(m)->us_per_minute = PyLong_FromLong(60000000); + _datetimemodulestate(m)->seconds_per_day = PyLong_FromLong(24 * 3600); + + if (_datetimemodulestate(m)->us_per_us == NULL || + _datetimemodulestate(m)->us_per_ms == NULL || + _datetimemodulestate(m)->us_per_second == NULL || + _datetimemodulestate(m)->us_per_minute == NULL || + _datetimemodulestate(m)->seconds_per_day == NULL) return NULL; /* The rest are too big for 32-bit ints, but even * us_per_week fits in 40 bits, so doubles should be exact. */ - us_per_hour = PyLong_FromDouble(3600000000.0); - us_per_day = PyLong_FromDouble(86400000000.0); - us_per_week = PyLong_FromDouble(604800000000.0); - if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) + _datetimemodulestate(m)->us_per_hour = PyLong_FromDouble(3600000000.0); + _datetimemodulestate(m)->us_per_day = PyLong_FromDouble(86400000000.0); + _datetimemodulestate(m)->us_per_week = PyLong_FromDouble(604800000000.0); + + if (_datetimemodulestate(m)->us_per_hour == NULL || + _datetimemodulestate(m)->us_per_day == NULL || + _datetimemodulestate(m)->us_per_week == NULL) return NULL; return m; + + fail: + PyState_RemoveModule(&_datetimemodule); + Py_DECREF(m); + return NULL; } /* ---------------------------------------------------------------------------