@@ -1387,7 +1387,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
13871387 * Miscellaneous helpers.
13881388 */
13891389
1390- /* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1390+ /* For various reasons, we need to use tp_richcompare instead of tp_compare.
13911391 * The comparisons here all most naturally compute a cmp()-like result.
13921392 * This little helper turns that into a bool result for rich comparisons.
13931393 */
@@ -1705,31 +1705,23 @@ delta_subtract(PyObject *left, PyObject *right)
17051705 return result ;
17061706}
17071707
1708- /* This is more natural as a tp_compare, but doesn't work then: for whatever
1709- * reason, Python's try_3way_compare ignores tp_compare unless
1710- * PyInstance_Check returns true, but these aren't old-style classes.
1711- */
17121708static PyObject *
1713- delta_richcompare (PyDateTime_Delta * self , PyObject * other , int op )
1709+ delta_richcompare (PyObject * self , PyObject * other , int op )
17141710{
1715- int diff = 42 ; /* nonsense */
1716-
17171711 if (PyDelta_Check (other )) {
1718- diff = GET_TD_DAYS (self ) - GET_TD_DAYS (other );
1712+ int diff = GET_TD_DAYS (self ) - GET_TD_DAYS (other );
17191713 if (diff == 0 ) {
17201714 diff = GET_TD_SECONDS (self ) - GET_TD_SECONDS (other );
17211715 if (diff == 0 )
17221716 diff = GET_TD_MICROSECONDS (self ) -
17231717 GET_TD_MICROSECONDS (other );
17241718 }
1719+ return diff_to_bool (diff , op );
1720+ }
1721+ else {
1722+ Py_INCREF (Py_NotImplemented );
1723+ return Py_NotImplemented ;
17251724 }
1726- else if (op == Py_EQ || op == Py_NE )
1727- diff = 1 ; /* any non-zero value will do */
1728-
1729- else /* stop this from falling back to address comparison */
1730- return cmperror ((PyObject * )self , other );
1731-
1732- return diff_to_bool (diff , op );
17331725}
17341726
17351727static PyObject * delta_getstate (PyDateTime_Delta * self );
@@ -2145,7 +2137,7 @@ static PyTypeObject PyDateTime_DeltaType = {
21452137 delta_doc , /* tp_doc */
21462138 0 , /* tp_traverse */
21472139 0 , /* tp_clear */
2148- ( richcmpfunc ) delta_richcompare , /* tp_richcompare */
2140+ delta_richcompare , /* tp_richcompare */
21492141 0 , /* tp_weaklistoffset */
21502142 0 , /* tp_iter */
21512143 0 , /* tp_iternext */
@@ -2499,31 +2491,19 @@ date_isocalendar(PyDateTime_Date *self)
24992491
25002492/* Miscellaneous methods. */
25012493
2502- /* This is more natural as a tp_compare, but doesn't work then: for whatever
2503- * reason, Python's try_3way_compare ignores tp_compare unless
2504- * PyInstance_Check returns true, but these aren't old-style classes.
2505- */
25062494static PyObject *
2507- date_richcompare (PyDateTime_Date * self , PyObject * other , int op )
2495+ date_richcompare (PyObject * self , PyObject * other , int op )
25082496{
2509- int diff = 42 ; /* nonsense */
2510-
2511- if (PyDate_Check (other ))
2512- diff = memcmp (self -> data , ((PyDateTime_Date * )other )-> data ,
2513- _PyDateTime_DATE_DATASIZE );
2514-
2515- else if (PyObject_HasAttrString (other , "timetuple" )) {
2516- /* A hook for other kinds of date objects. */
2497+ if (PyDate_Check (other )) {
2498+ int diff = memcmp (((PyDateTime_Date * )self )-> data ,
2499+ ((PyDateTime_Date * )other )-> data ,
2500+ _PyDateTime_DATE_DATASIZE );
2501+ return diff_to_bool (diff , op );
2502+ }
2503+ else {
25172504 Py_INCREF (Py_NotImplemented );
25182505 return Py_NotImplemented ;
25192506 }
2520- else if (op == Py_EQ || op == Py_NE )
2521- diff = 1 ; /* any non-zero value will do */
2522-
2523- else /* stop this from falling back to address comparison */
2524- return cmperror ((PyObject * )self , other );
2525-
2526- return diff_to_bool (diff , op );
25272507}
25282508
25292509static PyObject *
@@ -2701,7 +2681,7 @@ static PyTypeObject PyDateTime_DateType = {
27012681 date_doc , /* tp_doc */
27022682 0 , /* tp_traverse */
27032683 0 , /* tp_clear */
2704- ( richcmpfunc ) date_richcompare , /* tp_richcompare */
2684+ date_richcompare , /* tp_richcompare */
27052685 0 , /* tp_weaklistoffset */
27062686 0 , /* tp_iter */
27072687 0 , /* tp_iternext */
@@ -3223,36 +3203,28 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
32233203 * Miscellaneous methods.
32243204 */
32253205
3226- /* This is more natural as a tp_compare, but doesn't work then: for whatever
3227- * reason, Python's try_3way_compare ignores tp_compare unless
3228- * PyInstance_Check returns true, but these aren't old-style classes.
3229- */
32303206static PyObject *
3231- time_richcompare (PyDateTime_Time * self , PyObject * other , int op )
3207+ time_richcompare (PyObject * self , PyObject * other , int op )
32323208{
32333209 int diff ;
32343210 naivety n1 , n2 ;
32353211 int offset1 , offset2 ;
32363212
32373213 if (! PyTime_Check (other )) {
3238- if (op == Py_EQ || op == Py_NE ) {
3239- PyObject * result = op == Py_EQ ? Py_False : Py_True ;
3240- Py_INCREF (result );
3241- return result ;
3242- }
3243- /* Stop this from falling back to address comparison. */
3244- return cmperror ((PyObject * )self , other );
3214+ Py_INCREF (Py_NotImplemented );
3215+ return Py_NotImplemented ;
32453216 }
3246- if (classify_two_utcoffsets (( PyObject * ) self , & offset1 , & n1 , Py_None ,
3247- other , & offset2 , & n2 , Py_None ) < 0 )
3217+ if (classify_two_utcoffsets (self , & offset1 , & n1 , Py_None ,
3218+ other , & offset2 , & n2 , Py_None ) < 0 )
32483219 return NULL ;
32493220 assert (n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN );
32503221 /* If they're both naive, or both aware and have the same offsets,
32513222 * we get off cheap. Note that if they're both naive, offset1 ==
32523223 * offset2 == 0 at this point.
32533224 */
32543225 if (n1 == n2 && offset1 == offset2 ) {
3255- diff = memcmp (self -> data , ((PyDateTime_Time * )other )-> data ,
3226+ diff = memcmp (((PyDateTime_Time * )self )-> data ,
3227+ ((PyDateTime_Time * )other )-> data ,
32563228 _PyDateTime_TIME_DATASIZE );
32573229 return diff_to_bool (diff , op );
32583230 }
@@ -3474,7 +3446,7 @@ static PyTypeObject PyDateTime_TimeType = {
34743446 time_doc , /* tp_doc */
34753447 0 , /* tp_traverse */
34763448 0 , /* tp_clear */
3477- ( richcmpfunc ) time_richcompare , /* tp_richcompare */
3449+ time_richcompare , /* tp_richcompare */
34783450 0 , /* tp_weaklistoffset */
34793451 0 , /* tp_iter */
34803452 0 , /* tp_iternext */
@@ -4115,54 +4087,43 @@ datetime_ctime(PyDateTime_DateTime *self)
41154087
41164088/* Miscellaneous methods. */
41174089
4118- /* This is more natural as a tp_compare, but doesn't work then: for whatever
4119- * reason, Python's try_3way_compare ignores tp_compare unless
4120- * PyInstance_Check returns true, but these aren't old-style classes.
4121- */
41224090static PyObject *
4123- datetime_richcompare (PyDateTime_DateTime * self , PyObject * other , int op )
4091+ datetime_richcompare (PyObject * self , PyObject * other , int op )
41244092{
41254093 int diff ;
41264094 naivety n1 , n2 ;
41274095 int offset1 , offset2 ;
41284096
41294097 if (! PyDateTime_Check (other )) {
4130- /* If other has a "timetuple" attr, that's an advertised
4131- * hook for other classes to ask to get comparison control.
4132- * However, date instances have a timetuple attr, and we
4133- * don't want to allow that comparison. Because datetime
4134- * is a subclass of date, when mixing date and datetime
4135- * in a comparison, Python gives datetime the first shot
4136- * (it's the more specific subtype). So we can stop that
4137- * combination here reliably.
4138- */
4139- if (PyObject_HasAttrString (other , "timetuple" ) &&
4140- ! PyDate_Check (other )) {
4141- /* A hook for other kinds of datetime objects. */
4142- Py_INCREF (Py_NotImplemented );
4143- return Py_NotImplemented ;
4098+ if (PyDate_Check (other )) {
4099+ /* Prevent invocation of date_richcompare. We want to
4100+ return NotImplemented here to give the other object
4101+ a chance. But since DateTime is a subclass of
4102+ Date, if the other object is a Date, it would
4103+ compute an ordering based on the date part alone,
4104+ and we don't want that. So force unequal or
4105+ uncomparable here in that case. */
4106+ if (op == Py_EQ )
4107+ Py_RETURN_FALSE ;
4108+ if (op == Py_NE )
4109+ Py_RETURN_TRUE ;
4110+ return cmperror (self , other );
41444111 }
4145- if (op == Py_EQ || op == Py_NE ) {
4146- PyObject * result = op == Py_EQ ? Py_False : Py_True ;
4147- Py_INCREF (result );
4148- return result ;
4149- }
4150- /* Stop this from falling back to address comparison. */
4151- return cmperror ((PyObject * )self , other );
4112+ Py_INCREF (Py_NotImplemented );
4113+ return Py_NotImplemented ;
41524114 }
41534115
4154- if (classify_two_utcoffsets ((PyObject * )self , & offset1 , & n1 ,
4155- (PyObject * )self ,
4156- other , & offset2 , & n2 ,
4157- other ) < 0 )
4116+ if (classify_two_utcoffsets (self , & offset1 , & n1 , self ,
4117+ other , & offset2 , & n2 , other ) < 0 )
41584118 return NULL ;
41594119 assert (n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN );
41604120 /* If they're both naive, or both aware and have the same offsets,
41614121 * we get off cheap. Note that if they're both naive, offset1 ==
41624122 * offset2 == 0 at this point.
41634123 */
41644124 if (n1 == n2 && offset1 == offset2 ) {
4165- diff = memcmp (self -> data , ((PyDateTime_DateTime * )other )-> data ,
4125+ diff = memcmp (((PyDateTime_DateTime * )self )-> data ,
4126+ ((PyDateTime_DateTime * )other )-> data ,
41664127 _PyDateTime_DATETIME_DATASIZE );
41674128 return diff_to_bool (diff , op );
41684129 }
@@ -4568,7 +4529,7 @@ static PyTypeObject PyDateTime_DateTimeType = {
45684529 datetime_doc , /* tp_doc */
45694530 0 , /* tp_traverse */
45704531 0 , /* tp_clear */
4571- ( richcmpfunc ) datetime_richcompare , /* tp_richcompare */
4532+ datetime_richcompare , /* tp_richcompare */
45724533 0 , /* tp_weaklistoffset */
45734534 0 , /* tp_iter */
45744535 0 , /* tp_iternext */
0 commit comments