@@ -1027,6 +1027,40 @@ new_datetime_ex(int year, int month, int day, int hour, int minute,
10271027 new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
10281028 &PyDateTime_DateTimeType)
10291029
1030+ static PyObject *
1031+ call_subclass_fold (PyObject * cls , int fold , const char * format , ...)
1032+ {
1033+ PyObject * kwargs = NULL , * res = NULL ;
1034+ va_list va ;
1035+
1036+ va_start (va , format );
1037+ PyObject * args = Py_VaBuildValue (format , va );
1038+ va_end (va );
1039+ if (args == NULL ) {
1040+ return NULL ;
1041+ }
1042+ if (fold ) {
1043+ kwargs = PyDict_New ();
1044+ if (kwargs == NULL ) {
1045+ goto Done ;
1046+ }
1047+ PyObject * obj = PyLong_FromLong (fold );
1048+ if (obj == NULL ) {
1049+ goto Done ;
1050+ }
1051+ int err = PyDict_SetItemString (kwargs , "fold" , obj );
1052+ Py_DECREF (obj );
1053+ if (err < 0 ) {
1054+ goto Done ;
1055+ }
1056+ }
1057+ res = PyObject_Call (cls , args , kwargs );
1058+ Done :
1059+ Py_DECREF (args );
1060+ Py_XDECREF (kwargs );
1061+ return res ;
1062+ }
1063+
10301064static PyObject *
10311065new_datetime_subclass_fold_ex (int year , int month , int day , int hour , int minute ,
10321066 int second , int usecond , PyObject * tzinfo ,
@@ -1036,17 +1070,11 @@ new_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute
10361070 // Use the fast path constructor
10371071 dt = new_datetime (year , month , day , hour , minute , second , usecond ,
10381072 tzinfo , fold );
1039- } else {
1073+ }
1074+ else {
10401075 // Subclass
1041- dt = PyObject_CallFunction (cls , "iiiiiiiO" ,
1042- year ,
1043- month ,
1044- day ,
1045- hour ,
1046- minute ,
1047- second ,
1048- usecond ,
1049- tzinfo );
1076+ dt = call_subclass_fold (cls , fold , "iiiiiiiO" , year , month , day ,
1077+ hour , minute , second , usecond , tzinfo );
10501078 }
10511079
10521080 return dt ;
@@ -1102,6 +1130,24 @@ new_time_ex(int hour, int minute, int second, int usecond,
11021130#define new_time (hh , mm , ss , us , tzinfo , fold ) \
11031131 new_time_ex2(hh, mm, ss, us, tzinfo, fold, &PyDateTime_TimeType)
11041132
1133+ static PyObject *
1134+ new_time_subclass_fold_ex (int hour , int minute , int second , int usecond ,
1135+ PyObject * tzinfo , int fold , PyObject * cls )
1136+ {
1137+ PyObject * t ;
1138+ if ((PyTypeObject * )cls == & PyDateTime_TimeType ) {
1139+ // Use the fast path constructor
1140+ t = new_time (hour , minute , second , usecond , tzinfo , fold );
1141+ }
1142+ else {
1143+ // Subclass
1144+ t = call_subclass_fold (cls , fold , "iiiiO" , hour , minute , second ,
1145+ usecond , tzinfo );
1146+ }
1147+
1148+ return t ;
1149+ }
1150+
11051151/* Create a timedelta instance. Normalize the members iff normalize is
11061152 * true. Passing false is a speed optimization, if you know for sure
11071153 * that seconds and microseconds are already in their proper ranges. In any
@@ -3430,21 +3476,14 @@ date_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
34303476static PyObject *
34313477date_replace (PyDateTime_Date * self , PyObject * args , PyObject * kw )
34323478{
3433- PyObject * clone ;
3434- PyObject * tuple ;
34353479 int year = GET_YEAR (self );
34363480 int month = GET_MONTH (self );
34373481 int day = GET_DAY (self );
34383482
34393483 if (! PyArg_ParseTupleAndKeywords (args , kw , "|iii:replace" , date_kws ,
34403484 & year , & month , & day ))
34413485 return NULL ;
3442- tuple = Py_BuildValue ("iii" , year , month , day );
3443- if (tuple == NULL )
3444- return NULL ;
3445- clone = date_new (Py_TYPE (self ), tuple , NULL );
3446- Py_DECREF (tuple );
3447- return clone ;
3486+ return new_date_subclass_ex (year , month , day , (PyObject * )Py_TYPE (self ));
34483487}
34493488
34503489static Py_hash_t
@@ -4533,8 +4572,6 @@ time_hash(PyDateTime_Time *self)
45334572static PyObject *
45344573time_replace (PyDateTime_Time * self , PyObject * args , PyObject * kw )
45354574{
4536- PyObject * clone ;
4537- PyObject * tuple ;
45384575 int hh = TIME_GET_HOUR (self );
45394576 int mm = TIME_GET_MINUTE (self );
45404577 int ss = TIME_GET_SECOND (self );
@@ -4551,15 +4588,8 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
45514588 "fold must be either 0 or 1" );
45524589 return NULL ;
45534590 }
4554- tuple = Py_BuildValue ("iiiiO" , hh , mm , ss , us , tzinfo );
4555- if (tuple == NULL )
4556- return NULL ;
4557- clone = time_new (Py_TYPE (self ), tuple , NULL );
4558- if (clone != NULL ) {
4559- TIME_SET_FOLD (clone , fold );
4560- }
4561- Py_DECREF (tuple );
4562- return clone ;
4591+ return new_time_subclass_fold_ex (hh , mm , ss , us , tzinfo , fold ,
4592+ (PyObject * )Py_TYPE (self ));
45634593}
45644594
45654595static PyObject *
@@ -6003,8 +6033,6 @@ datetime_hash(PyDateTime_DateTime *self)
60036033static PyObject *
60046034datetime_replace (PyDateTime_DateTime * self , PyObject * args , PyObject * kw )
60056035{
6006- PyObject * clone ;
6007- PyObject * tuple ;
60086036 int y = GET_YEAR (self );
60096037 int m = GET_MONTH (self );
60106038 int d = GET_DAY (self );
@@ -6025,15 +6053,8 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
60256053 "fold must be either 0 or 1" );
60266054 return NULL ;
60276055 }
6028- tuple = Py_BuildValue ("iiiiiiiO" , y , m , d , hh , mm , ss , us , tzinfo );
6029- if (tuple == NULL )
6030- return NULL ;
6031- clone = datetime_new (Py_TYPE (self ), tuple , NULL );
6032- if (clone != NULL ) {
6033- DATE_SET_FOLD (clone , fold );
6034- }
6035- Py_DECREF (tuple );
6036- return clone ;
6056+ return new_datetime_subclass_fold_ex (y , m , d , hh , mm , ss , us , tzinfo , fold ,
6057+ (PyObject * )Py_TYPE (self ));
60376058}
60386059
60396060static PyObject *
0 commit comments