diff options
author | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2012-05-21 14:39:05 +0100 |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2012-05-21 14:39:05 +0100 |
commit | 5b46eef3ef59edba8b936d8f4ced49917a18020d (patch) | |
tree | 661d3d213fa0c7e6ef6ad2b7dec0de0de97ffb57 | |
parent | 90379b582f5ae828af3ee915c7bcf89bb3af6545 (diff) | |
download | pykolab-5b46eef3ef59edba8b936d8f4ced49917a18020d.tar.gz |
Rough implementation of kolabformat wrapper
-rw-r--r-- | pykolab/xml/__init__.py | 16 | ||||
-rw-r--r-- | pykolab/xml/attendee.py | 60 | ||||
-rw-r--r-- | pykolab/xml/contact.py | 43 | ||||
-rw-r--r-- | pykolab/xml/contact_reference.py | 24 | ||||
-rw-r--r-- | pykolab/xml/event.py | 470 |
5 files changed, 613 insertions, 0 deletions
diff --git a/pykolab/xml/__init__.py b/pykolab/xml/__init__.py new file mode 100644 index 0000000..f73f5e9 --- /dev/null +++ b/pykolab/xml/__init__.py @@ -0,0 +1,16 @@ +from attendee import Attendee +from contact import Contact +from contact_reference import ContactReference + +from event import Event +from event import event_from_ical +from event import event_from_string + +__all__ = [ + "Attendee", + "Contact", + "ContactReference", + "Event", + "event_from_ical", + "event_from_string", + ] diff --git a/pykolab/xml/attendee.py b/pykolab/xml/attendee.py new file mode 100644 index 0000000..692524d --- /dev/null +++ b/pykolab/xml/attendee.py @@ -0,0 +1,60 @@ +import kolabformat + +from contact_reference import ContactReference + +class Attendee(kolabformat.Attendee): + partstat_map = { + "NEEDS-ACTION": kolabformat.PartNeedsAction, + "ACCEPTED": kolabformat.PartAccepted, + "DECLINED": kolabformat.PartDeclined, + "TENTATIVE": kolabformat.PartTentative, + "DELEGATED": kolabformat.PartDelegated, + # Not yet implemented + #"COMPLETED": , + #"IN-PROCESS": , + } + + role_map = { + "REQ-PARTICIPANT": kolabformat.Required, + "CHAIR": kolabformat.Chair, + "OPTIONAL": kolabformat.Optional, + "NONPARTICIPANT": kolabformat.NonParticipant, + } + + rsvp_map = { + "TRUE": True, + "FALSE": False, + } + + def __init__(self, email, name=None, rsvp=False, role=None, participant_status=None): + self.email = email + + contactreference = ContactReference(email) + + if not name == None: + contactreference.set_name(name) + + kolabformat.Attendee.__init__(self, contactreference) + + if isinstance(rsvp, bool): + self.setRSVP(rsvp) + else: + if self.rsvp_map.has_key(rsvp): + self.setRSVP(self.rsvp_map[rsvp]) + + if not role == None: + self.set_role(role) + + if not participant_status == None: + self.set_participant_status(participant_status) + + def set_participant_status(self, participant_status): + if self.participant_status_map.has_key(participant_status): + self.setPartStat(self.participant_status_map[participant_status]) + + def set_role(self, role): + if self.role_map.has_key(role): + self.setRole(self.role_map[role]) + + def __str__(self): + return self.email diff --git a/pykolab/xml/contact.py b/pykolab/xml/contact.py new file mode 100644 index 0000000..1577b58 --- /dev/null +++ b/pykolab/xml/contact.py @@ -0,0 +1,43 @@ +import kolabformat + +class Contact(kolabformat.Contact): + def __init__(self, *args, **kw): + kolabformat.Contact.__init__(self, *args, **kw) + + def get_uid(self): + uid = self.uid() + if not uid == '': + return uid + else: + self.__str__() + return kolabformat.getSerializedUID() + + def get_email(self, preferred=True): + if preferred: + return self.emailAddresses()[self.emailAddressPreferredIndex()] + else: + return [x for x in self.emailAddresses()] + + def set_email(self, email, preferred_index=0): + if isinstance(email, basestring): + self.setEmailAddresses([email], preferred_index) + else: + self.setEmailAddresses(email, preferred_index) + + def add_email(self, email): + if isinstance(email, basestring): + self.add_emails([email]) + elif isinstance(email, list): + self.add_emails(email) + + def add_emails(self, emails): + preferred_email = self.get_email() + emails = [x for x in set(self.get_email(preferred=False) + emails)] + preferred_email_index = emails.index(preferred_email) + self.setEmailAddresses(emails, preferred_email_index) + + def set_name(self, name): + self.setName(name) + + def __str__(self): + return kolabformat.writeContact(self) diff --git a/pykolab/xml/contact_reference.py b/pykolab/xml/contact_reference.py new file mode 100644 index 0000000..ff41480 --- /dev/null +++ b/pykolab/xml/contact_reference.py @@ -0,0 +1,24 @@ +import kolabformat + +""" + def __eq__(self, *args): return _kolabformat.ContactReference___eq__(self, *args) + def isValid(self): return _kolabformat.ContactReference_isValid(self) + def setName(self, *args): return _kolabformat.ContactReference_setName(self, *args) + def email(self): return _kolabformat.ContactReference_email(self) + def uid(self): return _kolabformat.ContactReference_uid(self) + def name(self): return _kolabformat.ContactReference_name(self) + def type(self): return _kolabformat.ContactReference_type(self) +""" + +class ContactReference(kolabformat.ContactReference): + def __init__(self, email=None): + if email == None: + kolabformat.ContactReference.__init__(self) + else: + kolabformat.ContactReference.__init__(self, email) + + def set_email(self, email): + self.email = email + + def set_name(self, name): + self.setName(name) diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py new file mode 100644 index 0000000..a23b785 --- /dev/null +++ b/pykolab/xml/event.py @@ -0,0 +1,470 @@ +import datetime +import icalendar +import kolabformat +import time + +from pykolab import constants + +from attendee import Attendee +from contact_reference import ContactReference + +def event_from_ical(string): + return Event(from_ical=string) + +def event_from_string(string): + return Event(from_string=string) + +class Event(object): + StatusTentative = kolabformat.StatusTentative + def __init__(self, from_ical="", from_string=""): + self._attendees = [] + + if from_ical == "": + if from_string == "": + self.event = kolabformat.Event() + else: + self.event = kolabformat.readEvent(from_string, False) + else: + self.from_ical(from_ical) + + def add_attendee(self, email, name=None, rsvp=False, role=None): + attendee = Attendee(email, name, rsvp, role) + self._attendees.append(attendee) + self.event.setAttendees(self._attendees) + + def as_string_itip(self): + cal = icalendar.Calendar() + cal.add( + 'prodid', + '-//pykolab-%s-%s//kolab.org//' % ( + constants.__version__, + constants.__release__ + ) + ) + + cal.add('version', '2.0') + # TODO: Really? + cal.add('calscale', 'GREGORIAN') + # TODO: Not always a request... + cal.add('method', 'REQUEST') + + # TODO: Add timezone information using icalendar.?() + # Not sure if there is a class for it. + + event = icalendar.Event() + + # Required + event['uid'] = self.get_uid() + + # NOTE: Make sure to list(set()) or duplicates may arise + for attr in list(set(event.singletons)): + if hasattr(self, 'get_ical_%s' % (attr.lower())): + exec("retval = self.get_ical_%s()" % (attr.lower())) + if not retval == None and not retval == "": + event.add(attr.lower(), retval) + + elif hasattr(self, 'get_%s' % (attr.lower())): + exec("retval = self.get_%s()" % (attr.lower())) + if not retval == None and not retval == "": + event.add(attr.lower(), retval) + + #else: + #print "no function for", attr.lower() + + # NOTE: Make sure to list(set()) or duplicates may arise + for attr in list(set(event.multiple)): + if hasattr(self, 'get_ical_%s' % (attr.lower())): + exec("retval = self.get_ical_%s()" % (attr.lower())) + if isinstance(retval, list) and not len(retval) == 0: + for _retval in retval: + event.add(attr.lower(), _retval) + + elif hasattr(self, 'get_%s' % (attr.lower())): + exec("retval = self.get_%s()" % (attr.lower())) + if isinstance(retval, list) and not len(retval) == 0: + for _retval in retval: + event.add(attr.lower(), _retval) + + #else: + #print "no function for", attr.lower() + + #event.add('attendee', self.get_attendees()) + + #BEGIN:VEVENT + #DESCRIPTION:Project XYZ Review Meeting + #CATEGORIES:MEETING + #CLASS:PUBLIC + #CREATED:19980309T130000Z + #SUMMARY:XYZ Project Review + #DTSTART;TZID=US-Eastern:19980312T083000 + #DTEND;TZID=US-Eastern:19980312T093000 + #LOCATION:1CP Conference Room 4350 + #END:VEVENT + + #event['description'] = + + cal.add_component(event) + + if hasattr(cal, 'to_ical'): + return cal.to_ical() + elif hasattr(cal, 'as_string'): + return cal.as_string() + + def from_ical(self, ical): + self.event = kolabformat.Event() + if hasattr(icalendar.Event, 'from_ical'): + ical_event = icalendar.Event.from_ical(ical) + elif hasattr(icalendar.Event, 'from_string'): + ical_event = icalendar.Event.from_string(ical) + + for attr in list(set(ical_event.required)): + if ical_event.has_key(attr): + if hasattr(self, 'set_ical_%s' % (attr.lower())): + exec("self.set_ical_%s(%r)" % (attr.lower(),ical_event.decoded(attr))) + else: + print attr, "exists but no function exists" + + # NOTE: Make sure to list(set()) or duplicates may arise + for attr in list(set(ical_event.singletons)): + if ical_event.has_key(attr): + if hasattr(self, 'set_ical_%s' % (attr.lower())): + exec("self.set_ical_%s(%r)" % (attr.lower(),ical_event.decoded(attr))) + else: + print attr, "exists but no function exists" + + # NOTE: Make sure to list(set()) or duplicates may arise + for attr in list(set(ical_event.multiple)): + if ical_event.has_key(attr): + if hasattr(self, 'set_ical_%s' % (attr.lower())): + exec("self.set_ical_%s(%r)" % (attr.lower(),ical_event.decoded(attr))) + else: + print attr, "exists but no function exists" + + def get_attendees(self): + return self.event.attendees() + + def get_created(self): + _datetime = self.event.created() + + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year(), + _datetime.month(), + _datetime.day(), + _datetime.hour(), + _datetime.minute(), + _datetime.second() + ) + + try: + result = datetime.datetime(year, month, day, hour, minute, second) + except ValueError: + result = datetime.datetime.now() + + def get_end(self): + _datetime = self.event.end() + + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year(), + _datetime.month(), + _datetime.day(), + _datetime.hour(), + _datetime.minute(), + _datetime.second() + ) + + return datetime.datetime(year, month, day, hour, minute, second) + + def get_ical_attendee(self): + # TODO: Formatting, aye? See also the example snippet: + # + # ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP: + # MAILTO:employee-A@host.com + + attendees = [] + for attendee in self.get_attendees(): + contact = attendee.contact() + rsvp = attendee.rsvp() + role = attendee.role() + + if rsvp: + _rsvp = "TRUE" + else: + _rsvp = "FALSE" + + #Required = _kolabformat.Required + #Chair = _kolabformat.Chair + #Optional = _kolabformat.Optional + #NonParticipant = _kolabformat.NonParticipant + + # TODO: Check the role strings for validity + if role == kolabformat.Required: + _role = "REQ-PARTICIPANT" + elif role == kolabformat.Chair: + _role = "CHAIR" + elif role == kolabformat.Optional: + _role = "OPTIONAL" + elif role == kolabformat.NonParticipant: + _role = "NON-PARTICIPANT" + + _attendee = "RSVP=%s" % _rsvp + _attendee += ";ROLE=%s" % _role + _attendee += ";MAILTO:%s" % contact.email() + + attendees.append(_attendee) + + return attendees + + def get_ical_created(self): + return self.get_created() + + def get_ical_dtend(self): + return self.get_end() + + def get_ical_dtstamp(self): + return + try: + retval = self.event.lastModified() + if retval == None or retval == "": + return datetime.datetime.now() + except: + return datetime.datetime.now() + + def get_ical_dtstart(self): + return self.get_start() + + def get_ical_organizer(self): + organizer = self.get_organizer() + name = organizer.name() + if not name: + return "mailto:%s" % (organizer.email()) + else: + return "CN=%s:mailto:%s" %(name, organizer.email()) + + def get_ical_status(self): + status = self.event.status() + + # TODO: See which ones are actually valid for iTip + if status == kolabformat.StatusUndefined: + _status = "UNDEFINED" + elif status == kolabformat.StatusNeedsAction: + _status = "NEEDS-ACTION" + elif status == kolabformat.StatusCompleted: + _status = "COMPLETED" + elif status == kolabformat.StatusInProcess: + _status = "INPROCESS" + elif status == kolabformat.StatusCancelled: + _status = "CANCELLED" + elif status == kolabformat.StatusTentative: + _status = "TENTATIVE" + elif status == kolabformat.StatusConfirmed: + _status = "CONFIRMED" + elif status == kolabformat.StatusDraft: + _status = "DRAFT" + elif status == kolabformat.StatusFinal: + _status = "FINAL" + else: + _status = "UNDEFINED" + + return _status + + def get_organizer(self): + return self.event.organizer() + + def get_priority(self): + return self.event.priority() + + def get_start(self): + _datetime = self.event.start() + + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year(), + _datetime.month(), + _datetime.day(), + _datetime.hour(), + _datetime.minute(), + _datetime.second() + ) + + return datetime.datetime(year, month, day, hour, minute, second) + + def get_summary(self): + return self.event.summary() + + def get_uid(self): + uid = self.event.uid() + if not uid == '': + return uid + else: + self.__str__() + return kolabformat.getSerializedUID() + + def set_created(self, _datetime=None): + if _datetime == None: + _datetime = datetime.datetime.now() + + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year, + _datetime.month, + _datetime.day, + _datetime.hour, + _datetime.minute, + _datetime.second + ) + + self.event.setCreated( + kolabformat.cDateTime(year, month, day, hour, minute, second) + ) + + def set_end(self, _datetime): + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year, + _datetime.month, + _datetime.day, + _datetime.hour, + _datetime.minute, + _datetime.second + ) + + self.event.setEnd( + kolabformat.cDateTime(year, month, day, hour, minute, second) + ) + + def set_ical_attendee(self, _attendee): + if isinstance(_attendee, list): + for attendee in _attendee: + rsvp = False + role = None + cn = None + address = None + for param in attendee.split(';'): + if (len(param.split('=')) > 1): + exec("%s = %r" % (param.split('=')[0].lower(), param.split('=')[1])) + if (len(param.split(':')) > 1): + address = param.split(':')[1] + self.add_attendee(address, name=cn, rsvp=rsvp, role=role) + + def set_ical_dtend(self, dtend): + self.set_end(dtend) + + def set_ical_dtstamp(self, dtstamp): + self.set_dtstamp(dtstamp) + + def set_ical_dtstart(self, dtstart): + self.set_start(dtstart) + + def set_ical_organizer(self, organizer): + self.set_organizer(organizer) + + def set_ical_priority(self, priority): + self.set_priority(priority) + + def set_ical_status(self, status): + # TODO: See which ones are actually valid for iTip + if status == "UNDEFINED": + _status = kolabformat.StatusUndefined + elif status == "NEEDS-ACTION": + _status = kolabformat.StatusNeedsAction + elif status == "COMPLETED": + _status = kolabformat.StatusCompleted + elif status == "INPROCESS": + _status = kolabformat.StatusInProcess + elif status == "CANCELLED": + _status = kolabformat.StatusCancelled + elif status == "TENTATIVE": + _status = kolabformat.StatusTentative + elif status == "CONFIRMED": + _status = kolabformat.StatusConfirmed + elif status == "DRAFT": + _status = kolabformat.StatusDraft + elif status == "FINAL": + _status = kolabformat.StatusFinal + else: + _status = kolabformat.StatusUndefined + + self.event.setStatus(_status) + + def set_ical_summary(self, summary): + self.set_summary(str(summary)) + + def set_ical_uid(self, uid): + self.set_uid(str(uid)) + + def set_organizer(self, email, name=None): + contactreference = ContactReference(email) + if not name == None: + contactreference.set_name(name) + + self.event.setOrganizer(contactreference) + + def set_priority(self, priority): + self.event.setPriority(priority) + + def set_start(self, _datetime): + ( + year, + month, + day, + hour, + minute, + second + ) = ( + _datetime.year, + _datetime.month, + _datetime.day, + _datetime.hour, + _datetime.minute, + _datetime.second + ) + + self.event.setStart(kolabformat.cDateTime(year, month, day, hour, minute, second)) + + def set_status(self, status): + self.event.setStatus(status) + + def set_summary(self, summary): + self.event.setSummary(summary) + + def set_uid(self, uid): + self.event.setUid(str(uid)) + + def __str__(self): + return kolabformat.writeEvent(self.event) + +class EventIntegrityError(Exception): + def __init__(self, message): + Exception.__init__(self, message) |