@@ -1178,6 +1178,8 @@ new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
1178
1178
return t ;
1179
1179
}
1180
1180
1181
+ static PyDateTime_Delta * look_up_delta (int , int , int , PyTypeObject * );
1182
+
1181
1183
/* Create a timedelta instance. Normalize the members iff normalize is
1182
1184
* true. Passing false is a speed optimization, if you know for sure
1183
1185
* 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,
1198
1200
if (check_delta_day_range (days ) < 0 )
1199
1201
return NULL ;
1200
1202
1203
+ self = look_up_delta (days , seconds , microseconds , type );
1204
+ if (self != NULL ) {
1205
+ return (PyObject * )self ;
1206
+ }
1207
+ assert (!PyErr_Occurred ());
1208
+
1201
1209
self = (PyDateTime_Delta * ) (type -> tp_alloc (type , 0 ));
1202
1210
if (self != NULL ) {
1203
1211
self -> hashcode = -1 ;
@@ -1219,6 +1227,8 @@ typedef struct
1219
1227
PyObject * name ;
1220
1228
} PyDateTime_TimeZone ;
1221
1229
1230
+ static PyDateTime_TimeZone * look_up_timezone (PyObject * offset , PyObject * name );
1231
+
1222
1232
/* Create new timezone instance checking offset range. This
1223
1233
function does not check the name argument. Caller must assure
1224
1234
that offset is a timedelta instance and name is either NULL
@@ -1234,6 +1244,12 @@ create_timezone(PyObject *offset, PyObject *name)
1234
1244
assert (PyDelta_Check (offset ));
1235
1245
assert (name == NULL || PyUnicode_Check (name ));
1236
1246
1247
+ self = look_up_timezone (offset , name );
1248
+ if (self != NULL ) {
1249
+ return (PyObject * )self ;
1250
+ }
1251
+ assert (!PyErr_Occurred ());
1252
+
1237
1253
self = (PyDateTime_TimeZone * )(type -> tp_alloc (type , 0 ));
1238
1254
if (self == NULL ) {
1239
1255
return NULL ;
@@ -2892,6 +2908,25 @@ static PyTypeObject PyDateTime_DeltaType = {
2892
2908
0 , /* tp_free */
2893
2909
};
2894
2910
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
+
2895
2930
/*
2896
2931
* PyDateTime_Date implementation.
2897
2932
*/
@@ -4184,6 +4219,23 @@ static PyTypeObject PyDateTime_TimeZoneType = {
4184
4219
timezone_new , /* tp_new */
4185
4220
};
4186
4221
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
+
4187
4239
/*
4188
4240
* PyDateTime_Time implementation.
4189
4241
*/
@@ -6719,45 +6771,42 @@ static PyMethodDef module_methods[] = {
6719
6771
{NULL , NULL }
6720
6772
};
6721
6773
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
+
6722
6803
/* Get a new C API by calling this function.
6723
6804
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
6724
6805
*/
6725
6806
static inline PyDateTime_CAPI *
6726
6807
get_datetime_capi (void )
6727
6808
{
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 ;
6761
6810
}
6762
6811
6763
6812
static int
@@ -6955,8 +7004,7 @@ _datetime_exec(PyObject *module)
6955
7004
if (capi == NULL ) {
6956
7005
goto error ;
6957
7006
}
6958
- PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME ,
6959
- datetime_destructor );
7007
+ PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME , NULL );
6960
7008
if (capsule == NULL ) {
6961
7009
PyMem_Free (capi );
6962
7010
goto error ;
0 commit comments