# HG changeset patch # User Paul Boddie # Date 1431814476 -7200 # Node ID 7cd2088ea85d9bed0353fa720352bda1cab56d45 # Parent 7e1f796f5e0d174ca0fff9f8319077c963a9475f Attempted to consolidate identifier handling, particularly the construction and comparison of recurrence identifiers. Modified the period start and end retrieval methods, removing timezone conversion parameters. Fixed links to replacement events, again. Simplified invocations by removing superfluous uid parameters. diff -r 7e1f796f5e0d -r 7cd2088ea85d imiptools/data.py --- a/imiptools/data.py Sat May 16 20:03:34 2015 +0200 +++ b/imiptools/data.py Sun May 17 00:14:36 2015 +0200 @@ -43,6 +43,14 @@ def __init__(self, fragment): self.objtype, (self.details, self.attr) = fragment.items()[0] + def get_uid(self): + return self.get_value("UID") + + def get_recurrenceid(self): + return format_datetime(self.get_utc_datetime("RECURRENCE-ID")) + + # Structure access. + def copy(self): return Object(to_dict(self.to_node())) @@ -117,7 +125,7 @@ # Computed results. def has_recurrence(self, tzid, recurrence): - recurrences = [p.start for p in get_periods(self, tzid, recurrence, inclusive=True)] + recurrences = [p.get_start() for p in get_periods(self, tzid, recurrence, inclusive=True)] return recurrence in recurrences def get_periods(self, tzid, end): @@ -511,8 +519,8 @@ def __call__(self, first, second): return cmp( - (to_datetime(first.start, self.tzid), to_datetime(first.end, self.tzid)), - (to_datetime(second.start, self.tzid), to_datetime(second.end, self.tzid)) + (to_datetime(first.get_start(), self.tzid), to_datetime(first.get_end(), self.tzid)), + (to_datetime(second.get_start(), self.tzid), to_datetime(second.get_end(), self.tzid)) ) def get_periods_for_freebusy(obj, periods, tzid): @@ -522,21 +530,12 @@ using the indicated 'tzid' to convert dates to datetimes. """ - start, start_attr = obj.get_datetime_item("DTSTART") - if obj.has_key("DTEND"): - end, end_attr = obj.get_datetime_item("DTEND") - elif obj.has_key("DURATION"): - duration = obj.get_duration("DURATION") - end = start + duration - else: - end, end_attr = start, start_attr - - tzid = get_tzid(start_attr, end_attr) or tzid + tzid = obj.get_tzid() or tzid l = [] for p in periods: - start, end = get_freebusy_period(p.start, p.end, tzid) + start, end = get_freebusy_period(p.get_start(), p.get_end(), tzid) start, end = [to_timezone(x, "UTC") for x in start, end] # Create a new period for free/busy purposes with the converted diff -r 7e1f796f5e0d -r 7cd2088ea85d imiptools/handlers/__init__.py --- a/imiptools/handlers/__init__.py Sat May 16 20:03:34 2015 +0200 +++ b/imiptools/handlers/__init__.py Sun May 17 00:14:36 2015 +0200 @@ -81,8 +81,8 @@ def set_object(self, obj): self.obj = obj - self.uid = self.obj.get_value("UID") - self.recurrenceid = format_datetime(self.obj.get_utc_datetime("RECURRENCE-ID")) + self.uid = self.obj.get_uid() + self.recurrenceid = self.obj.get_recurrenceid() self.sequence = self.obj.get_value("SEQUENCE") self.dtstamp = self.obj.get_value("DTSTAMP") diff -r 7e1f796f5e0d -r 7cd2088ea85d imiptools/period.py --- a/imiptools/period.py Sat May 16 20:03:34 2015 +0200 +++ b/imiptools/period.py Sun May 17 00:14:36 2015 +0200 @@ -54,17 +54,11 @@ # Datetime metadata methods. - def get_start(self, tzid=None): - if tzid: - return to_timezone(self.start, tzid) - else: - return self.start + def get_start(self): + return self.start - def get_end(self, tzid=None): - if tzid: - return to_timezone(self.end, tzid) - else: - return self.end + def get_end(self): + return self.end def get_start_item(self): return self.start, get_datetime_attributes(self.start) diff -r 7e1f796f5e0d -r 7cd2088ea85d imipweb/data.py --- a/imipweb/data.py Sat May 16 20:03:34 2015 +0200 +++ b/imipweb/data.py Sun May 17 00:14:36 2015 +0200 @@ -62,11 +62,10 @@ # Period data methods. - def get_start(self): - return self.start + # get_start inherited def get_end(self): - return end_date_from_calendar(self.end) + return end_date_from_calendar(Period.get_end(self)) def get_tzid(self): return get_tzid(self.start_attr, self.end_attr) diff -r 7e1f796f5e0d -r 7cd2088ea85d imipweb/event.py --- a/imipweb/event.py Sat May 16 20:03:34 2015 +0200 +++ b/imipweb/event.py Sun May 17 00:14:36 2015 +0200 @@ -23,7 +23,7 @@ from imiptools.client import update_attendees, update_participation from imiptools.data import get_uri, uri_dict, uri_values from imiptools.dates import format_datetime, to_date, get_datetime, \ - get_datetime_item, get_period_item, \ + get_datetime_item, get_period_item, to_datetime, \ to_recurrence_start, to_timezone, to_utc_datetime from imiptools.mail import Messenger from imiptools.period import have_conflict @@ -64,33 +64,35 @@ def is_organiser(self, obj): return get_uri(obj.get_value("ORGANIZER")) == self.user - def get_recurrence_key(self, period): - return format_datetime(to_utc_datetime(period.get_start(), self.get_tzid())) - - def get_recurrence_keys(self, recurrenceids): - return [to_recurrence_start(s, self.get_tzid()) for s in recurrenceids] - - def is_replaced(self, period, recurrenceid, recurrenceids): - start_utc = self.get_recurrence_key(period) - return not recurrenceid and recurrenceids and start_utc in self.get_recurrence_keys(recurrenceids) and "replaced" or "" + def is_replaced(self, period, recurrenceids): + for s in recurrenceids: + dt = to_timezone(get_datetime(s), self.get_tzid()) + if to_datetime(period.get_start(), self.get_tzid()) == dt: + return s + return None def is_affected(self, period, recurrenceid): - start_utc = self.get_recurrence_key(period) - return recurrenceid and start_utc == to_recurrence_start(recurrenceid, self.get_tzid()) and "affected" or "" + if not recurrenceid: + return None + dt = to_timezone(get_datetime(recurrenceid), self.get_tzid()) + if to_datetime(period.get_start(), self.get_tzid()) == dt: + return recurrenceid + return None # Request logic methods. - def handle_request(self, uid, recurrenceid, obj): + def handle_request(self, obj): """ - Handle actions involving the given 'uid', 'recurrenceid', and 'obj' as - the object's representation, returning an error if one occurred, or None - if the request was successfully handled. + Handle actions involving the given 'obj' as an object's representation, + returning an error if one occurred, or None if the request was + successfully handled. """ # Handle a submitted form. args = self.env.get_args() + uid = obj.get_uid() # Get the possible actions. @@ -477,7 +479,7 @@ attendees = self.get_current_attendees(obj) is_attendee = self.user in attendees - is_request = (obj.get_value("UID"), obj.get_value("RECURRENCE-ID")) in self._get_requests() + is_request = (obj.get_uid(), obj.get_recurrenceid()) in self._get_requests() sequence = obj.get_value("SEQUENCE") # Show appropriate options depending on the role of the user. @@ -509,12 +511,12 @@ self._control("save", "submit", "Save without sending") page.p.close() - def show_object_on_page(self, uid, obj, errors=None): + def show_object_on_page(self, obj, errors=None): """ - Show the calendar object with the given 'uid' and representation 'obj' - on the current page. If 'errors' is given, show a suitable message for - the different errors provided. + Show the calendar object with the representation 'obj' on the current + page. If 'errors' is given, show a suitable message for the different + errors provided. """ page = self.page @@ -522,6 +524,7 @@ self._control("editing", "hidden", "true") + uid = obj.get_uid() args = self.env.get_args() # Obtain basic event information, generating any necessary editing controls. @@ -538,9 +541,9 @@ # Obtain any separate recurrences for this event. - recurrenceid = format_datetime(obj.get_utc_datetime("RECURRENCE-ID")) + recurrenceid = obj.get_recurrenceid() recurrenceids = self._get_recurrences(uid) - replaced = self.is_replaced(p, recurrenceid, recurrenceids) + replaced = not recurrenceid and self.is_replaced(p, recurrenceids) # Provide a summary of the object. @@ -583,7 +586,7 @@ elif name == "DTSTART": page.td(class_="objectvalue %s replaced" % field, rowspan=2) - page.a("First occurrence replaced by a separate event", href=self.link_to(uid, self.get_recurrence_key(p))) + page.a("First occurrence replaced by a separate event", href=self.link_to(uid, replaced)) page.td.close() page.tr.close() @@ -650,7 +653,7 @@ page.table.close() self.show_recurrences(obj, errors) - self.show_conflicting_events(uid, obj) + self.show_conflicting_events(obj) self.show_request_controls(obj) page.form.close() @@ -721,8 +724,8 @@ # Obtain any parent object if this object is a specific recurrence. - uid = obj.get_value("UID") - recurrenceid = format_datetime(obj.get_utc_datetime("RECURRENCE-ID")) + uid = obj.get_uid() + recurrenceid = obj.get_recurrenceid() if recurrenceid: parent = self._get_object(uid) @@ -792,7 +795,7 @@ sequence = obj.get_value("SEQUENCE") p = event_period_from_period(period) - replaced = self.is_replaced(p, recurrenceid, recurrenceids) + replaced = not recurrenceid and self.is_replaced(p, recurrenceids) # Isolate the controls from neighbouring tables. @@ -838,15 +841,15 @@ page.div.close() - def show_conflicting_events(self, uid, obj): + def show_conflicting_events(self, obj): """ - Show conflicting events for the object having the given 'uid' and - representation 'obj'. + Show conflicting events for the object having the representation 'obj'. """ page = self.page - recurrenceid = format_datetime(obj.get_utc_datetime("RECURRENCE-ID")) + uid = obj.get_uid() + recurrenceid = obj.get_recurrenceid() recurrenceids = self._get_recurrences(uid) # Obtain the user's timezone. @@ -875,7 +878,7 @@ # Show any conflicts with periods of actual attendance. for p in have_conflict(freebusy, periods, True): - if self.is_replaced(p, recurrenceid, recurrenceids): + if not recurrenceid and self.is_replaced(p, recurrenceids): continue if (p.uid != uid or (recurrenceid and p.recurrenceid) and p.recurrenceid != recurrenceid) and p.transp != "ORG": conflicts.append(p) @@ -901,8 +904,8 @@ # Provide details of any conflicting event. - start = self.format_datetime(p.get_start(tzid), "long") - end = self.format_datetime(p.get_end(tzid), "long") + start = self.format_datetime(to_timezone(p.get_start(), tzid), "long") + end = self.format_datetime(to_timezone(p.get_end(), tzid), "long") page.tr() @@ -1036,7 +1039,7 @@ ssn = self._simple_suffixed_name p = event_period_from_period(period) - replaced = self.is_replaced(p, recurrenceid, recurrenceids) + replaced = not recurrenceid and self.is_replaced(p, recurrenceids) # Show controls for editing as organiser. @@ -1091,11 +1094,11 @@ page = self.page p = event_period_from_period(period) - replaced = self.is_replaced(p, recurrenceid, recurrenceids) + replaced = not recurrenceid and self.is_replaced(p, recurrenceids) css = " ".join([ - replaced, - self.is_affected(p, recurrenceid) + replaced and "replaced" or "", + self.is_affected(p, recurrenceid) and "affected" or "" ]) formdate = show_start and p.get_form_start() or p.get_form_end() @@ -1117,13 +1120,13 @@ if not obj: return False - errors = self.handle_request(uid, recurrenceid, obj) + errors = self.handle_request(obj) if not errors: return True self.new_page(title="Event") - self.show_object_on_page(uid, obj, errors) + self.show_object_on_page(obj, errors) return True