@@ -1172,6 +1172,8 @@ new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
11721172 return t ;
11731173}
11741174
1175+ static PyDateTime_Delta * look_up_delta (int , int , int , PyTypeObject * );
1176+
11751177/* Create a timedelta instance. Normalize the members iff normalize is
11761178 * true. Passing false is a speed optimization, if you know for sure
11771179 * 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,
11921194 if (check_delta_day_range (days ) < 0 )
11931195 return NULL ;
11941196
1197+ self = look_up_delta (days , seconds , microseconds , type );
1198+ if (self != NULL ) {
1199+ return (PyObject * )self ;
1200+ }
1201+ assert (!PyErr_Occurred ());
1202+
11951203 self = (PyDateTime_Delta * ) (type -> tp_alloc (type , 0 ));
11961204 if (self != NULL ) {
11971205 self -> hashcode = -1 ;
@@ -1213,6 +1221,8 @@ typedef struct
12131221 PyObject * name ;
12141222} PyDateTime_TimeZone ;
12151223
1224+ static PyDateTime_TimeZone * look_up_timezone (PyObject * offset , PyObject * name );
1225+
12161226/* Create new timezone instance checking offset range. This
12171227 function does not check the name argument. Caller must assure
12181228 that offset is a timedelta instance and name is either NULL
@@ -1227,6 +1237,12 @@ create_timezone(PyObject *offset, PyObject *name)
12271237 assert (PyDelta_Check (offset ));
12281238 assert (name == NULL || PyUnicode_Check (name ));
12291239
1240+ self = look_up_timezone (offset , name );
1241+ if (self != NULL ) {
1242+ return (PyObject * )self ;
1243+ }
1244+ assert (!PyErr_Occurred ());
1245+
12301246 self = (PyDateTime_TimeZone * )(type -> tp_alloc (type , 0 ));
12311247 if (self == NULL ) {
12321248 return NULL ;
@@ -2885,6 +2901,25 @@ static PyTypeObject PyDateTime_DeltaType = {
28852901 0 , /* tp_free */
28862902};
28872903
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+
28882923/*
28892924 * PyDateTime_Date implementation.
28902925 */
@@ -4175,6 +4210,23 @@ static PyTypeObject PyDateTime_TimeZoneType = {
41754210 timezone_new , /* tp_new */
41764211};
41774212
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+
41784230/*
41794231 * PyDateTime_Time implementation.
41804232 */
@@ -6706,44 +6758,42 @@ static PyMethodDef module_methods[] = {
67066758 {NULL , NULL }
67076759};
67086760
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+
67096790/* Get a new C API by calling this function.
67106791 * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
67116792 */
67126793static inline PyDateTime_CAPI *
67136794get_datetime_capi (void )
67146795{
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 ;
67476797}
67486798
67496799static int
@@ -6933,8 +6983,7 @@ _datetime_exec(PyObject *module)
69336983 if (capi == NULL ) {
69346984 goto error ;
69356985 }
6936- PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME ,
6937- datetime_destructor );
6986+ PyObject * capsule = PyCapsule_New (capi , PyDateTime_CAPSULE_NAME , NULL );
69386987 if (capsule == NULL ) {
69396988 PyMem_Free (capi );
69406989 goto error ;
0 commit comments