# HG changeset patch # User Paul Boddie # Date 1508098565 -7200 # Node ID c4521a67f95d65d3e98aae50c3053a1039b54fe6 # Parent 22a0b7b99d8f1124edb1663ab426913fed59ddfc Support rule-originating period exclusion. Initialise new attendees and test for the organiser as a new attendee when setting their attendance. diff -r 22a0b7b99d8f -r c4521a67f95d imiptools/client.py --- a/imiptools/client.py Sun Oct 15 21:34:23 2017 +0200 +++ b/imiptools/client.py Sun Oct 15 22:16:05 2017 +0200 @@ -804,12 +804,8 @@ if to_set: self.obj.set_periods(to_set) - # Exclude only the main period, if appropriate. - - if to_exclude: - main = get_main_period(to_exclude) - if main: - self.obj.update_exceptions([main], []) + if to_exclude: + self.obj.update_exceptions(to_exclude, to_set or []) # General message generation methods. diff -r 22a0b7b99d8f -r c4521a67f95d imipweb/data.py --- a/imipweb/data.py Sun Oct 15 21:34:23 2017 +0200 +++ b/imipweb/data.py Sun Oct 15 22:16:05 2017 +0200 @@ -412,8 +412,9 @@ "Return whether an update can be prepared and sent." return not self.is_organiser() or \ + not self.obj.is_shared() or \ self.obj.is_shared() and self.state.get("changed") and \ - self.have_other_attendees() + self.have_other_attendees() def have_other_attendees(self): @@ -471,7 +472,7 @@ "Add a blank attendee." attendees = self.state.get("attendees") - attendees[uri or ""] = {} + attendees[uri or ""] = {"PARTSTAT" : "NEEDS-ACTION"} def add_suggested_attendee(self, index): @@ -511,9 +512,9 @@ # Cancel any removed periods. if operation == "remove": - for p in current: + for index, p in enumerate(current): if p == period: - p.cancelled = True + self.cancel_periods([index]) break # Add or replace any other suggestions. @@ -573,6 +574,12 @@ for index in to_remove: del periods[index] + def can_edit_attendance(self): + + "Return whether the organiser's attendance can be edited." + + return self.state.get("attendees").has_key(self.user) + def edit_attendance(self, partstat): "Set the 'partstat' of the current user, if attending." @@ -580,7 +587,9 @@ attendees = self.state.get("attendees") attr = attendees.get(self.user) - if attr: + # Set the attendance for the user, if attending. + + if attr is not None: new_attr = {} new_attr.update(attr) new_attr["PARTSTAT"] = partstat @@ -1287,6 +1296,14 @@ cancelled_removed = select_recurrences(cancelled, removed).values() + # Cancelled periods originating from rules must be excluded since there are + # no explicit instances to be deleted. + + cancelled_rule = [] + for p in cancelled_removed: + if p.origin == "RRULE": + cancelled_rule.append(p) + # Reinstated periods are previously-cancelled periods that are now modified # periods, and they appear in updates. @@ -1300,7 +1317,6 @@ # As organiser... if is_organiser: - to_exclude = [] # For unshared events... # All modifications redefine the event. @@ -1309,9 +1325,11 @@ # New periods should cause the event to be redefined. # Other changes should also cause event redefinition. # Event redefinition should only occur if no replacement periods exist. + # Cancelled rule-originating periods must be excluded. if not is_shared or new and not replaced: to_set = active_periods + to_exclude = cancelled_rule to_unschedule = [] to_reschedule = [] to_add = [] @@ -1323,6 +1341,7 @@ else: to_set = [] + to_exclude = [] to_unschedule = cancelled_removed to_reschedule = list(chain(replaced_modified, retained_modified, reinstated)) to_add = new