diff options
-rw-r--r-- | pykolab/xml/event.py | 50 | ||||
-rw-r--r-- | tests/test-005-timezone.py | 50 | ||||
-rw-r--r-- | wallace/module_resources.py | 44 |
3 files changed, 128 insertions, 16 deletions
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py index d2973aa..b92339a 100644 --- a/pykolab/xml/event.py +++ b/pykolab/xml/event.py @@ -225,19 +225,36 @@ class Event(object): 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) + if not _datetime.hour() == None and not _datetime.hour() < 0: + ( + hour, + minute, + second + ) = ( + _datetime.hour(), + _datetime.minute(), + _datetime.second() + ) + + _timezone = _datetime.timezone() + + if _timezone == '': + _timezone = pytz.utc + elif _timezone == None: + _timezone = pytz.utc + else: + _timezone = pytz.timezone(_timezone) + + if _datetime.hour() == None or _datetime.hour() < 0: + return datetime.date(year, month, day) + else: + return datetime.datetime(year, month, day, hour, minute, second, tzinfo=_timezone) def get_ical_attendee(self): # TODO: Formatting, aye? See also the example snippet: @@ -253,6 +270,8 @@ class Event(object): role = attendee.get_role() partstat = attendee.get_participant_status() cutype = attendee.get_cutype() + delegators = attendee.get_delegated_from() + delegatees = attendee.get_delegated_to() if rsvp in attendee.rsvp_map.keys(): _rsvp = rsvp @@ -298,6 +317,12 @@ class Event(object): if not _cutype == None: _attendee.params['CUTYPE'] = icalendar.vText(_cutype) + if not delegators == None and len(delegators) > 0: + _attendee.params['DELEGATED-FROM'] = icalendar.vText(delegators[0].email()) + + if not delegatees == None and len(delegatees) > 0: + _attendee.params['DELEGATED-TO'] = icalendar.vText(delegatees[0].email()) + attendees.append(_attendee) return attendees @@ -816,6 +841,7 @@ class Event(object): attendees = self.get_attendees() + # TODO: There's an exception here for delegation (partstat DELEGATED) for attendee in attendees: if attendee.get_email() == from_address: # Only the attendee is supposed to be listed in a reply @@ -834,8 +860,8 @@ class Event(object): if msg_from == None: organizer = self.get_organizer() - email = organizer.get_email() - name = organizer.get_name() + email = organizer.email() + name = organizer.name() if email == from_address: if not name: msg_from = email @@ -851,9 +877,11 @@ class Event(object): else: msg_from = '"%s" <%s>' % (name, email) - if msg_from == None: - log.error(_("No sender specified")) + if from_address == None: + log.error(_("No sender specified")) + else: + msg_from = from_address msg['From'] = msg_from diff --git a/tests/test-005-timezone.py b/tests/test-005-timezone.py new file mode 100644 index 0000000..9b12c66 --- /dev/null +++ b/tests/test-005-timezone.py @@ -0,0 +1,50 @@ +import datetime +import icalendar +import pytz +import unittest + +from pykolab.xml import Attendee +from pykolab.xml import Event +from pykolab.xml import EventIntegrityError +from pykolab.xml import InvalidAttendeeParticipantStatusError +from pykolab.xml import InvalidEventDateError +from pykolab.xml import event_from_ical + +class TestTimezone(unittest.TestCase): + + def test_001_timezone_conflict(self): + london = Event() + london.set_organizer("john.doe@example.org", "Doe, John") + london.add_attendee("resource-car-vw@example.org", cutype="RESOURCE") + london.set_start(datetime.datetime.now(pytz.timezone("Europe/London"))) + london.set_end(datetime.datetime.now(pytz.timezone("Europe/London"))) + + zurich = Event() + zurich.set_organizer("john.doe@example.org", "Doe, John") + zurich.add_attendee("resource-car-vw@example.org", cutype="RESOURCE") + zurich.set_start(datetime.datetime.now(pytz.timezone("Europe/Zurich"))) + zurich.set_end(datetime.datetime.now(pytz.timezone("Europe/Zurich"))) + + london_xml = london.__str__() + zurich_xml = zurich.__str__() + + #print london_xml + #print zurich_xml + + london_itip = london.as_string_itip() + zurich_itip = zurich.as_string_itip() + + del london, zurich + + #print london_itip + #print zurich_itip + + london_cal = icalendar.Calendar.from_ical(london_itip) + london = event_from_ical(london_cal.walk('VEVENT')[0].to_ical()) + + zurich_cal = icalendar.Calendar.from_ical(zurich_itip) + zurich = event_from_ical(zurich_cal.walk('VEVENT')[0].to_ical()) + + self.assertEqual(london_xml, london.__str__()) + self.assertEqual(zurich_xml, zurich.__str__()) + diff --git a/wallace/module_resources.py b/wallace/module_resources.py index 525cc3b..a4873f4 100644 --- a/wallace/module_resources.py +++ b/wallace/module_resources.py @@ -274,7 +274,6 @@ def execute(*args, **kw): _ee = to_dt(event.get_end()) _ie = to_dt(itip['end'].dt) - if _es < _is: if _es <= _ie: if _ee <= _is: @@ -386,7 +385,7 @@ def execute(*args, **kw): itip_event['xml'].to_message().as_string() ) - send_response(resources[resource]['mail'], itip_events) + send_response(resources[resource]['mail'], itip_event) else: # This must have been a resource collection originally. @@ -395,15 +394,29 @@ def execute(*args, **kw): if resources[resource].has_key('memberof'): original_resource = resources[resources[resource]['memberof']] + # Randomly selects a target resource from the resource + # collection. _target_resource = resources[original_resource['uniquemember'][random.randint(0,(len(original_resource['uniquemember'])-1))]] - # unset all + # Remove all resources from the collection. for _r in original_resource['uniquemember']: del resources[_r] if original_resource['mail'] in [a.get_email() for a in itip_event['xml'].get_attendees()]: + # + # Delegate: + # + # - delegator: the original resource collection + # - delegatee: the target resource + # + + itip_event['xml'].delegate( + original_resource['mail'], + _target_resource['mail'] + ) + itip_event['xml'].set_attendee_participant_status( - [a for a in itip_event['xml'].get_attendees() if a.get_email() == original_resource['mail']][0], + [a for a in itip_event['xml'].get_attendees() if a.get_email() == _target_resource['mail']][0], "ACCEPTED" ) @@ -414,6 +427,8 @@ def execute(*args, **kw): level=9 ) + # TODO: The Cyrus IMAP (or Dovecot) Administrator login + # name comes from configuration. imap.imap.m.setacl(_target_resource['kolabtargetfolder'], "cyrus-admin", "lrswipkxtecda") imap.imap.m.append( _target_resource['kolabtargetfolder'], @@ -422,7 +437,7 @@ def execute(*args, **kw): itip_event['xml'].to_message().as_string() ) - send_response(original_resource['mail'], itip_events) + send_response(original_resource['mail'], itip_event) # Disconnect IMAP or we lock the mailbox almost constantly imap.disconnect() @@ -478,6 +493,8 @@ def itip_events_from_message(message): for c in cal.walk(): if c.name == "VEVENT": + itip = {} + # From the event, take the following properties: # # - start @@ -717,9 +734,26 @@ def send_response(from_address, itip_events): if conf.debuglevel > 8: smtp.set_debuglevel(True) + if isinstance(itip_events, dict): + itip_events = [ itip_events ] + for itip_event in itip_events: attendee = [a for a in itip_event['xml'].get_attendees() if a.get_email() == from_address][0] participant_status = itip_event['xml'].get_ical_attendee_participant_status(attendee) + + if participant_status == "DELEGATED": + # Extra actions to take + delegator = [a for a in itip_event['xml'].get_attendees() if a.get_email() == from_address][0] + delegatee = [a for a in itip_event['xml'].get_attendees() if from_address in [b.email() for b in a.get_delegated_from()]][0] + + itip_event['xml'].event.setAttendees([ delegator, delegatee ]) + + message = itip_event['xml'].to_message_itip(delegatee.get_email(), method="REPLY", participant_status=itip_event['xml'].get_ical_attendee_participant_status(delegatee)) + smtp.sendmail(message['From'], message['To'], message.as_string()) + + itip_event['xml'].event.setAttendees([a for a in itip_event['xml'].get_attendees() if a.get_email() == from_address]) + message = itip_event['xml'].to_message_itip(from_address, method="REPLY", participant_status=participant_status) smtp.sendmail(message['From'], message['To'], message.as_string()) + smtp.quit() |