summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-05-21 14:39:05 +0100
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-05-21 14:39:05 +0100
commit5b46eef3ef59edba8b936d8f4ced49917a18020d (patch)
tree661d3d213fa0c7e6ef6ad2b7dec0de0de97ffb57
parent90379b582f5ae828af3ee915c7bcf89bb3af6545 (diff)
downloadpykolab-5b46eef3ef59edba8b936d8f4ced49917a18020d.tar.gz
Rough implementation of kolabformat wrapper
-rw-r--r--pykolab/xml/__init__.py16
-rw-r--r--pykolab/xml/attendee.py60
-rw-r--r--pykolab/xml/contact.py43
-rw-r--r--pykolab/xml/contact_reference.py24
-rw-r--r--pykolab/xml/event.py470
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)