@@ -1172,6 +1172,8 @@ new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
1172
1172
return t ;
1173
1173
}
1174
1174
1175
+ static PyDateTime_Delta * look_up_delta (int , int , int , PyTypeObject * );
1176
+
1175
1177
/* Create a timedelta instance. Normalize the members iff normalize is
1176
1178
* true. Passing false is a speed optimization, if you know for sure
1177
1179
* that seconds and microseconds are already in their proper ranges. In any
@@ -1192,6 +1194,12 @@ new_delta_ex(int days, int seconds, int microseconds, int normalize,
1192
1194
if (check_delta_day_range (days ) < 0 )
1193
1195
return NULL ;
1194
1196
1197
+ self = look_up_delta (days , seconds , microseconds , type );
1198
+ if (self != NULL ) {
1199
+ return (PyObject * )self ;
1200
+ }
1201
+ assert (!PyErr_Occurred ());
1202
+
1195
1203
self = (PyDateTime_Delta * ) (type -> tp_alloc (type , 0 ));
1196
1204
if (self != NULL ) {
1197
1205
self -> hashcode = -1 ;
@@ -1213,6 +1221,8 @@ typedef struct
1213
1221
PyObject * name ;
1214
1222
} PyDateTime_TimeZone ;
1215
1223
1224
+ static PyDateTime_TimeZone * look_up_timezone (PyObject * offset , PyObject * name );
1225
+
1216
1226
/* Create new timezone instance checking offset range. This
1217
1227
function does not check the name argument. Caller must assure
1218
1228
that offset is a timedelta instance and name is either NULL
@@ -1227,6 +1237,12 @@ create_timezone(PyObject *offset, PyObject *name)
1227
1237
assert (PyDelta_Check (offset ));
1228
1238
assert (name == NULL || PyUnicode_Check (name ));
1229
1239
1240
+ self = look_up_timezone (offset , name );
1241
+ if (self != NULL ) {
1242
+ return (PyObject * )self ;
1243
+ }
1244
+ assert (!PyErr_Occurred ());
1245
+
1230
1246
self = (PyDateTime_TimeZone * )(type -> tp_alloc (type , 0 ));
1231
1247
if (self == NULL ) {
1232
1248
return NULL ;
@@ -2885,6 +2901,25 @@ static PyTypeObject PyDateTime_DeltaType = {
2885
2901
0 , /* tp_free */
2886
2902
};
2887
2903
2904
+ // XXX Can we make this const?
2905
+ static PyDateTime_Delta zero_delta = {
2906
+ PyObject_HEAD_INIT (& PyDateTime_DeltaType )
2907
+ /* Letting this be set lazily is a benign race. */
2908
+ .hashcode = -1 ,
2909
+ };
2910
+
2911
+ static PyDateTime_Delta *
2912
+ look_up_delta (int days , int seconds , int microseconds , PyTypeObject * type )
2913
+ {
2914
+ if (days == 0 && seconds == 0 && microseconds == 0
2915
+ && type == zero_delta .ob_base .ob_type )
2916
+ {
2917
+ return & zero_delta ;
2918
+ }
2919
+ return NULL ;
2920
+ }
2921
+
2922
+
2888
2923
/*
2889
2924
* PyDateTime_Date implementation.
2890
2925
*/
@@ -4175,6 +4210,23 @@ static PyTypeObject PyDateTime_TimeZoneType = {
4175
4210
timezone_new , /* tp_new */
4176
4211
};
4177
4212
4213
+ // XXX Can we make this const?
4214
+ static PyDateTime_TimeZone utc_timezone = {
4215
+ PyObject_HEAD_INIT (& PyDateTime_TimeZoneType )
4216
+ .offset = (PyObject * )& zero_delta ,
4217
+ .name = NULL ,
4218
+ };
4219
+
4220
+ static PyDateTime_TimeZone *
4221
+ look_up_timezone (PyObject * offset , PyObject * name )
4222
+ {
4223
+ if (offset == utc_timezone .offset && name == NULL ) {
4224
+ return & utc_timezone ;
4225
+ }
4226
+ return NULL ;
4227
+ }
4228
+
4229
+
4178
4230
/*
4179
4231
* PyDateTime_Time implementation.
4180
4232
*/
@@ -6706,44 +6758,42 @@ static PyMethodDef module_methods[] = {
6706
6758
{NULL , NULL }
6707
6759
};
6708
6760
6761
+
6762
+ /* The C-API is process-global. This violates interpreter isolation
6763
+ * due to the objects stored here. Thus each of those objects must
6764
+ * be managed carefully. */
6765
+ // XXX Can we make this const?
6766
+ static PyDateTime_CAPI capi = {
6767
+ /* The classes must be readied before used here.
6768
+ * That will happen the first time the module is loaded.
6769
+ * They aren't safe to be shared between interpreters,
6770
+ * but that's okay as long as the module is single-phase init. */
6771
+ .DateType = & PyDateTime_DateType ,
6772
+ .DateTimeType = & PyDateTime_DateTimeType ,
6773
+ .TimeType = & PyDateTime_TimeType ,
6774
+ .DeltaType = & PyDateTime_DeltaType ,
6775
+ .TZInfoType = & PyDateTime_TZInfoType ,
6776
+
6777
+ .TimeZone_UTC = (PyObject * )& utc_timezone ,
6778
+
6779
+ .Date_FromDate = new_date_ex ,
6780
+ .DateTime_FromDateAndTime = new_datetime_ex ,
6781
+ .Time_FromTime = new_time_ex ,
6782
+ .Delta_FromDelta = new_delta_ex ,
6783
+ .TimeZone_FromTimeZone = new_timezone ,
6784
+ .DateTime_FromTimestamp = datetime_fromtimestamp ,
6785
+ .Date_FromTimestamp = datetime_date_fromtimestamp_capi ,
6786
+ .DateTime_FromDateAndTimeAndFold = new_datetime_ex2 ,
6787
+ .Time_FromTimeAndFold = new_time_ex2 ,
6788
+ };
6789
+
6709
6790
/* Get a new C API by calling this function.
6710
6791
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
6711
6792
*/
6712
6793
static inline PyDateTime_CAPI *
6713
6794
get_datetime_capi (void )
6714
6795
{
6715
- PyDateTime_CAPI * capi = PyMem_Malloc (sizeof (PyDateTime_CAPI ));
6716
- if (capi == NULL ) {
6717
- PyErr_NoMemory ();
6718
- return NULL ;
6719
- }
6720
- capi -> DateType = & PyDateTime_DateType ;
6721
- capi -> DateTimeType = & PyDateTime_DateTimeType ;
6722
- capi -> TimeType = & PyDateTime_TimeType ;
6723
- capi -> DeltaType = & PyDateTime_DeltaType ;
6724
- capi -> TZInfoType = & PyDateTime_TZInfoType ;
6725
- capi -> Date_FromDate = new_date_ex ;
6726
- capi -> DateTime_FromDateAndTime = new_datetime_ex ;
6727
- capi -> Time_FromTime = new_time_ex ;
6728
- capi -> Delta_FromDelta = new_delta_ex ;
6729
- capi -> TimeZone_FromTimeZone = new_timezone ;
6730
- capi -> DateTime_FromTimestamp = datetime_fromtimestamp ;
6731
- capi -> Date_FromTimestamp = datetime_date_fromtimestamp_capi ;
6732
- capi -> DateTime_FromDateAndTimeAndFold = new_datetime_ex2 ;
6733
- capi -> Time_FromTimeAndFold = new_time_ex2 ;
6734
- // Make sure this function is called after utc has
6735
- // been initialized.
6736
- datetime_state * st = STATIC_STATE ();
6737
- assert (st -> utc != NULL );
6738
- capi -> TimeZone_UTC = st -> utc ; // borrowed ref
6739
- return capi ;
6740
- }
6741
-
6742
- static void
6743
- datetime_destructor (PyObject * op )
6744
- {
6745
- void * ptr = PyCapsule_GetPointer (op , PyDateTime_CAPSULE_NAME );
6746
- PyMem_Free (ptr );
6796
+ return & capi ;
6747
6797
}
6748
6798
6749
6799
static int
@@ -6933,8 +6983,7 @@ _datetime_exec(PyObject *module)
6933
6983
if (capi == NULL ) {
6934
6984
goto error ;
6935
6985
}
6936
- PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME ,
6937
- datetime_destructor );
6986
+ PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME , NULL );
6938
6987
if (capsule == NULL ) {
6939
6988
PyMem_Free (capi );
6940
6989
goto error ;
0 commit comments