1.1 --- a/imip_manager.py Wed Mar 04 18:03:35 2015 +0100
1.2 +++ b/imip_manager.py Thu Mar 05 15:26:50 2015 +0100
1.3 @@ -42,7 +42,8 @@
1.4 from imiptools.period import add_day_start_points, add_empty_days, add_slots, \
1.5 convert_periods, get_freebusy_details, \
1.6 get_scale, have_conflict, get_slots, get_spans, \
1.7 - partition_by_day, remove_period, update_freebusy
1.8 + partition_by_day, remove_period, remove_affected_period, \
1.9 + update_freebusy
1.10 from imiptools.profile import Preferences
1.11 import imip_store
1.12 import markup
1.13 @@ -357,6 +358,9 @@
1.14 obj = self.objects[(uid, recurrenceid)] = fragment and Object(fragment)
1.15 return obj
1.16
1.17 + def _get_recurrences(self, uid):
1.18 + return self.store.get_recurrences(self.user, uid)
1.19 +
1.20 def _get_requests(self):
1.21 if self.requests is None:
1.22 cancellations = self.store.get_cancellations(self.user)
1.23 @@ -369,8 +373,16 @@
1.24 for uid, recurrenceid in self._get_requests():
1.25 obj = self._get_object(uid, recurrenceid)
1.26 if obj:
1.27 - for start, end in obj.get_periods_for_freebusy(self.get_tzid(), self.get_window_end()):
1.28 - summary.append((start, end, uid, obj.get_value("TRANSP"), recurrenceid))
1.29 + periods = obj.get_periods_for_freebusy(self.get_tzid(), self.get_window_end())
1.30 +
1.31 + # Subtract any recurrences from the free/busy details of a parent
1.32 + # object.
1.33 +
1.34 + recurrenceids = self._get_recurrences(uid)
1.35 +
1.36 + for start, end in periods:
1.37 + if recurrenceid or start not in recurrenceids:
1.38 + summary.append((start, end, uid, obj.get_value("TRANSP"), recurrenceid))
1.39 return summary
1.40
1.41 # Preference methods.
1.42 @@ -414,10 +426,18 @@
1.43 is_only_organiser = self.user not in uri_values(obj.get_values("ATTENDEE"))
1.44
1.45 freebusy = self.store.get_freebusy(self.user)
1.46 +
1.47 update_freebusy(freebusy,
1.48 obj.get_periods_for_freebusy(self.get_tzid(), self.get_window_end()),
1.49 is_only_organiser and "ORG" or obj.get_value("TRANSP"),
1.50 uid, recurrenceid)
1.51 +
1.52 + # Subtract any recurrences from the free/busy details of a parent
1.53 + # object.
1.54 +
1.55 + for recurrenceid in self._get_recurrences(uid):
1.56 + remove_affected_period(freebusy, uid, recurrenceid)
1.57 +
1.58 self.store.set_freebusy(self.user, freebusy)
1.59
1.60 def remove_from_freebusy(self, uid, recurrenceid=None):
1.61 @@ -1086,10 +1106,11 @@
1.62
1.63 # Obtain any parent object if this object is a specific recurrence.
1.64
1.65 + uid = obj.get_value("UID")
1.66 recurrenceid = format_datetime(obj.get_utc_datetime("RECURRENCE-ID"))
1.67
1.68 if recurrenceid:
1.69 - obj = self._get_object(obj.get_value("UID"))
1.70 + obj = self._get_object(uid)
1.71 if not obj:
1.72 return
1.73
1.74 @@ -1098,6 +1119,7 @@
1.75 # Obtain the periods associated with the event in the user's time zone.
1.76
1.77 periods = obj.get_periods(self.get_tzid(), self.get_window_end())
1.78 + recurrenceids = self._get_recurrences(uid)
1.79
1.80 if len(periods) == 1:
1.81 return
1.82 @@ -1115,7 +1137,7 @@
1.83
1.84 for start, end in periods:
1.85 start_utc = format_datetime(to_timezone(start, "UTC"))
1.86 - css = recurrenceid and start_utc == recurrenceid and "replaced" or ""
1.87 + css = recurrenceids and start_utc in recurrenceids and "replaced" or ""
1.88
1.89 page.tr()
1.90 page.td(self.format_datetime(start, "long"), class_=css)
2.1 --- a/imiptools/content.py Wed Mar 04 18:03:35 2015 +0100
2.2 +++ b/imiptools/content.py Thu Mar 05 15:26:50 2015 +0100
2.3 @@ -242,7 +242,12 @@
2.4 self.update_freebusy_for_participant(freebusy, periods, participant_attr,
2.5 for_organiser and self.is_not_attendee(participant, self.obj))
2.6
2.7 - self.remove_freebusy_for_original_recurrence(freebusy)
2.8 + # Subtract any recurrences from the free/busy details of a parent
2.9 + # object.
2.10 +
2.11 + for recurrenceid in self.store.get_recurrences(user, self.uid):
2.12 + remove_affected_period(freebusy, self.uid, recurrenceid)
2.13 +
2.14 self.store.set_freebusy_for_other(user, freebusy, participant)
2.15
2.16 def update_freebusy_from_organiser(self, attendee, organiser_item):
2.17 @@ -511,53 +516,6 @@
2.18 sequence = self.obj.get_value("SEQUENCE") or "0"
2.19 self.obj["SEQUENCE"] = [(str(int(sequence) + (increment and 1 or 0)), {})]
2.20
2.21 - def detach_recurrence(self, identity):
2.22 -
2.23 - "Detach the current object from its parent if it is a recurrence."
2.24 -
2.25 - # Where a recurring object is updated by a specific occurrence, the
2.26 - # details of the recurring "parent" must be changed.
2.27 -
2.28 - obj = self.get_parent_object(identity)
2.29 - if not obj:
2.30 - return
2.31 -
2.32 - # The original recurrence is obtained, although the recurrence
2.33 - # identifier could be converted back to a UTC datetime and used
2.34 - # instead.
2.35 -
2.36 - recurrence = self.obj.get_datetime("RECURRENCE-ID")
2.37 - if not obj.has_recurrence(self.get_tzid(identity), recurrence):
2.38 - return
2.39 -
2.40 - # To detach the occurrence, the exceptions to the defined recurrence are
2.41 - # modified.
2.42 -
2.43 - item = obj.get_item("EXDATE")
2.44 - if item:
2.45 - exdates, exdate_attr = item
2.46 - if not isinstance(exdates, list):
2.47 - exdates = [exdates]
2.48 - else:
2.49 - exdates, exdate_attr = [], {}
2.50 -
2.51 - # Convert the occurrence to the same time regime as the other
2.52 - # exceptions.
2.53 -
2.54 - exdate_tzid = exdate_attr.get("TZID")
2.55 - exdate = recurrence
2.56 - if exdate_tzid:
2.57 - exdate = to_timezone(exdate, exdate_tzid)
2.58 - else:
2.59 - exdate = to_timezone(exdate, "UTC")
2.60 -
2.61 - # Update the exceptions and store the modified parent event.
2.62 -
2.63 - exdates.append(format_datetime(exdate))
2.64 - obj["EXDATE"] = [(exdates, exdate_attr)]
2.65 -
2.66 - self.store.set_event(identity, self.uid, None, obj.to_node())
2.67 -
2.68 def get_tzid(self, identity):
2.69
2.70 "Return the time regime applicable for the given 'identity'."
3.1 --- a/imiptools/handlers/person.py Wed Mar 04 18:03:35 2015 +0100
3.2 +++ b/imiptools/handlers/person.py Thu Mar 05 15:26:50 2015 +0100
3.3 @@ -53,10 +53,6 @@
3.4
3.5 self.store.set_event(attendee, self.uid, self.recurrenceid, self.obj.to_node())
3.6
3.7 - # Detach any recurrence from its parent.
3.8 -
3.9 - self.detach_recurrence(attendee)
3.10 -
3.11 # Queue any request.
3.12
3.13 if queue:
4.1 --- a/imiptools/handlers/person_outgoing.py Wed Mar 04 18:03:35 2015 +0100
4.2 +++ b/imiptools/handlers/person_outgoing.py Thu Mar 05 15:26:50 2015 +0100
4.3 @@ -22,6 +22,7 @@
4.4
4.5 from imiptools.content import Handler
4.6 from imiptools.data import get_window_end, uri_dict, uri_item, uri_values
4.7 +from imiptools.period import remove_affected_period
4.8
4.9 class PersonHandler(Handler):
4.10
4.11 @@ -69,10 +70,6 @@
4.12
4.13 self.store.dequeue_request(identity, self.uid, self.recurrenceid)
4.14
4.15 - # Detach any recurrence from its parent.
4.16 -
4.17 - self.detach_recurrence(identity)
4.18 -
4.19 # Update free/busy information.
4.20
4.21 if update_freebusy:
4.22 @@ -98,7 +95,12 @@
4.23 self.update_freebusy_for_participant(freebusy, periods, attr,
4.24 from_organiser and self.is_not_attendee(identity, obj))
4.25
4.26 - self.remove_freebusy_for_original_recurrence(freebusy)
4.27 + # Subtract any recurrences from the free/busy details of a parent
4.28 + # object.
4.29 +
4.30 + for recurrenceid in self.store.get_recurrences(identity, self.uid):
4.31 + remove_affected_period(freebusy, self.uid, recurrenceid)
4.32 +
4.33 self.store.set_freebusy(identity, freebusy)
4.34
4.35 if self.publisher:
5.1 --- a/imiptools/handlers/resource.py Wed Mar 04 18:03:35 2015 +0100
5.2 +++ b/imiptools/handlers/resource.py Thu Mar 05 15:26:50 2015 +0100
5.3 @@ -23,6 +23,7 @@
5.4 from imiptools.data import get_address, get_uri, get_window_end, to_part
5.5 from imiptools.dates import get_default_timezone
5.6 from imiptools.handlers.common import CommonFreebusy
5.7 +from imiptools.period import remove_affected_period
5.8
5.9 class ResourceHandler(Handler):
5.10
5.11 @@ -87,10 +88,6 @@
5.12 event = self.obj.to_node()
5.13 self.store.set_event(attendee, self.uid, self.recurrenceid, event)
5.14
5.15 - # Detach any recurrence from its parent.
5.16 -
5.17 - self.detach_recurrence(attendee)
5.18 -
5.19 # Only update free/busy details if the event is scheduled.
5.20
5.21 if scheduled:
5.22 @@ -98,12 +95,11 @@
5.23 else:
5.24 self.remove_from_freebusy(freebusy)
5.25
5.26 - # For any parent object, refresh the updated periods.
5.27 + # Subtract any recurrences from the free/busy details of a parent
5.28 + # object.
5.29
5.30 - obj = self.get_parent_object(attendee)
5.31 - if obj:
5.32 - periods = obj.get_periods_for_freebusy(tzid, get_window_end(tzid))
5.33 - self._update_freebusy(freebusy, periods, None)
5.34 + for recurrenceid in self.store.get_recurrences(attendee, self.uid):
5.35 + remove_affected_period(freebusy, self.uid, recurrenceid)
5.36
5.37 self.store.set_freebusy(attendee, freebusy)
5.38