|
1 | 1 | from __future__ import print_function |
| 2 | + |
2 | 3 | import copy |
| 4 | +import operator |
| 5 | +import sys |
3 | 6 | import unittest |
4 | 7 | from collections import namedtuple |
5 | 8 | from datetime import datetime, timedelta |
|
8 | 11 | import pytest |
9 | 12 | from numpy.testing import assert_almost_equal, assert_equal |
10 | 13 |
|
| 14 | +import cftime |
11 | 15 | from cftime import datetime as datetimex |
12 | 16 | from cftime import real_datetime |
13 | 17 | from cftime import (DateFromJulianDay, Datetime360Day, DatetimeAllLeap, |
14 | 18 | DatetimeGregorian, DatetimeJulian, DatetimeNoLeap, |
15 | 19 | DatetimeProlepticGregorian, JulianDayFromDate, _parse_date, |
16 | 20 | date2index, date2num, num2date, utime) |
17 | | -import cftime |
18 | 21 |
|
19 | 22 | # test cftime module for netCDF time <--> python datetime conversions. |
20 | 23 |
|
@@ -1106,12 +1109,75 @@ def not_comparable_3(): |
1106 | 1109 | self.datetime_date1 > self.date2_365_day |
1107 | 1110 |
|
1108 | 1111 | def not_comparable_4(): |
1109 | | - "compare a datetime instance to something other than a datetime" |
| 1112 | + "compare a datetime instance to non-datetime" |
1110 | 1113 | self.date1_365_day > 0 |
1111 | 1114 |
|
| 1115 | + def not_comparable_5(): |
| 1116 | + "compare non-datetime to a datetime instance" |
| 1117 | + 0 < self.date_1_365_day |
| 1118 | + |
1112 | 1119 | for func in [not_comparable_1, not_comparable_2, not_comparable_3, not_comparable_4]: |
1113 | 1120 | self.assertRaises(TypeError, func) |
1114 | 1121 |
|
| 1122 | + @pytest.mark.skipif(sys.version_info.major != 2, |
| 1123 | + reason='python2 specific, non-comparable test') |
| 1124 | + def test_richcmp_py2(self): |
| 1125 | + class Rich(object): |
| 1126 | + """Dummy class with traditional rich comparison support.""" |
| 1127 | + def __lt__(self, other): |
| 1128 | + raise NotImplementedError('__lt__') |
| 1129 | + def __le__(self, other): |
| 1130 | + raise NotImplementedError('__le__') |
| 1131 | + def __eq__(self, other): |
| 1132 | + raise NotImplementedError('__eq__') |
| 1133 | + def __ne__(self, other): |
| 1134 | + raise NotImplementedError('__ne__') |
| 1135 | + def __gt__(self, other): |
| 1136 | + raise NotImplementedError('__gt__') |
| 1137 | + def __ge__(self, other): |
| 1138 | + raise NotImplementedError('__ge__') |
| 1139 | + |
| 1140 | + class CythonRich(object): |
| 1141 | + """Dummy class with spoof cython rich comparison support.""" |
| 1142 | + def __richcmp__(self, other): |
| 1143 | + """ |
| 1144 | + This method is never called. However it is introspected |
| 1145 | + by the cftime.datetime.__richcmp__ method, which will then |
| 1146 | + return NotImplemented, causing Python to call this classes |
| 1147 | + __cmp__ method as a back-stop, and hence spoofing the |
| 1148 | + cython specific rich comparison behaviour. |
| 1149 | + """ |
| 1150 | + pass |
| 1151 | + def __cmp__(self, other): |
| 1152 | + raise NotImplementedError('__richcmp__') |
| 1153 | + |
| 1154 | + class Pass(object): |
| 1155 | + """Dummy class with no rich comparison support whatsoever.""" |
| 1156 | + pass |
| 1157 | + |
| 1158 | + class Pass___cmp__(object): |
| 1159 | + """Dummy class that delegates all comparisons.""" |
| 1160 | + def __cmp__(self, other): |
| 1161 | + return NotImplemented |
| 1162 | + |
| 1163 | + # Test LHS operand comparison operator processing. |
| 1164 | + for op, expected in [(operator.gt, '__lt__'), (operator.ge, '__le__'), |
| 1165 | + (operator.eq, '__eq__'), (operator.ne, '__ne__'), |
| 1166 | + (operator.lt, '__gt__'), (operator.le, '__ge__')]: |
| 1167 | + with self.assertRaisesRegexp(NotImplementedError, expected): |
| 1168 | + op(self.date1_365_day, Rich()) |
| 1169 | + |
| 1170 | + with self.assertRaisesRegexp(NotImplementedError, '__richcmp__'): |
| 1171 | + op(self.date1_365_day, CythonRich()) |
| 1172 | + |
| 1173 | + # Test RHS operand comparison operator processing. |
| 1174 | + for op in [operator.gt, operator.ge, operator.eq, operator.ne, |
| 1175 | + operator.lt, operator.le]: |
| 1176 | + with self.assertRaisesRegexp(TypeError, 'cannot compare'): |
| 1177 | + op(Pass(), self.date1_365_day) |
| 1178 | + |
| 1179 | + with self.assertRaisesRegexp(TypeError, 'cannot compare'): |
| 1180 | + op(Pass___cmp__(), self.date1_365_day) |
1115 | 1181 |
|
1116 | 1182 |
|
1117 | 1183 | class issue17TestCase(unittest.TestCase): |
|
0 commit comments