@@ -1178,6 +1178,8 @@ new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
11781178 return t ;
11791179}
11801180
1181+ static PyDateTime_Delta * look_up_delta (int , int , int , PyTypeObject * );
1182+
11811183/* Create a timedelta instance. Normalize the members iff normalize is
11821184 * true. Passing false is a speed optimization, if you know for sure
11831185 * that seconds and microseconds are already in their proper ranges. In any
@@ -1198,6 +1200,12 @@ new_delta_ex(int days, int seconds, int microseconds, int normalize,
11981200 if (check_delta_day_range (days ) < 0 )
11991201 return NULL ;
12001202
1203+ self = look_up_delta (days , seconds , microseconds , type );
1204+ if (self != NULL ) {
1205+ return (PyObject * )self ;
1206+ }
1207+ assert (!PyErr_Occurred ());
1208+
12011209 self = (PyDateTime_Delta * ) (type -> tp_alloc (type , 0 ));
12021210 if (self != NULL ) {
12031211 self -> hashcode = -1 ;
@@ -1219,6 +1227,8 @@ typedef struct
12191227 PyObject * name ;
12201228} PyDateTime_TimeZone ;
12211229
1230+ static PyDateTime_TimeZone * look_up_timezone (PyObject * offset , PyObject * name );
1231+
12221232/* Create new timezone instance checking offset range. This
12231233 function does not check the name argument. Caller must assure
12241234 that offset is a timedelta instance and name is either NULL
@@ -1234,6 +1244,12 @@ create_timezone(PyObject *offset, PyObject *name)
12341244 assert (PyDelta_Check (offset ));
12351245 assert (name == NULL || PyUnicode_Check (name ));
12361246
1247+ self = look_up_timezone (offset , name );
1248+ if (self != NULL ) {
1249+ return (PyObject * )self ;
1250+ }
1251+ assert (!PyErr_Occurred ());
1252+
12371253 self = (PyDateTime_TimeZone * )(type -> tp_alloc (type , 0 ));
12381254 if (self == NULL ) {
12391255 return NULL ;
@@ -2892,6 +2908,25 @@ static PyTypeObject PyDateTime_DeltaType = {
28922908 0 , /* tp_free */
28932909};
28942910
2911+ // XXX Can we make this const?
2912+ static PyDateTime_Delta zero_delta = {
2913+ PyObject_HEAD_INIT (& PyDateTime_DeltaType )
2914+ /* Letting this be set lazily is a benign race. */
2915+ .hashcode = -1 ,
2916+ };
2917+
2918+ static PyDateTime_Delta *
2919+ look_up_delta (int days , int seconds , int microseconds , PyTypeObject * type )
2920+ {
2921+ if (days == 0 && seconds == 0 && microseconds == 0
2922+ && type == zero_delta .ob_base .ob_type )
2923+ {
2924+ return & zero_delta ;
2925+ }
2926+ return NULL ;
2927+ }
2928+
2929+
28952930/*
28962931 * PyDateTime_Date implementation.
28972932 */
@@ -4184,6 +4219,23 @@ static PyTypeObject PyDateTime_TimeZoneType = {
41844219 timezone_new , /* tp_new */
41854220};
41864221
4222+ // XXX Can we make this const?
4223+ static PyDateTime_TimeZone utc_timezone = {
4224+ PyObject_HEAD_INIT (& PyDateTime_TimeZoneType )
4225+ .offset = (PyObject * )& zero_delta ,
4226+ .name = NULL ,
4227+ };
4228+
4229+ static PyDateTime_TimeZone *
4230+ look_up_timezone (PyObject * offset , PyObject * name )
4231+ {
4232+ if (offset == utc_timezone .offset && name == NULL ) {
4233+ return & utc_timezone ;
4234+ }
4235+ return NULL ;
4236+ }
4237+
4238+
41874239/*
41884240 * PyDateTime_Time implementation.
41894241 */
@@ -6719,45 +6771,42 @@ static PyMethodDef module_methods[] = {
67196771 {NULL , NULL }
67206772};
67216773
6774+
6775+ /* The C-API is process-global. This violates interpreter isolation
6776+ * due to the objects stored here. Thus each of those objects must
6777+ * be managed carefully. */
6778+ // XXX Can we make this const?
6779+ static PyDateTime_CAPI capi = {
6780+ /* The classes must be readied before used here.
6781+ * That will happen the first time the module is loaded.
6782+ * They aren't safe to be shared between interpreters,
6783+ * but that's okay as long as the module is single-phase init. */
6784+ .DateType = & PyDateTime_DateType ,
6785+ .DateTimeType = & PyDateTime_DateTimeType ,
6786+ .TimeType = & PyDateTime_TimeType ,
6787+ .DeltaType = & PyDateTime_DeltaType ,
6788+ .TZInfoType = & PyDateTime_TZInfoType ,
6789+
6790+ .TimeZone_UTC = (PyObject * )& utc_timezone ,
6791+
6792+ .Date_FromDate = new_date_ex ,
6793+ .DateTime_FromDateAndTime = new_datetime_ex ,
6794+ .Time_FromTime = new_time_ex ,
6795+ .Delta_FromDelta = new_delta_ex ,
6796+ .TimeZone_FromTimeZone = new_timezone ,
6797+ .DateTime_FromTimestamp = datetime_fromtimestamp ,
6798+ .Date_FromTimestamp = datetime_date_fromtimestamp_capi ,
6799+ .DateTime_FromDateAndTimeAndFold = new_datetime_ex2 ,
6800+ .Time_FromTimeAndFold = new_time_ex2 ,
6801+ };
6802+
67226803/* Get a new C API by calling this function.
67236804 * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
67246805 */
67256806static inline PyDateTime_CAPI *
67266807get_datetime_capi (void )
67276808{
6728- datetime_state * st = get_datetime_state ();
6729-
6730- PyDateTime_CAPI * capi = PyMem_Malloc (sizeof (PyDateTime_CAPI ));
6731- if (capi == NULL ) {
6732- PyErr_NoMemory ();
6733- return NULL ;
6734- }
6735- capi -> DateType = st -> date_type ;
6736- capi -> DateTimeType = st -> datetime_type ;
6737- capi -> TimeType = st -> time_type ;
6738- capi -> DeltaType = st -> delta_type ;
6739- capi -> TZInfoType = st -> tzinfo_type ;
6740- capi -> Date_FromDate = new_date_ex ;
6741- capi -> DateTime_FromDateAndTime = new_datetime_ex ;
6742- capi -> Time_FromTime = new_time_ex ;
6743- capi -> Delta_FromDelta = new_delta_ex ;
6744- capi -> TimeZone_FromTimeZone = new_timezone ;
6745- capi -> DateTime_FromTimestamp = datetime_fromtimestamp ;
6746- capi -> Date_FromTimestamp = datetime_date_fromtimestamp_capi ;
6747- capi -> DateTime_FromDateAndTimeAndFold = new_datetime_ex2 ;
6748- capi -> Time_FromTimeAndFold = new_time_ex2 ;
6749- // Make sure this function is called after utc has
6750- // been initialized.
6751- assert (st -> utc != NULL );
6752- capi -> TimeZone_UTC = st -> utc ; // borrowed ref
6753- return capi ;
6754- }
6755-
6756- static void
6757- datetime_destructor (PyObject * op )
6758- {
6759- void * ptr = PyCapsule_GetPointer (op , PyDateTime_CAPSULE_NAME );
6760- PyMem_Free (ptr );
6809+ return & capi ;
67616810}
67626811
67636812static int
@@ -6955,8 +7004,7 @@ _datetime_exec(PyObject *module)
69557004 if (capi == NULL ) {
69567005 goto error ;
69577006 }
6958- PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME ,
6959- datetime_destructor );
7007+ PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME , NULL );
69607008 if (capsule == NULL ) {
69617009 PyMem_Free (capi );
69627010 goto error ;
0 commit comments