# HG changeset patch # User Paul Boddie # Date 1428359807 -7200 # Node ID 644d9bf74b9bee8098a1ec9d76dedeb7cc8ddec1 # Parent 54c8876a02c48503bb1dedfe4320ecf648263141 Consolidated conversion to/from calendar date conventions in the data module. Added origin information to period objects. diff -r 54c8876a02c4 -r 644d9bf74b9b imipweb/data.py --- a/imipweb/data.py Mon Apr 06 22:57:23 2015 +0200 +++ b/imipweb/data.py Tue Apr 07 00:36:47 2015 +0200 @@ -33,43 +33,48 @@ intended to represent information obtained from an iCalendar resource. """ - def __init__(self, start, end, start_attr=None, end_attr=None, form_start=None, form_end=None): + def __init__(self, start, end, start_attr=None, end_attr=None, form_start=None, form_end=None, origin=None): Period.__init__(self, start, end) self.start_attr = start_attr self.end_attr = end_attr self.form_start = form_start self.form_end = form_end + self.origin = origin def as_tuple(self): - return self.start, self.end, self.start_attr, self.end_attr, self.form_start, self.form_end + return self.start, self.end, self.start_attr, self.end_attr, self.form_start, self.form_end, self.origin def __repr__(self): - return "EventPeriod(%r, %r, %r, %r, %r, %r)" % self.as_tuple() + return "EventPeriod(%r, %r, %r, %r, %r, %r, %r)" % self.as_tuple() + + def as_event_period(self): + return self + + # Period data methods. def get_start(self): return self.start def get_end(self): - return self.end + return end_date_from_calendar(self.end) - def as_event_period(self): - return self + # Form data compatibility methods. def get_form_start(self): if not self.form_start: - self.form_start = self.get_form_date(self.start, self.start_attr) + self.form_start = self.get_form_date(self.get_start(), self.start_attr) return self.form_start def get_form_end(self): if not self.form_end: - self.form_end = self.get_form_date(self.end, self.end_attr) + self.form_end = self.get_form_date(self.get_end(), self.end_attr) return self.form_end def as_form_period(self): return FormPeriod( - self.get_form_date(self.start, self.start_attr), - self.get_form_date(self.end, self.end_attr), - isinstance(self.end, datetime) or self.start != self.end - timedelta(1), + self.get_form_start(), + self.get_form_end(), + isinstance(self.end, datetime) or self.get_start() != self.get_end(), isinstance(self.start, datetime) or isinstance(self.end, datetime) ) @@ -83,24 +88,22 @@ dt, attr ) -def event_period_from_recurrence_period(period): - return EventPeriod(period.start, period.end, period.start_attr, period.end_attr) - class FormPeriod: "A period whose information originates from a form." - def __init__(self, start, end, end_enabled=True, times_enabled=True): + def __init__(self, start, end, end_enabled=True, times_enabled=True, origin=None): self.start = start self.end = end self.end_enabled = end_enabled self.times_enabled = times_enabled + self.origin = origin def as_tuple(self): - return self.start, self.end, self.end_enabled, self.times_enabled + return self.start, self.end, self.end_enabled, self.times_enabled, self.origin def __repr__(self): - return "FormPeriod(%r, %r, %r, %r)" % self.as_tuple() + return "FormPeriod(%r, %r, %r, %r, %r)" % self.as_tuple() def _get_start(self): t = self.start.as_datetime_item(self.times_enabled) @@ -109,7 +112,7 @@ else: return None - def _get_end(self): + def _get_end(self, adjust=False): # Handle specified end datetimes. @@ -117,6 +120,7 @@ t = self.end.as_datetime_item(self.times_enabled) if t: dtend, dtend_attr = t + dtend = adjust and end_date_to_calendar(dtend) or dtend else: return None @@ -137,6 +141,29 @@ return dtend, dtend_attr + def as_event_period(self, index=None): + t = self._get_start() + if t: + dtstart, dtstart_attr = t + else: + raise PeriodError(*[index is not None and ("dtstart", index) or "dtstart"]) + + t = self._get_end(adjust=True) + if t: + dtend, dtend_attr = t + else: + raise PeriodError(*[index is not None and ("dtend", index) or "dtend"]) + + if dtstart > dtend: + raise PeriodError(*[ + index is not None and ("dtstart", index) or "dtstart", + index is not None and ("dtend", index) or "dtend" + ]) + + return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr, self.start, self.end) + + # Period data methods. + def get_start(self): t = self._get_start() if t: @@ -153,26 +180,7 @@ else: return None - def as_event_period(self, index=None): - t = self._get_start() - if t: - dtstart, dtstart_attr = t - else: - raise PeriodError(*[index is not None and ("dtstart", index) or "dtstart"]) - - t = self._get_end() - if t: - dtend, dtend_attr = t - else: - raise PeriodError(*[index is not None and ("dtend", index) or "dtend"]) - - if dtstart > dtend: - raise PeriodError(*[ - index is not None and ("dtstart", index) or "dtstart", - index is not None and ("dtend", index) or "dtend" - ]) - - return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr, self.start, self.end) + # Form data methods. def get_form_start(self): return self.start @@ -291,4 +299,20 @@ else: return dt +def event_period_from_period(period): + if isinstance(period, EventPeriod): + return period + elif isinstance(period, FormPeriod): + return period.as_event_period() + else: + return EventPeriod(period.start, period.end, period.start_attr, period.end_attr, origin=period.origin) + +def form_period_from_period(period): + if isinstance(period, EventPeriod): + return period.as_form_period() + elif isinstance(period, FormPeriod): + return period + else: + return event_period_from_period(period).as_form_period() + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 54c8876a02c4 -r 644d9bf74b9b imipweb/event.py --- a/imipweb/event.py Mon Apr 06 22:57:23 2015 +0200 +++ b/imipweb/event.py Tue Apr 07 00:36:47 2015 +0200 @@ -28,8 +28,7 @@ from imiptools.mail import Messenger from imiptools.period import have_conflict from imipweb.data import EventPeriod, \ - end_date_from_calendar, end_date_to_calendar, \ - event_period_from_recurrence_period, \ + event_period_from_period, form_period_from_period, \ FormDate, FormPeriod, PeriodError from imipweb.handler import ManagerHandler from imipweb.resource import Resource @@ -188,9 +187,9 @@ "Set in the given 'obj' the given 'period' as the main start and end." - p = period.as_event_period() + p = event_period_from_period(period) result = self.set_datetime_in_object(p.start, p.start_attr and p.start_attr.get("TZID"), "DTSTART", obj) - result = self.set_datetime_in_object(end_date_to_calendar(p.end), p.end_attr and p.end_attr.get("TZID"), "DTEND", obj) or result + result = self.set_datetime_in_object(p.end, p.end_attr and p.end_attr.get("TZID"), "DTEND", obj) or result return result def set_periods_in_object(self, obj, periods): @@ -206,9 +205,9 @@ del obj["RDATE"] for period in periods: - p = period.as_event_period() + p = event_period_from_period(period) tzid = p.start_attr and p.start_attr.get("TZID") or p.end_attr and p.end_attr.get("TZID") - new_rdates.append(get_period_item(p.start, end_date_to_calendar(p.end), tzid)) + new_rdates.append(get_period_item(p.start, p.end, tzid)) obj["RDATE"] = new_rdates @@ -305,7 +304,7 @@ else: dtend, dtend_attr = dtstart, dtstart_attr - return EventPeriod(dtstart, end_date_from_calendar(dtend), dtstart_attr, dtend_attr) + return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr) def get_main_period(self): @@ -332,8 +331,8 @@ def get_existing_recurrences(self, obj): recurrences = [] for period in obj.get_periods(self.get_tzid(), self.get_window_end()): - if period.origin == "RDATE": - recurrences.append(event_period_from_recurrence_period(period)) + if period.origin != "DTSTART": + recurrences.append(period) return recurrences def get_recurrences(self): @@ -708,22 +707,21 @@ page.a("This event modifies a recurring event.", href=self.link_to(uid)) page.p.close() - # Obtain the periods associated with the event in the user's time zone. + # Obtain the periods associated with the event. - periods = map(event_period_from_recurrence_period, obj.get_periods(self.get_tzid(), self.get_window_end())) recurrences = self.get_current_recurrences(obj) - if len(periods) <= 1: + if len(recurrences) < 1: return recurrenceids = self._get_recurrences(uid) + page.p("This event occurs on the following occasions within the next %d days:" % self.get_window_size()) + # Show each recurrence in a separate table if editable. if self.is_organiser(obj) and recurrences: - page.p("The following occurrences are editable:") - for index, p in enumerate(recurrences): # Isolate the controls from neighbouring tables. @@ -735,6 +733,7 @@ page.table(cellspacing=5, cellpadding=5, class_="recurrence") page.caption("Occurrence") page.tbody() + page.tr() error = errors and ("dtstart", index) in errors and " error" or "" page.th("Start", class_="objectheading start%s" % error) @@ -745,6 +744,7 @@ page.th("End", class_="objectheading end%s" % error) self.show_recurrence_controls(obj, index, p, recurrenceid, recurrenceids, False) page.tr.close() + page.tbody.close() page.table.close() @@ -752,26 +752,25 @@ # Otherwise, use a compact single table. - page.p("This event occurs on the following occasions within the next %d days:" % self.get_window_size()) + else: + page.table(cellspacing=5, cellpadding=5, class_="recurrence") + page.caption("Occurrences") + page.thead() + page.tr() + page.th("Start", class_="objectheading start") + page.th("End", class_="objectheading end") + page.tr.close() + page.thead.close() + page.tbody() - page.table(cellspacing=5, cellpadding=5, class_="recurrence") - page.caption("Occurrences") - page.thead() - page.tr() - page.th("Start", class_="objectheading start") - page.th("End", class_="objectheading end") - page.tr.close() - page.thead.close() - page.tbody() + for index, p in enumerate(recurrences): + page.tr() + self.show_recurrence_label(p, recurrenceid, recurrenceids, True) + self.show_recurrence_label(p, recurrenceid, recurrenceids, False) + page.tr.close() - for index, p in enumerate(periods): - page.tr() - self.show_recurrence_label(p, recurrenceid, recurrenceids, True) - self.show_recurrence_label(p, recurrenceid, recurrenceids, False) - page.tr.close() - - page.tbody.close() - page.table.close() + page.tbody.close() + page.table.close() def show_conflicting_events(self, uid, obj): @@ -865,7 +864,7 @@ individual controls for dynamic manipulation. """ - p = period.as_form_period() + p = form_period_from_period(period) page = self.page args = self.env.get_args() @@ -967,14 +966,11 @@ page = self.page sn = self._suffixed_name ssn = self._simple_suffixed_name - p = period + + p = event_period_from_period(period) start_utc = format_datetime(to_timezone(p.get_start(), "UTC")) replaced = recurrenceids and start_utc in recurrenceids and "replaced" or "" - css = " ".join([ - replaced, - recurrenceid and start_utc == recurrenceid and "affected" or "" - ]) # Show controls for editing as organiser. @@ -1006,10 +1002,10 @@ else: self.show_recurrence_label(p, recurrenceid, recurrenceids, show_start) - def show_recurrence_label(self, p, recurrenceid, recurrenceids, show_start): + def show_recurrence_label(self, period, recurrenceid, recurrenceids, show_start): """ - Show datetime details for the given period 'p', employing any + Show datetime details for the given 'period', employing any 'recurrenceid' and 'recurrenceids' for the object to configure the displayed information. @@ -1019,6 +1015,8 @@ page = self.page + p = event_period_from_period(period) + start_utc = format_datetime(to_timezone(p.get_start(), "UTC")) replaced = recurrenceids and start_utc in recurrenceids and "replaced" or "" css = " ".join([