diff --git a/CHANGES.rst b/CHANGES.rst index b46dae7f..d0682ba3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,11 +14,11 @@ Breaking changes: New features: -- ... +- vDDDTypes is hashable #487 #492 [niccokunzmann] Bug fixes: -- ... +- vDDDTypes' equality also checks the dt attribute #497 #492 [niccokunzmann] 5.0.2 (2022-11-03) ------------------ diff --git a/src/icalendar/prop.py b/src/icalendar/prop.py index f6c261c0..dcbb9260 100644 --- a/src/icalendar/prop.py +++ b/src/icalendar/prop.py @@ -320,9 +320,12 @@ def to_ical(self): def __eq__(self, other): if isinstance(other, vDDDTypes): - return self.params == other.params + return self.params == other.params and self.dt == other.dt return False + def __hash__(self): + return hash(self.dt) + @classmethod def from_ical(cls, ical, timezone=None): if isinstance(ical, cls): diff --git a/src/icalendar/tests/test_unit_prop.py b/src/icalendar/tests/test_unit_prop.py index 05493205..b732b233 100644 --- a/src/icalendar/tests/test_unit_prop.py +++ b/src/icalendar/tests/test_unit_prop.py @@ -4,10 +4,12 @@ from datetime import timedelta from icalendar.parser import Parameters import unittest -from icalendar.prop import vDatetime +from icalendar.prop import vDatetime, vDDDTypes from icalendar.windows_to_olson import WINDOWS_TO_OLSON - +import pytest import pytz +from copy import deepcopy +from dateutil import tz class TestProp(unittest.TestCase): @@ -112,27 +114,6 @@ def test_prop_vDDDTypes(self): # Bad input self.assertRaises(ValueError, vDDDTypes, 42) - def test_vDDDTypes_equivalance(self): - from ..prop import vDDDTypes - from copy import deepcopy - - vDDDTypes = [ - vDDDTypes(pytz.timezone('US/Eastern').localize(datetime(year=2022, month=7, day=22, hour=12, minute=7))), - vDDDTypes(datetime(year=2022, month=7, day=22, hour=12, minute=7)), - vDDDTypes(date(year=2022, month=7, day=22)), - vDDDTypes(time(hour=22, minute=7, second=2))] - - for v_type in vDDDTypes: - self.assertEqual(v_type, deepcopy(v_type)) - for other in vDDDTypes: - if other is v_type: - continue - self.assertNotEqual(v_type, other) - - # see if equivalnce fails for other types - self.assertNotEqual(v_type, 42) - self.assertNotEqual(v_type, 'test') - def test_prop_vDate(self): from ..prop import vDate @@ -518,6 +499,39 @@ def test_prop_TypesFactory(self): ) + +vDDDTypes_list = [ + vDDDTypes(pytz.timezone('US/Eastern').localize(datetime(year=2022, month=7, day=22, hour=12, minute=7))), + vDDDTypes(datetime(year=2022, month=7, day=22, hour=12, minute=7)), + vDDDTypes(datetime(year=2022, month=7, day=22, hour=12, minute=7, tzinfo=tz.UTC)), + vDDDTypes(date(year=2022, month=7, day=22)), + vDDDTypes(date(year=2022, month=7, day=23)), + vDDDTypes(time(hour=22, minute=7, second=2)) +] + +def identity(x): + return x + +@pytest.mark.parametrize("map", [ + deepcopy, + identity, + hash, +]) +@pytest.mark.parametrize("v_type", vDDDTypes_list) +@pytest.mark.parametrize("other", vDDDTypes_list) +def test_vDDDTypes_equivalance(map, v_type, other): + if v_type is other: + assert map(v_type) == map(other), f"identity implies equality: {map.__name__}()" + assert not (map(v_type) != map(other)), f"identity implies equality: {map.__name__}()" + else: + assert map(v_type) != map(other), f"expected inequality: {map.__name__}()" + assert not (map(v_type) == map(other)), f"expected inequality: {map.__name__}()" + +@pytest.mark.parametrize("v_type", vDDDTypes_list) +def test_inequality_with_different_types(v_type): + assert v_type != 42 + assert v_type != 'test' + class TestPropertyValues(unittest.TestCase): def test_vDDDLists_timezone(self):