From 67e47bce745813f1694ba755bf3b79fc8849a37e Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Fri, 7 Jan 2022 21:33:22 +0100 Subject: bugfix: no_overwrite, no_create flags in save_todo would only work for events --- caldav/objects.py | 15 +++++++++------ tests/test_caldav.py | 21 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/caldav/objects.py b/caldav/objects.py index 91f4af9..4032273 100644 --- a/caldav/objects.py +++ b/caldav/objects.py @@ -974,7 +974,7 @@ class Calendar(DAVObject): except error.NotFoundError: raise except Exception as err: - raise NotImplementedError("The object_by_uid is not compatible with some server implementations. work in progress.") + raise NotImplementedError(f"Server said {str(err)}. The object_by_uid is not compatible with some server implementations. work in progress.") # Ref Lucas Verney, we've actually done a substring search, if the # uid given in the query is short (i.e. just "0") we're likely to @@ -1473,17 +1473,20 @@ class CalendarObjectResource(DAVObject): ## a unique new calendar item is created to the server without ## overwriting old stuff or vice versa - it seems silly to me ## to do a PUT instead of POST when creating new data). + ## TODO: the "find id"-logic is duplicated in _create, + ## should be refactored if not self.id: - try: - self.id = self.vobject_instance.vevent.uid.value - except AttributeError: - pass + for component in self.vobject_instance.getChildren(): + if hasattr(component, 'uid'): + self.id = component.uid.value if not self.id and no_create: raise error.ConsistencyError("no_create flag was set, but no ID given") existing = None ## some servers require one to explicitly search for the right kind of object. ## todo: would arguably be nicer to verify the type of the object and take it from there - if obj_type: + if not self.id: + methods = [] + elif obj_type: methods = (getattr(self.parent, "%s_by_uid" % obj_type),) else: methods = (self.parent.object_by_uid, self.parent.event_by_uid, self.parent.todo_by_uid, self.parent.journal_by_uid) diff --git a/tests/test_caldav.py b/tests/test_caldav.py index a4fa1b4..a516843 100644 --- a/tests/test_caldav.py +++ b/tests/test_caldav.py @@ -1041,6 +1041,7 @@ class RepeatedFunctionalTestsBaseClass(object): # add todo-item logging.info("Adding todo item to calendar Yep") t1 = c.save_todo(todo) + assert_equal(t1.id, '20070313T123432Z-456553@example.com') # c.todos() should give a full list of todo items logging.info("Fetching the full list of todo items (should be one)") @@ -1398,7 +1399,10 @@ class RepeatedFunctionalTestsBaseClass(object): # add event e1 = c.save_event(ev1) + if not self.check_compatibility_flag('no_todo'): + t1 = c.save_todo(todo) assert_not_equal(e1.url, None) + assert_not_equal(t1.url, None) if not self.check_compatibility_flag('event_by_url_is_broken'): assert_equal(c.event_by_url(e1.url).url, e1.url) assert_equal(c.event_by_uid(e1.id).url, e1.url) @@ -1407,25 +1411,36 @@ class RepeatedFunctionalTestsBaseClass(object): ## (but some calendars may throw a "409 Conflict") if not self.check_compatibility_flag('no_overwrite'): e2 = c.save_event(ev1) + if not self.check_compatibility_flag('no_todo'): + t2 = c.save_todo(todo) ## add same event with "no_create". Should work like a charm. e2 = c.save_event(ev1, no_create=True) - - e2.instance.vevent.summary.value = e2.instance.vevent.summary.value + '!' + if not self.check_compatibility_flag('no_todo'): + t2 = c.save_todo(todo, no_create=True) ## this should also work. + e2.instance.vevent.summary.value = e2.instance.vevent.summary.value + '!' e2.save(no_create=True) + if not self.check_compatibility_flag('no_todo'): + t2.instance.vtodo.summary.value = t2.instance.vtodo.summary.value + '!' + t2.save(no_create=True) + + if not self.check_compatibility_flag('event_by_url_is_broken'): e3 = c.event_by_url(e1.url) assert_equal(e3.instance.vevent.summary.value, 'Bastille Day Party!') ## "no_overwrite" should throw a ConsistencyError assert_raises(error.ConsistencyError, c.save_event, ev1, no_overwrite=True) + if not self.check_compatibility_flag('no_todo'): + assert_raises(error.ConsistencyError, c.save_todo, todo, no_overwrite=True) # delete event e1.delete() - + if not self.check_compatibility_flag('no_todo'): + t1.delete # Verify that we can't look it up, both by URL and by ID assert_raises(error.NotFoundError, c.event_by_url, e1.url) -- cgit v1.2.3