From d72fedb9a3e5a362eafa0d74a86c7aff4266d5c0 Mon Sep 17 00:00:00 2001 From: jaca Date: Fri, 4 Nov 2022 10:31:32 +0100 Subject: [PATCH 1/3] refactor test_recurrence_exdates_one_line --- .../tests/events/event_with_recurrence.ics | 7 +++ src/icalendar/tests/test_recurrence.py | 49 +++++++------------ 2 files changed, 24 insertions(+), 32 deletions(-) create mode 100644 src/icalendar/tests/events/event_with_recurrence.ics diff --git a/src/icalendar/tests/events/event_with_recurrence.ics b/src/icalendar/tests/events/event_with_recurrence.ics new file mode 100644 index 0000000..c2dd182 --- /dev/null +++ b/src/icalendar/tests/events/event_with_recurrence.ics @@ -0,0 +1,7 @@ +BEGIN:VEVENT +DTSTART:19960401T010000 +DTEND:19960401T020000 +RRULE:FREQ=DAILY;COUNT=100 +EXDATE:19960402T010000Z,19960403T010000Z,19960404T010000Z +SUMMARY:A recurring event with exdates +END:VEVENT diff --git a/src/icalendar/tests/test_recurrence.py b/src/icalendar/tests/test_recurrence.py index 9cf03db..1c34639 100644 --- a/src/icalendar/tests/test_recurrence.py +++ b/src/icalendar/tests/test_recurrence.py @@ -1,11 +1,24 @@ -from icalendar.caselessdict import CaselessDict +import pytest import unittest -import datetime -import icalendar +from datetime import datetime import os -import pytz +import icalendar +def test_recurrence_properly_parsed(events): + assert events.event_with_recurrence['rrule'] == {'COUNT': [100], 'FREQ': ['DAILY']} + +@pytest.mark.parametrize('i, exception_date', [ + (0, datetime(1996, 4, 2, 1, 0)), + (1, datetime(1996, 4, 3, 1, 0)), + (2, datetime(1996, 4, 4, 1, 0)) +]) +def test_exdate_properly_parsed(events, i, exception_date, in_timezone): + assert events.event_with_recurrence['exdate'].dts[i].dt == in_timezone(exception_date, 'UTC') + +def test_exdate_properly_marshalled(events): + actual = events.event_with_recurrence['exdate'].to_ical() + assert actual == b'19960402T010000Z,19960403T010000Z,19960404T010000Z' class TestRecurrence(unittest.TestCase): @@ -15,34 +28,6 @@ class TestRecurrence(unittest.TestCase): data = fp.read() self.cal = icalendar.Calendar.from_ical(data) - def test_recurrence_exdates_one_line(self): - first_event = self.cal.walk('vevent')[0] - - self.assertIsInstance(first_event, CaselessDict) - self.assertEqual( - first_event['rrule'], {'COUNT': [100], 'FREQ': ['DAILY']} - ) - - self.assertEqual( - first_event['exdate'].to_ical(), - b'19960402T010000Z,19960403T010000Z,19960404T010000Z' - ) - - self.assertEqual( - first_event['exdate'].dts[0].dt, - pytz.utc.localize(datetime.datetime(1996, 4, 2, 1, 0)) - ) - - self.assertEqual( - first_event['exdate'].dts[1].dt, - pytz.utc.localize(datetime.datetime(1996, 4, 3, 1, 0)) - ) - - self.assertEqual( - first_event['exdate'].dts[2].dt, - pytz.utc.localize(datetime.datetime(1996, 4, 4, 1, 0)) - ) - def test_recurrence_exdates_multiple_lines(self): event = self.cal.walk('vevent')[1] From 651b7bdb28588630e1aa64d3996902a81430e799 Mon Sep 17 00:00:00 2001 From: jaca Date: Sun, 6 Nov 2022 15:37:43 +0100 Subject: [PATCH 2/3] refactor test_recurrence_exdates_multiple_lines --- ...recurrence_exdates_on_different_lines.ics} | 12 ----- src/icalendar/tests/test_recurrence.py | 51 ++++++++++--------- 2 files changed, 26 insertions(+), 37 deletions(-) rename src/icalendar/tests/{recurrence.ics => events/event_with_recurrence_exdates_on_different_lines.ics} (61%) diff --git a/src/icalendar/tests/recurrence.ics b/src/icalendar/tests/events/event_with_recurrence_exdates_on_different_lines.ics similarity index 61% rename from src/icalendar/tests/recurrence.ics rename to src/icalendar/tests/events/event_with_recurrence_exdates_on_different_lines.ics index c25fd2d..8f329d7 100644 --- a/src/icalendar/tests/recurrence.ics +++ b/src/icalendar/tests/events/event_with_recurrence_exdates_on_different_lines.ics @@ -1,14 +1,3 @@ -BEGIN:VCALENDAR -METHOD:Request -PRODID:-//My product//mxm.dk/ -VERSION:2.0 -BEGIN:VEVENT -DTSTART:19960401T010000 -DTEND:19960401T020000 -RRULE:FREQ=DAILY;COUNT=100 -EXDATE:19960402T010000Z,19960403T010000Z,19960404T010000Z -SUMMARY:A recurring event with exdates -END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/Vienna:20120327T100000 DTEND;TZID=Europe/Vienna:20120327T180000 @@ -21,4 +10,3 @@ EXDATE;TZID=Europe/Vienna:20120417T100000 DTSTAMP:20130716T120638Z SUMMARY:A Recurring event with multiple exdates, one per line. END:VEVENT -END:VCALENDAR diff --git a/src/icalendar/tests/test_recurrence.py b/src/icalendar/tests/test_recurrence.py index 1c34639..0092979 100644 --- a/src/icalendar/tests/test_recurrence.py +++ b/src/icalendar/tests/test_recurrence.py @@ -1,9 +1,7 @@ -import pytest import unittest - from datetime import datetime -import os -import icalendar + +import pytest def test_recurrence_properly_parsed(events): assert events.event_with_recurrence['rrule'] == {'COUNT': [100], 'FREQ': ['DAILY']} @@ -20,27 +18,30 @@ def test_exdate_properly_marshalled(events): actual = events.event_with_recurrence['exdate'].to_ical() assert actual == b'19960402T010000Z,19960403T010000Z,19960404T010000Z' +# TODO: DOCUMENT BETTER! +# In this case we have multiple EXDATE definitions, one per line. +# Icalendar makes a list out of this instead of zipping it into one +# vDDDLists object. Actually, this feels correct for me, as it also +# allows to define different timezones per exdate line - but client +# code has to handle this as list and not blindly expecting to be able +# to call event['EXDATE'].to_ical() on it: +def test_exdate_formed_from_exdates_on_multiple_lines_is_a_list(events): + exdate = events.event_with_recurrence_exdates_on_different_lines['exdate'] + assert isinstance(exdate, list) + +@pytest.mark.parametrize('i, exception_date', [ + (0, b'20120529T100000'), + (1, b'20120403T100000'), + (2, b'20120410T100000'), + (3, b'20120501T100000'), + (4, b'20120417T100000') +]) +def test_list_exdate_properly_marshalled(events, i, exception_date): + exdate = events.event_with_recurrence_exdates_on_different_lines['exdate'] + assert exdate[i].to_ical() == exception_date + + class TestRecurrence(unittest.TestCase): - - def setUp(self): - directory = os.path.dirname(__file__) - with open(os.path.join(directory, 'recurrence.ics'), 'rb') as fp: - data = fp.read() - self.cal = icalendar.Calendar.from_ical(data) - def test_recurrence_exdates_multiple_lines(self): - event = self.cal.walk('vevent')[1] - - exdate = event['exdate'] - - # TODO: DOCUMENT BETTER! - # In this case we have multiple EXDATE definitions, one per line. - # Icalendar makes a list out of this instead of zipping it into one - # vDDDLists object. Actually, this feels correct for me, as it also - # allows to define different timezones per exdate line - but client - # code has to handle this as list and not blindly expecting to be able - # to call event['EXDATE'].to_ical() on it: - self.assertEqual(isinstance(exdate, list), True) # multiple EXDATE - self.assertEqual(exdate[0].to_ical(), b'20120529T100000') - # TODO: test for embedded timezone information! + pass From 4bee8bc97598b644b18eac0fe2e31d02c3f61d4c Mon Sep 17 00:00:00 2001 From: jaca Date: Sun, 6 Nov 2022 15:58:11 +0100 Subject: [PATCH 3/3] add test for embedded timezone information in exdate parsing --- src/icalendar/tests/test_recurrence.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/icalendar/tests/test_recurrence.py b/src/icalendar/tests/test_recurrence.py index 0092979..701b649 100644 --- a/src/icalendar/tests/test_recurrence.py +++ b/src/icalendar/tests/test_recurrence.py @@ -1,4 +1,3 @@ -import unittest from datetime import datetime import pytest @@ -29,19 +28,15 @@ def test_exdate_formed_from_exdates_on_multiple_lines_is_a_list(events): exdate = events.event_with_recurrence_exdates_on_different_lines['exdate'] assert isinstance(exdate, list) -@pytest.mark.parametrize('i, exception_date', [ - (0, b'20120529T100000'), - (1, b'20120403T100000'), - (2, b'20120410T100000'), - (3, b'20120501T100000'), - (4, b'20120417T100000') +@pytest.mark.parametrize('i, exception_date, exception_date_ics', [ + (0, datetime(2012, 5, 29, 10, 0), b'20120529T100000'), + (1, datetime(2012, 4, 3, 10, 0), b'20120403T100000'), + (2, datetime(2012, 4, 10, 10, 0), b'20120410T100000'), + (3, datetime(2012, 5, 1, 10, 0), b'20120501T100000'), + (4, datetime(2012, 4, 17, 10, 0), b'20120417T100000') ]) -def test_list_exdate_properly_marshalled(events, i, exception_date): +def test_list_exdate_to_ical_is_inverse_of_from_ical(events, i, exception_date, exception_date_ics, in_timezone): exdate = events.event_with_recurrence_exdates_on_different_lines['exdate'] - assert exdate[i].to_ical() == exception_date + assert exdate[i].dts[0].dt == in_timezone(exception_date, 'Europe/Vienna') + assert exdate[i].to_ical() == exception_date_ics - -class TestRecurrence(unittest.TestCase): - def test_recurrence_exdates_multiple_lines(self): - # TODO: test for embedded timezone information! - pass