@@ -1387,7 +1387,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1387
1387
* Miscellaneous helpers.
1388
1388
*/
1389
1389
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.
1391
1391
* The comparisons here all most naturally compute a cmp()-like result.
1392
1392
* This little helper turns that into a bool result for rich comparisons.
1393
1393
*/
@@ -1705,31 +1705,23 @@ delta_subtract(PyObject *left, PyObject *right)
1705
1705
return result ;
1706
1706
}
1707
1707
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
- */
1712
1708
static PyObject *
1713
- delta_richcompare (PyDateTime_Delta * self , PyObject * other , int op )
1709
+ delta_richcompare (PyObject * self , PyObject * other , int op )
1714
1710
{
1715
- int diff = 42 ; /* nonsense */
1716
-
1717
1711
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 );
1719
1713
if (diff == 0 ) {
1720
1714
diff = GET_TD_SECONDS (self ) - GET_TD_SECONDS (other );
1721
1715
if (diff == 0 )
1722
1716
diff = GET_TD_MICROSECONDS (self ) -
1723
1717
GET_TD_MICROSECONDS (other );
1724
1718
}
1719
+ return diff_to_bool (diff , op );
1720
+ }
1721
+ else {
1722
+ Py_INCREF (Py_NotImplemented );
1723
+ return Py_NotImplemented ;
1725
1724
}
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 );
1733
1725
}
1734
1726
1735
1727
static PyObject * delta_getstate (PyDateTime_Delta * self );
@@ -2145,7 +2137,7 @@ static PyTypeObject PyDateTime_DeltaType = {
2145
2137
delta_doc , /* tp_doc */
2146
2138
0 , /* tp_traverse */
2147
2139
0 , /* tp_clear */
2148
- ( richcmpfunc ) delta_richcompare , /* tp_richcompare */
2140
+ delta_richcompare , /* tp_richcompare */
2149
2141
0 , /* tp_weaklistoffset */
2150
2142
0 , /* tp_iter */
2151
2143
0 , /* tp_iternext */
@@ -2499,31 +2491,19 @@ date_isocalendar(PyDateTime_Date *self)
2499
2491
2500
2492
/* Miscellaneous methods. */
2501
2493
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
- */
2506
2494
static PyObject *
2507
- date_richcompare (PyDateTime_Date * self , PyObject * other , int op )
2495
+ date_richcompare (PyObject * self , PyObject * other , int op )
2508
2496
{
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 {
2517
2504
Py_INCREF (Py_NotImplemented );
2518
2505
return Py_NotImplemented ;
2519
2506
}
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 );
2527
2507
}
2528
2508
2529
2509
static PyObject *
@@ -2701,7 +2681,7 @@ static PyTypeObject PyDateTime_DateType = {
2701
2681
date_doc , /* tp_doc */
2702
2682
0 , /* tp_traverse */
2703
2683
0 , /* tp_clear */
2704
- ( richcmpfunc ) date_richcompare , /* tp_richcompare */
2684
+ date_richcompare , /* tp_richcompare */
2705
2685
0 , /* tp_weaklistoffset */
2706
2686
0 , /* tp_iter */
2707
2687
0 , /* tp_iternext */
@@ -3223,36 +3203,28 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3223
3203
* Miscellaneous methods.
3224
3204
*/
3225
3205
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
- */
3230
3206
static PyObject *
3231
- time_richcompare (PyDateTime_Time * self , PyObject * other , int op )
3207
+ time_richcompare (PyObject * self , PyObject * other , int op )
3232
3208
{
3233
3209
int diff ;
3234
3210
naivety n1 , n2 ;
3235
3211
int offset1 , offset2 ;
3236
3212
3237
3213
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 ;
3245
3216
}
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 )
3248
3219
return NULL ;
3249
3220
assert (n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN );
3250
3221
/* If they're both naive, or both aware and have the same offsets,
3251
3222
* we get off cheap. Note that if they're both naive, offset1 ==
3252
3223
* offset2 == 0 at this point.
3253
3224
*/
3254
3225
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 ,
3256
3228
_PyDateTime_TIME_DATASIZE );
3257
3229
return diff_to_bool (diff , op );
3258
3230
}
@@ -3474,7 +3446,7 @@ static PyTypeObject PyDateTime_TimeType = {
3474
3446
time_doc , /* tp_doc */
3475
3447
0 , /* tp_traverse */
3476
3448
0 , /* tp_clear */
3477
- ( richcmpfunc ) time_richcompare , /* tp_richcompare */
3449
+ time_richcompare , /* tp_richcompare */
3478
3450
0 , /* tp_weaklistoffset */
3479
3451
0 , /* tp_iter */
3480
3452
0 , /* tp_iternext */
@@ -4115,54 +4087,43 @@ datetime_ctime(PyDateTime_DateTime *self)
4115
4087
4116
4088
/* Miscellaneous methods. */
4117
4089
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
- */
4122
4090
static PyObject *
4123
- datetime_richcompare (PyDateTime_DateTime * self , PyObject * other , int op )
4091
+ datetime_richcompare (PyObject * self , PyObject * other , int op )
4124
4092
{
4125
4093
int diff ;
4126
4094
naivety n1 , n2 ;
4127
4095
int offset1 , offset2 ;
4128
4096
4129
4097
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 );
4144
4111
}
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 ;
4152
4114
}
4153
4115
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 )
4158
4118
return NULL ;
4159
4119
assert (n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN );
4160
4120
/* If they're both naive, or both aware and have the same offsets,
4161
4121
* we get off cheap. Note that if they're both naive, offset1 ==
4162
4122
* offset2 == 0 at this point.
4163
4123
*/
4164
4124
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 ,
4166
4127
_PyDateTime_DATETIME_DATASIZE );
4167
4128
return diff_to_bool (diff , op );
4168
4129
}
@@ -4568,7 +4529,7 @@ static PyTypeObject PyDateTime_DateTimeType = {
4568
4529
datetime_doc , /* tp_doc */
4569
4530
0 , /* tp_traverse */
4570
4531
0 , /* tp_clear */
4571
- ( richcmpfunc ) datetime_richcompare , /* tp_richcompare */
4532
+ datetime_richcompare , /* tp_richcompare */
4572
4533
0 , /* tp_weaklistoffset */
4573
4534
0 , /* tp_iter */
4574
4535
0 , /* tp_iternext */
0 commit comments