3 commits - pykolab/xml tests/functional tests/unit wallace/module_resources.py
Thomas Brüderli
bruederli at kolabsys.com
Wed Feb 26 19:12:21 CET 2014
pykolab/xml/event.py | 30 +++++-----
tests/functional/test_wallace/test_005_resource_invitation.py | 25 ++++----
tests/unit/test-003-event.py | 12 ++++
wallace/module_resources.py | 25 ++++++--
4 files changed, 59 insertions(+), 33 deletions(-)
New commits:
commit c1153b7c7214af35d7057f93592bb08d7de63f88
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 20 06:09:15 2014 -0500
Add the resource's common name when delegating; allow customized subject and text for iTip replies
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index 4f3ca0a..2dea819 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -153,25 +153,28 @@ class Event(object):
elif hasattr(cal, 'as_string'):
return cal.as_string()
- def delegate(self, delegators, delegatees):
+ def delegate(self, delegators, delegatees, names=None):
if not isinstance(delegators, list):
delegators = [delegators]
if not isinstance(delegatees, list):
delegatees = [delegatees]
+ if not isinstance(names, list):
+ names = [names]
+
_delegators = []
for delegator in delegators:
_delegators.append(self.get_attendee(delegator))
_delegatees = []
- for delegatee in delegatees:
+ for i,delegatee in enumerate(delegatees):
try:
_delegatees.append(self.get_attendee(delegatee))
except:
# TODO: An iTip needs to be sent out to the new attendee
- self.add_attendee(delegatee)
+ self.add_attendee(delegatee, names[i] if i < len(names) else None)
_delegatees.append(self.get_attendee(delegatee))
for delegator in _delegators:
@@ -916,7 +919,7 @@ class Event(object):
return msg
- def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED"):
+ def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED", subject=None, message_text=None):
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
@@ -979,19 +982,19 @@ class Event(object):
msg['Date'] = formatdate(localtime=True)
- # TODO: Should allow for localization
- text = utils.multiline_message("""
- This is a response to one of your event requests.
- """)
+ if subject is None:
+ subject = _("Reservation Request for %s was %s") % (self.get_summary(), participant_status)
- msg.attach( MIMEText(text) )
+ msg["Subject"] = subject
+
+ if message_text is None:
+ message_text = _("""This is an automated response to one of your event requests.""")
+
+ msg.attach(MIMEText(utils.multiline_message(message_text)))
part = MIMEBase('text', 'calendar', charset='UTF-8', method=method)
del part['MIME-Version'] # mime parts don't need this
- # TODO: Should allow for localization
- msg["Subject"] = "Meeting Request %s" % (participant_status)
-
part.set_payload(self.as_string_itip(method=method))
part.add_header('Content-Disposition', 'attachment; filename="event.ics"')
diff --git a/tests/functional/test_wallace/test_005_resource_invitation.py b/tests/functional/test_wallace/test_005_resource_invitation.py
index 780ca0f..8d6803d 100644
--- a/tests/functional/test_wallace/test_005_resource_invitation.py
+++ b/tests/functional/test_wallace/test_005_resource_invitation.py
@@ -52,7 +52,7 @@ DTEND;TZID=Europe/London:%s
SUMMARY:test
DESCRIPTION:test
ORGANIZER;CN="Doe, John":mailto:john.doe at example.org
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:%s
+ATTENDEE;ROLE=REQ-PARTICIPANT;CUTYPE=RESOURCE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:%s
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
@@ -94,7 +94,7 @@ SEQUENCE:2
SUMMARY:test
DESCRIPTION:test
ORGANIZER;CN="Doe, John":mailto:john.doe at example.org
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:%s
+ATTENDEE;ROLE=REQ-PARTICIPANT;CUTYPE=RESOURCE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:%s
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
@@ -305,7 +305,7 @@ class TestResourceInvitation(unittest.TestCase):
def test_002_invite_resource(self):
uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,7,13, 10,0,0))
- response = self.check_message_received("Meeting Request ACCEPTED", self.audi['mail'])
+ response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail'])
self.assertIsInstance(response, email.message.Message)
event = self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid)
@@ -316,7 +316,7 @@ class TestResourceInvitation(unittest.TestCase):
def test_003_invite_resource_conflict(self):
uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,7,13, 12,0,0))
- response = self.check_message_received("Meeting Request DECLINED", self.audi['mail'])
+ response = self.check_message_received("Reservation Request for test was DECLINED", self.audi['mail'])
self.assertIsInstance(response, email.message.Message)
self.assertEqual(self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid), None)
@@ -328,29 +328,30 @@ class TestResourceInvitation(unittest.TestCase):
uid = self.send_itip_invitation(self.cars['mail'], datetime.datetime(2014,7,13, 12,0,0))
# one of the collection members accepted the reservation
- accept = self.check_message_received("Meeting Request ACCEPTED")
+ accept = self.check_message_received("Reservation Request for test was ACCEPTED")
self.assertIsInstance(accept, email.message.Message)
- self.assertIn(accept['from'], [ self.passat['mail'], self.boxter['mail'] ])
+
+ delegatee = self.passat if accept['from'].find(self.passat['mail']) >= 0 else self.boxter
+ self.assertIn(delegatee['mail'], accept['from'])
# check booking in the delegatee's resource calendar
- delegatee = self.passat if accept['from'] == self.passat['mail'] else self.boxter
self.assertIsInstance(self.check_resource_calendar_event(delegatee['kolabtargetfolder'], uid), pykolab.xml.Event)
- # resource collection respons with a DELEGATED message
- response = self.check_message_received("Meeting Request DELEGATED", self.cars['mail'])
+ # resource collection responds with a DELEGATED message
+ response = self.check_message_received("Reservation Request for test was DELEGATED", self.cars['mail'])
self.assertIsInstance(response, email.message.Message)
def test_005_rescheduling_reservation(self):
uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,5,1, 10,0,0))
- response = self.check_message_received("Meeting Request ACCEPTED", self.audi['mail'])
+ response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail'])
self.assertIsInstance(response, email.message.Message)
self.purge_mailbox(self.john['mailbox'])
self.send_itip_update(self.audi['mail'], uid, datetime.datetime(2014,5,1, 12,0,0)) # conflict with myself
- response = self.check_message_received("Meeting Request ACCEPTED", self.audi['mail'])
+ response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail'])
self.assertIsInstance(response, email.message.Message)
event = self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid)
@@ -371,5 +372,5 @@ class TestResourceInvitation(unittest.TestCase):
# make new reservation to the now free'd slot
self.send_itip_invitation(self.boxter['mail'], datetime.datetime(2014,5,1, 9,0,0))
- response = self.check_message_received("Meeting Request ACCEPTED", self.boxter['mail'])
+ response = self.check_message_received("Reservation Request for test was ACCEPTED", self.boxter['mail'])
self.assertIsInstance(response, email.message.Message)
diff --git a/wallace/module_resources.py b/wallace/module_resources.py
index dfd419a..b718ac4 100644
--- a/wallace/module_resources.py
+++ b/wallace/module_resources.py
@@ -358,7 +358,7 @@ def execute(*args, **kw):
# - delegator: the original resource collection
# - delegatee: the target resource
#
- itip_event['xml'].delegate(original_resource['mail'], _target_resource['mail'])
+ itip_event['xml'].delegate(original_resource['mail'], _target_resource['mail'], _target_resource['cn'])
accept_reservation_request(itip_event, _target_resource, original_resource)
done = True
@@ -822,6 +822,7 @@ def send_response(from_address, itip_events):
for itip_event in itip_events:
attendee = itip_event['xml'].get_attendee_by_email(from_address)
participant_status = itip_event['xml'].get_ical_attendee_participant_status(attendee)
+ message_text = None
if participant_status == "DELEGATED":
# Extra actions to take
@@ -834,9 +835,14 @@ def send_response(from_address, itip_events):
# restore list of attendees after to_message_itip()
itip_event['xml']._attendees = [ delegator, delegatee ]
itip_event['xml'].event.setAttendees(itip_event['xml']._attendees)
+
participant_status = "DELEGATED"
+ message_text = _("""
+ Your reservation request was delegated to "%s"
+ which is available for the requested time.
+ """) % (delegatee.get_name())
- message = itip_event['xml'].to_message_itip(from_address, method="REPLY", participant_status=participant_status)
+ message = itip_event['xml'].to_message_itip(from_address, method="REPLY", participant_status=participant_status, message_text=message_text)
smtp.sendmail(message['From'], message['To'], message.as_string())
smtp.quit()
commit 4d460abbc06e0cc54f0a0b285708102829b618cc
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 20 05:59:00 2014 -0500
Make sure the iCal version of an event has a valid dtstamp property
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index 482b1bc..4f3ca0a 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -404,9 +404,8 @@ class Event(object):
return self.get_end()
def get_ical_dtstamp(self):
- return
try:
- retval = self.event.lastModified()
+ retval = self.get_lastmodified()
if retval == None or retval == "":
return datetime.datetime.now()
except:
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
index 59f131d..b90333a 100644
--- a/tests/unit/test-003-event.py
+++ b/tests/unit/test-003-event.py
@@ -135,5 +135,17 @@ END:VCALENDAR
self.assertEqual(event.get_attendee_by_email("max at imum.com").get_cutype(), kolabformat.CutypeResource)
self.assertEqual(event.get_sequence(), 2)
+ def test_019_as_string_itip(self):
+ self.event.set_summary("test")
+ self.event.set_start(datetime.datetime(2014, 05, 23, 11, 00, 00, tzinfo=pytz.timezone("Europe/London")))
+ self.event.set_end(datetime.datetime(2014, 05, 23, 12, 30, 00, tzinfo=pytz.timezone("Europe/London")))
+
+ ical = icalendar.Calendar.from_ical(self.event.as_string_itip())
+ event = ical.walk('VEVENT')[0]
+
+ self.assertEqual(event['uid'], self.event.get_uid())
+ self.assertEqual(event['summary'], "test")
+ self.assertIsInstance(event['dtstamp'].dt, datetime.datetime)
+
if __name__ == '__main__':
unittest.main()
commit cffe8974b83342773fd28b5ce14540e34a88cf64
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 20 03:37:09 2014 -0500
Minor fixes for passing unit tests
diff --git a/wallace/module_resources.py b/wallace/module_resources.py
index 84447c2..dfd419a 100644
--- a/wallace/module_resources.py
+++ b/wallace/module_resources.py
@@ -560,7 +560,7 @@ def itip_events_from_message(message):
# The iTip part MUST be Content-Type: text/calendar (RFC 6047, section 2.4)
# But in real word, other mime-types are used as well
if part.get_content_type() in [ "text/calendar", "text/x-vcalendar", "application/ics" ]:
- if not part.get_param('method').upper() in itip_methods:
+ if not str(part.get_param('method')).upper() in itip_methods:
log.error(
_("Method %r not really interesting for us.") % (
part.get_param('method')
@@ -664,9 +664,12 @@ def resource_record_from_email_address(email_address):
"""
Resolves the given email address to a resource entity
"""
+ global auth
+
+ if not auth:
+ auth = Auth()
+ auth.connect()
- auth = Auth()
- auth.connect()
resource_records = []
log.debug(
@@ -696,9 +699,11 @@ def resource_records_from_itip_events(itip_events, recipient_email=None):
Given a list of itip_events, determine which resources have been
invited as attendees and/or resources.
"""
+ global auth
- auth = Auth()
- auth.connect()
+ if not auth:
+ auth = Auth()
+ auth.connect()
resource_records = []
More information about the commits
mailing list