1.1 --- a/imipweb/event.py Mon Apr 06 16:10:01 2015 +0200
1.2 +++ b/imipweb/event.py Mon Apr 06 16:39:52 2015 +0200
1.3 @@ -24,28 +24,15 @@
1.4 from imiptools.data import get_uri, uri_dict, uri_values
1.5 from imiptools.dates import format_datetime, to_date, get_datetime, \
1.6 get_datetime_item, get_period_item, \
1.7 - get_start_of_day, to_timezone
1.8 + to_timezone
1.9 from imiptools.mail import Messenger
1.10 -from imiptools.period import have_conflict, Period
1.11 +from imiptools.period import have_conflict
1.12 +from imipweb.data import EventPeriod, handle_date_control_values, \
1.13 + handle_period_controls
1.14 from imipweb.handler import ManagerHandler
1.15 from imipweb.resource import Resource
1.16 import pytz
1.17
1.18 -class EventPeriod(Period):
1.19 -
1.20 - "A simple period plus attribute details, compatible with RecurringPeriod."
1.21 -
1.22 - def __init__(self, start, end, start_attr=None, end_attr=None):
1.23 - Period.__init__(self, start, end)
1.24 - self.start_attr = start_attr
1.25 - self.end_attr = end_attr
1.26 -
1.27 - def as_tuple(self):
1.28 - return self.start, self.end, self.start_attr, self.end_attr
1.29 -
1.30 - def __repr__(self):
1.31 - return "EventPeriod(%r, %r, %r, %r)" % self.as_tuple()
1.32 -
1.33 class EventPage(Resource):
1.34
1.35 "A request handler for the event page."
1.36 @@ -204,7 +191,7 @@
1.37 start_values = self.get_date_control_values("dtstart")
1.38 end_values = self.get_date_control_values("dtend")
1.39
1.40 - period, errors = self.handle_period_controls(start_values, end_values, dtend_enabled, dttimes_enabled)
1.41 + period, errors = handle_period_controls(start_values, end_values, dtend_enabled, dttimes_enabled)
1.42
1.43 if errors:
1.44 return None, errors
1.45 @@ -230,84 +217,13 @@
1.46
1.47 dtend_enabled = str(index) in all_dtend_enabled
1.48 dttimes_enabled = str(index) in all_dttimes_enabled
1.49 - period, _errors = self.handle_period_controls(start_values, end_values, dtend_enabled, dttimes_enabled, index)
1.50 + period, _errors = handle_period_controls(start_values, end_values, dtend_enabled, dttimes_enabled, index)
1.51
1.52 periods.append(period)
1.53 errors += _errors
1.54
1.55 return periods, errors
1.56
1.57 - def handle_period_controls(self, start_values, end_values, dtend_enabled, dttimes_enabled, index=None):
1.58 -
1.59 - """
1.60 - Handle datetime controls for a particular period, described by the given
1.61 - 'start_values' and 'end_values', with 'dtend_enabled' and
1.62 - 'dttimes_enabled' affecting the usage of the provided values.
1.63 -
1.64 - If 'index' is specified, incorporate it into any error indicator.
1.65 - """
1.66 -
1.67 - t = self.handle_date_control_values(start_values, dttimes_enabled)
1.68 - if t:
1.69 - dtstart, dtstart_attr = t
1.70 - else:
1.71 - return None, [index is not None and ("dtstart", index) or "dtstart"]
1.72 -
1.73 - # Handle specified end datetimes.
1.74 -
1.75 - if dtend_enabled:
1.76 - t = self.handle_date_control_values(end_values, dttimes_enabled)
1.77 - if t:
1.78 - dtend, dtend_attr = t
1.79 -
1.80 - # Convert end dates to iCalendar "next day" dates.
1.81 -
1.82 - if not isinstance(dtend, datetime):
1.83 - dtend += timedelta(1)
1.84 - else:
1.85 - return None, [index is not None and ("dtend", index) or "dtend"]
1.86 -
1.87 - # Otherwise, treat the end date as the start date. Datetimes are
1.88 - # handled by making the event occupy the rest of the day.
1.89 -
1.90 - else:
1.91 - dtend = dtstart + timedelta(1)
1.92 - dtend_attr = dtstart_attr
1.93 -
1.94 - if isinstance(dtstart, datetime):
1.95 - dtend = get_start_of_day(dtend, attr["TZID"])
1.96 -
1.97 - if dtstart > dtend:
1.98 - return None, [
1.99 - index is not None and ("dtstart", index) or "dtstart",
1.100 - index is not None and ("dtend", index) or "dtend"
1.101 - ]
1.102 -
1.103 - return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr), None
1.104 -
1.105 - def handle_date_control_values(self, values, with_time=True):
1.106 -
1.107 - """
1.108 - Handle date control information for the given 'values', returning a
1.109 - (datetime, attr) tuple, or None if the fields cannot be used to
1.110 - construct a datetime object.
1.111 - """
1.112 -
1.113 - if not values or not values["date"]:
1.114 - return None
1.115 - elif with_time:
1.116 - value = "%s%s" % (values["date"], values["time"])
1.117 - attr = {"TZID" : values["tzid"], "VALUE" : "DATE-TIME"}
1.118 - dt = get_datetime(value, attr)
1.119 - else:
1.120 - attr = {"VALUE" : "DATE"}
1.121 - dt = get_datetime(values["date"])
1.122 -
1.123 - if dt:
1.124 - return dt, attr
1.125 -
1.126 - return None
1.127 -
1.128 def get_date_control_values(self, name, multiple=False, tzid_name=None):
1.129
1.130 """
1.131 @@ -338,17 +254,18 @@
1.132
1.133 # Construct a usable dictionary of values.
1.134
1.135 - time = (hour or minute or second) and \
1.136 - "T%s%s%s" % (
1.137 - (hour or "").rjust(2, "0")[:2],
1.138 - (minute or "").rjust(2, "0")[:2],
1.139 - (second or "").rjust(2, "0")[:2]
1.140 - ) or ""
1.141 + if hour or minute or second:
1.142 + hour = (hour or "").rjust(2, "0")[:2]
1.143 + minute = (minute or "").rjust(2, "0")[:2]
1.144 + second = (second or "").rjust(2, "0")[:2]
1.145 + time = "T%s%s%s" % (hour, minute, second)
1.146 + else:
1.147 + hour = minute = second = time = ""
1.148
1.149 value = {
1.150 - "date" : date,
1.151 - "time" : time,
1.152 - "tzid" : tzid or self.get_tzid()
1.153 + "date" : date, "time" : time,
1.154 + "tzid" : tzid or self.get_tzid(),
1.155 + "hour" : hour, "minute" : minute, "second" : second
1.156 }
1.157
1.158 # Return a single value or append to a collection of all values.