# HG changeset patch # User Paul Boddie # Date 1414363151 -3600 # Node ID 77f2ad0d6f88c56f024270c7a5c8d2b6a2fbd8ec # Parent 32997a697007cf2998a320385cd589b275fcbbdc Moved free/busy update functionality into the common content handling module. diff -r 32997a697007 -r 77f2ad0d6f88 imiptools/content.py --- a/imiptools/content.py Sun Oct 26 23:10:12 2014 +0100 +++ b/imiptools/content.py Sun Oct 26 23:39:11 2014 +0100 @@ -7,6 +7,7 @@ from datetime import date, datetime, timedelta from email.mime.text import MIMEText +from imiptools.period import have_conflict, insert_period, remove_period from pytz import timezone, UnknownTimeZoneError from vCalendar import parse, ParseError, to_dict from vRecurrence import get_parameters, get_rule @@ -155,6 +156,11 @@ def get_periods(obj, window_size=100): + """ + Return periods for the given object 'obj', confining materialised periods + to the given 'window_size' in days starting from the present moment. + """ + dtstart = get_utc_datetime(obj, "DTSTART") dtend = get_utc_datetime(obj, "DTEND") @@ -186,6 +192,35 @@ return periods +def update_freebusy(attendee, periods, transp, uid, store): + + """ + For the given 'attendee', update the free/busy details with the given + 'periods', 'transp' setting and 'uid' in the 'store'. Where no conflict + occurs, return the updated free/busy details; otherwise return None. + """ + + conflict = False + freebusy = store.get_freebusy(attendee) or [] + + if freebusy: + remove_period(freebusy, uid) + conflict = have_conflict(freebusy, periods) + + # If the event can be scheduled, it is registered in the free/busy list. + + if not conflict: + + for start, end in periods: + insert_period(freebusy, (start, end, uid)) + + if transp in (None, "OPAQUE"): + store.set_freebusy(attendee, freebusy) + + return freebusy + + return None + # Handler mechanism objects. def handle_itip_part(part, recipients, handlers): @@ -325,6 +360,9 @@ def get_periods(self): return get_periods(self.details) + def update_freebusy(self, attendee, periods): + return update_freebusy(attendee, periods, self.get_value("TRANSP"), self.uid, self.store) + def filter_by_recipients(self, values): return self.recipients.intersection(map(get_address, values)) diff -r 32997a697007 -r 77f2ad0d6f88 imiptools/handlers/resource.py --- a/imiptools/handlers/resource.py Sun Oct 26 23:10:12 2014 +0100 +++ b/imiptools/handlers/resource.py Sun Oct 26 23:39:11 2014 +0100 @@ -5,7 +5,6 @@ """ from imiptools.content import Handler, format_datetime, to_part -from imiptools.period import have_conflict, insert_period, remove_period from vCalendar import to_node class Event(Handler): @@ -75,44 +74,23 @@ # free/busy record and check for suitability. periods = self.get_periods() - - conflict = False - freebusy = self.store.get_freebusy(attendee) or [] + freebusy = self.update_freebusy(attendee, periods) + scheduled = freebusy is not None - if freebusy: - remove_period(freebusy, self.uid) - conflict = have_conflict(freebusy, periods) + attendee_attr["PARTSTAT"] = scheduled and "ACCEPTED" or "DECLINED" - # If the event can be scheduled, it is registered and a reply sent - # accepting the event. (The attendee has PARTSTAT=ACCEPTED as an - # attribute.) + self.details["ATTENDEE"] = [(attendee, attendee_attr)] - if not conflict: - for start, end in periods: - insert_period(freebusy, (start, end, self.uid)) + calendar.append(to_node( + {"VEVENT" : [(self.details, {})]} + )) - if self.get_value("TRANSP") in (None, "OPAQUE"): - self.store.set_freebusy(attendee, freebusy) - - if self.publisher: - self.publisher.set_freebusy(attendee, freebusy) - + if scheduled: self.store.set_event(attendee, self.uid, to_node( {"VEVENT" : [(self.details, {})]} )) - attendee_attr["PARTSTAT"] = "ACCEPTED" - - # If the event cannot be scheduled, it is not registered and a reply - # sent declining the event. (The attendee has PARTSTAT=DECLINED as an - # attribute.) - - else: - attendee_attr["PARTSTAT"] = "DECLINED" - - self.details["ATTENDEE"] = [(attendee, attendee_attr)] - calendar.append(to_node( - {"VEVENT" : [(self.details, {})]} - )) + if self.publisher: + self.publisher.set_freebusy(attendee, freebusy) return "REPLY", to_part("REPLY", calendar)