From 509b4f01edab892c8581c5afac4378da46d822c4 Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Fri, 7 Jan 2022 17:48:18 +0100 Subject: bugfix for empty unicode string (but not None) as ical_fragment --- caldav/lib/vcal.py | 5 ++--- tests/test_vcal.py | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/caldav/lib/vcal.py b/caldav/lib/vcal.py index 2b132ae..e7eca4f 100644 --- a/caldav/lib/vcal.py +++ b/caldav/lib/vcal.py @@ -86,8 +86,7 @@ def create_ical(ical_fragment=None, objtype=None, language='en_DK', **attributes ## late import, icalendar is not an explicit requirement for v0.x of the caldav library. ## (perhaps I should change my position on that soon) import icalendar - if ical_fragment: - ical_fragment = to_wire(ical_fragment) + ical_fragment = to_wire(ical_fragment) if not ical_fragment or not re.search(b'^BEGIN:V', ical_fragment, re.MULTILINE): my_instance = icalendar.Calendar() my_instance.add('prodid', f'-//python-caldav//caldav//{language}') @@ -108,6 +107,6 @@ def create_ical(ical_fragment=None, objtype=None, language='en_DK', **attributes if attributes[attribute] is not None: component.add(attribute, attributes[attribute]) ret = my_instance.to_ical() - if ical_fragment is not None: + if ical_fragment and ical_fragment.strip(): ret = re.sub(b"^END:V", ical_fragment.strip() + b"\nEND:V", ret, flags=re.MULTILINE) return ret diff --git a/tests/test_vcal.py b/tests/test_vcal.py index 42847b9..f820da2 100644 --- a/tests/test_vcal.py +++ b/tests/test_vcal.py @@ -30,15 +30,16 @@ RRULE:FREQ=YEARLY END:VEVENT END:VCALENDAR""" - class TestVcal(TestCase): - def assertSameICal(self, ical1, ical2): + def assertSameICal(self, ical1, ical2, ignore_uid=False): """helper method""" - def normalize(s): + def normalize(s, ignore_uid): s = to_wire(s).replace(b'\r\n',b'\n').strip().split(b'\n') s.sort() + if ignore_uid: + s = [x for x in s if not x.startswith(b'UID:')] return b"\n".join(s) - self.assertEqual(normalize(ical1), normalize(ical2)) + self.assertEqual(normalize(ical1, ignore_uid), normalize(ical2, ignore_uid)) return ical2 def verifyICal(self, ical): @@ -51,7 +52,7 @@ class TestVcal(TestCase): self.assertSameICal(icalobj.to_ical(), ical) self.assertSameICal(vobj.serialize(), ical) return icalobj.to_ical() - + ## TODO: create a test_fix, should be fairly simple - for each ## "fix" that's done in the code, make up some broken ical data ## that demonstrates the brokenness we're dealing with (preferably @@ -69,16 +70,26 @@ class TestVcal(TestCase): ## One may add stuff to a fully valid ical_fragment self.assertSameICal(create_and_validate(ical_fragment=ev, priority=3), ev+"\nPRIORITY:3\n") + ## binary string or unicode string ... shouldn't matter + self.assertSameICal(create_and_validate(ical_fragment=ev.encode('utf-8'), priority=3), ev+"\nPRIORITY:3\n") + ## The returned ical_fragment should always contain BEGIN:VCALENDAR and END:VCALENDAR ical_fragment = ev.replace('BEGIN:VCALENDAR', '').replace('END:VCALENDAR', '') self.assertSameICal(create_and_validate(ical_fragment=ical_fragment), ev) - + ## Create something with a dtstart and verify that we get it back in the ical - some_ical = create_and_validate(summary="gobledok", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) - self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) + some_ical0 = create_and_validate(summary="gobledok", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) + some_ical1 = create_and_validate(summary=b"gobledok", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) + self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical0) + self.assertSameICal(some_ical0, some_ical1, ignore_uid=True) ## Verify that ical_fragment works as intended some_ical = create_and_validate(summary="gobledok", ical_fragment="PRIORITY:3", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) - + + some_ical = create_and_validate(summary="gobledok", ical_fragment=b"PRIORITY:3", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) + self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) + + some_ical = create_and_validate(summary=b"gobledok", ical_fragment="", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) + self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) -- cgit v1.2.3