summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-02-11 11:06:43 (GMT)
committerGitHub <noreply@github.com>2024-02-11 11:06:43 (GMT)
commitb1043607884d774acabd255ecdcebb159f76a2fb (patch)
tree4621a610aa02126372c5a23d5ee55d7c2d5a9f5d /Lib/test
parentd9d6909697501a2604d5895f9f88aeec61274ab0 (diff)
downloadcpython-b1043607884d774acabd255ecdcebb159f76a2fb.zip
cpython-b1043607884d774acabd255ecdcebb159f76a2fb.tar.gz
cpython-b1043607884d774acabd255ecdcebb159f76a2fb.tar.bz2
gh-49766: Make date-datetime comparison more symmetric and flexible (GH-114760)
Now the special comparison methods like `__eq__` and `__lt__` return NotImplemented if one of comparands is date and other is datetime instead of ignoring the time part and the time zone or forcefully return "not equal" or raise TypeError. It makes comparison of date and datetime subclasses more symmetric and allows to change the default behavior by overriding the special comparison methods in subclasses. It is now the same as if date and datetime was independent classes.
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/datetimetester.py64
1 files changed, 36 insertions, 28 deletions
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 53ad5e5..980a8e6 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -5435,42 +5435,50 @@ class TestTimezoneConversions(unittest.TestCase):
class Oddballs(unittest.TestCase):
- def test_bug_1028306(self):
+ def test_date_datetime_comparison(self):
+ # bpo-1028306, bpo-5516 (gh-49766)
# Trying to compare a date to a datetime should act like a mixed-
# type comparison, despite that datetime is a subclass of date.
as_date = date.today()
as_datetime = datetime.combine(as_date, time())
- self.assertTrue(as_date != as_datetime)
- self.assertTrue(as_datetime != as_date)
- self.assertFalse(as_date == as_datetime)
- self.assertFalse(as_datetime == as_date)
- self.assertRaises(TypeError, lambda: as_date < as_datetime)
- self.assertRaises(TypeError, lambda: as_datetime < as_date)
- self.assertRaises(TypeError, lambda: as_date <= as_datetime)
- self.assertRaises(TypeError, lambda: as_datetime <= as_date)
- self.assertRaises(TypeError, lambda: as_date > as_datetime)
- self.assertRaises(TypeError, lambda: as_datetime > as_date)
- self.assertRaises(TypeError, lambda: as_date >= as_datetime)
- self.assertRaises(TypeError, lambda: as_datetime >= as_date)
-
- # Nevertheless, comparison should work with the base-class (date)
- # projection if use of a date method is forced.
- self.assertEqual(as_date.__eq__(as_datetime), True)
- different_day = (as_date.day + 1) % 20 + 1
- as_different = as_datetime.replace(day= different_day)
- self.assertEqual(as_date.__eq__(as_different), False)
+ date_sc = SubclassDate(as_date.year, as_date.month, as_date.day)
+ datetime_sc = SubclassDatetime(as_date.year, as_date.month,
+ as_date.day, 0, 0, 0)
+ for d in (as_date, date_sc):
+ for dt in (as_datetime, datetime_sc):
+ for x, y in (d, dt), (dt, d):
+ self.assertTrue(x != y)
+ self.assertFalse(x == y)
+ self.assertRaises(TypeError, lambda: x < y)
+ self.assertRaises(TypeError, lambda: x <= y)
+ self.assertRaises(TypeError, lambda: x > y)
+ self.assertRaises(TypeError, lambda: x >= y)
# And date should compare with other subclasses of date. If a
# subclass wants to stop this, it's up to the subclass to do so.
- date_sc = SubclassDate(as_date.year, as_date.month, as_date.day)
- self.assertEqual(as_date, date_sc)
- self.assertEqual(date_sc, as_date)
-
# Ditto for datetimes.
- datetime_sc = SubclassDatetime(as_datetime.year, as_datetime.month,
- as_date.day, 0, 0, 0)
- self.assertEqual(as_datetime, datetime_sc)
- self.assertEqual(datetime_sc, as_datetime)
+ for x, y in ((as_date, date_sc),
+ (date_sc, as_date),
+ (as_datetime, datetime_sc),
+ (datetime_sc, as_datetime)):
+ self.assertTrue(x == y)
+ self.assertFalse(x != y)
+ self.assertFalse(x < y)
+ self.assertFalse(x > y)
+ self.assertTrue(x <= y)
+ self.assertTrue(x >= y)
+
+ # Nevertheless, comparison should work if other object is an instance
+ # of date or datetime class with overridden comparison operators.
+ # So special methods should return NotImplemented, as if
+ # date and datetime were independent classes.
+ for x, y in (as_date, as_datetime), (as_datetime, as_date):
+ self.assertEqual(x.__eq__(y), NotImplemented)
+ self.assertEqual(x.__ne__(y), NotImplemented)
+ self.assertEqual(x.__lt__(y), NotImplemented)
+ self.assertEqual(x.__gt__(y), NotImplemented)
+ self.assertEqual(x.__gt__(y), NotImplemented)
+ self.assertEqual(x.__ge__(y), NotImplemented)
def test_extra_attributes(self):
with self.assertWarns(DeprecationWarning):