annotate gpp/gcalendar/calendar.py @ 133:c515b7401078

Use the new common way to apply markItUp to textareas and to get the smiley and markdown help dialogs for all the remaining apps except for forums and comments.
author Brian Neal <bgneal@gmail.com>
date Fri, 27 Nov 2009 00:21:47 +0000
parents 9c18250972d5
children d77e0dc772ad
rev   line source
gremmie@1 1 """
gremmie@1 2 This file contains the calendar class wich abstracts the Google gdata API for working with
gremmie@1 3 Google Calendars.
gremmie@1 4 """
gremmie@1 5 import datetime
gremmie@1 6 import pytz
gremmie@1 7
gremmie@1 8 from django.utils.tzinfo import FixedOffset
gremmie@1 9 from gdata.calendar.service import CalendarService
gremmie@1 10 from gdata.calendar import CalendarEventFeed
gremmie@1 11 from gdata.calendar import CalendarEventEntry
gremmie@1 12 from gdata.calendar import Who
gremmie@1 13 from gdata.calendar import Where
gremmie@1 14 from gdata.calendar import When
gremmie@1 15 from gdata.service import BadAuthentication
gremmie@1 16 import atom
gremmie@1 17
gremmie@1 18 from gcalendar.models import Event
gremmie@1 19
gremmie@1 20
gremmie@1 21 class CalendarError(Exception):
bgneal@68 22 def __init__(self, msg):
bgneal@68 23 self.msg = msg
gremmie@1 24
gremmie@1 25 def __str__(self):
bgneal@68 26 return repr(self.msg)
gremmie@1 27
gremmie@1 28
gremmie@1 29 class Calendar(object):
gremmie@1 30 DATE_FMT = '%Y-%m-%d'
gremmie@1 31 DATE_TIME_FMT = DATE_FMT + 'T%H:%M:%S'
gremmie@1 32 DATE_TIME_TZ_FMT = DATE_TIME_FMT + '.000Z'
gremmie@1 33
gremmie@1 34 def __init__(self, email, password, calendar_id='default'):
gremmie@1 35 self.client = CalendarService()
gremmie@1 36 self.client.email = email
gremmie@1 37 self.client.password = password
gremmie@1 38 self.client.source = 'Google-Calendar_Python_GCalendar'
gremmie@1 39 self.insert_feed = '/calendar/feeds/%s/private/full' % calendar_id
gremmie@1 40 self.batch_feed = '%s/batch' % self.insert_feed
gremmie@1 41 try:
gremmie@1 42 self.client.ProgrammaticLogin()
gremmie@1 43 except BadAuthentication:
bgneal@68 44 raise CalendarError('Incorrect password')
gremmie@1 45 except Exception, e:
bgneal@68 46 raise CalendarError(str(e))
gremmie@1 47
gremmie@1 48 def sync_events(self, qs):
gremmie@1 49 request_feed = CalendarEventFeed()
gremmie@1 50 for model in qs:
gremmie@1 51 if model.status == Event.NEW_APRV:
gremmie@1 52 event = CalendarEventEntry()
gremmie@1 53 request_feed.AddInsert(entry=self._populate_event(model, event))
gremmie@1 54 elif model.status == Event.EDIT_APRV:
gremmie@1 55 event = self._retrieve_event(model)
gremmie@1 56 request_feed.AddUpdate(entry=self._populate_event(model, event))
gremmie@1 57 elif model.status == Event.DEL_APRV:
gremmie@1 58 event = self._retrieve_event(model)
gremmie@1 59 request_feed.AddDelete(entry=event)
gremmie@1 60 else:
gremmie@1 61 assert False, 'unexpected status in sync_events'
gremmie@1 62
bgneal@68 63 try:
bgneal@68 64 response_feed = self.client.ExecuteBatch(request_feed, self.batch_feed)
bgneal@68 65 except Exception, e:
bgneal@68 66 raise CalendarError('ExecuteBatch exception: %s' % e)
bgneal@68 67
gremmie@1 68 err_msgs = []
gremmie@1 69 for entry in response_feed.entry:
gremmie@1 70 i = int(entry.batch_id.text)
gremmie@1 71 code = int(entry.batch_status.code)
gremmie@1 72
gremmie@1 73 error = False
gremmie@1 74 if qs[i].status == Event.NEW_APRV or qs[i].status == Event.EDIT_APRV:
gremmie@1 75 if (code == 201 and qs[i].status == Event.NEW_APRV) or \
gremmie@1 76 (code == 200 and qs[i].status == Event.EDIT_APRV):
gremmie@1 77 qs[i].google_id = entry.id.text
gremmie@1 78 qs[i].status = Event.ON_CAL
gremmie@1 79 qs[i].save()
gremmie@1 80 else:
gremmie@1 81 error = True
gremmie@1 82 elif qs[i].status == Event.DEL_APRV:
gremmie@1 83 if code == 200:
gremmie@1 84 qs[i].delete()
gremmie@1 85 else:
gremmie@1 86 error = True
gremmie@1 87
gremmie@1 88 if error:
bgneal@124 89 err_msgs.append('%s - (%d) %s' % (
bgneal@124 90 qs[i].what, code, entry.batch_status.reason))
gremmie@1 91
gremmie@1 92 if len(err_msgs) > 0:
bgneal@68 93 raise CalendarError(', '.join(err_msgs))
gremmie@1 94
gremmie@1 95 def _retrieve_event(self, model):
gremmie@1 96 try:
gremmie@1 97 event = self.client.GetCalendarEventEntry(model.google_id)
bgneal@68 98 except Exception, e:
bgneal@68 99 raise CalendarError('Could not retrieve event from Google: %s, %s' \
bgneal@68 100 % (model.what, e))
gremmie@1 101 return event
gremmie@1 102
gremmie@1 103 def _populate_event(self, model, event):
gremmie@1 104 """Populates a gdata event from an Event model object."""
gremmie@1 105 event.title = atom.Title(text=model.what)
gremmie@1 106 event.content = atom.Content(text=model.html)
gremmie@1 107 event.where = [Where(value_string=model.where)]
gremmie@1 108 event.who = [Who(name=model.user.username, email=model.user.email)]
gremmie@1 109
gremmie@1 110 if model.all_day:
gremmie@1 111 start_time = self._make_time(model.start_date)
gremmie@1 112 if model.start_date == model.end_date:
gremmie@1 113 end_time = None
gremmie@1 114 else:
gremmie@1 115 end_time = self._make_time(model.end_date)
gremmie@1 116 else:
gremmie@1 117 start_time = self._make_time(model.start_date, model.start_time, model.time_zone)
gremmie@1 118 end_time = self._make_time(model.end_date, model.end_time, model.time_zone)
gremmie@1 119
gremmie@1 120 event.when = [When(start_time=start_time, end_time=end_time)]
gremmie@1 121 return event
gremmie@1 122
gremmie@1 123 def _make_time(self, date, time=None, tz_name=None):
gremmie@1 124 """
gremmie@1 125 Returns the gdata formatted date/time string given a date, optional time,
gremmie@1 126 and optional time zone name (e.g. 'US/Pacific'). If the time zone name is None,
gremmie@1 127 no time zone info will be added to the string.
gremmie@1 128 """
gremmie@1 129
gremmie@1 130 if time is not None:
gremmie@1 131 d = datetime.datetime.combine(date, time)
gremmie@1 132 else:
gremmie@1 133 d = datetime.datetime(date.year, date.month, date.day)
gremmie@1 134
gremmie@1 135 if time is None:
gremmie@1 136 s = d.strftime(self.DATE_FMT)
gremmie@1 137 elif tz_name is None:
gremmie@1 138 s = d.strftime(self.DATE_TIME_FMT)
gremmie@1 139 else:
gremmie@1 140 try:
gremmie@1 141 tz = pytz.timezone(tz_name)
gremmie@1 142 except pytz.UnknownTimeZoneError:
bgneal@68 143 raise CalendarError('Invalid time zone: %s' (tz_name,))
gremmie@1 144 local = tz.localize(d)
gremmie@1 145 zulu = local.astimezone(FixedOffset(0))
gremmie@1 146 s = zulu.strftime(self.DATE_TIME_TZ_FMT)
gremmie@1 147
gremmie@1 148 return s
gremmie@1 149