Changeset View
Standalone View
pykolab/xml/event.py
Show All 20 Lines | |||||
from recurrence_rule import RecurrenceRule | from recurrence_rule import RecurrenceRule | ||||
log = pykolab.getLogger('pykolab.xml_event') | log = pykolab.getLogger('pykolab.xml_event') | ||||
def event_from_ical(ical, string=None): | def event_from_ical(ical, string=None): | ||||
return Event(from_ical=ical, from_string=string) | return Event(from_ical=ical, from_string=string) | ||||
def event_from_string(string): | def event_from_string(string): | ||||
Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
return Event(from_string=string) | return Event(from_string=string) | ||||
def event_from_message(message): | def event_from_message(message): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
event = None | event = None | ||||
if message.is_multipart(): | if message.is_multipart(): | ||||
for part in message.walk(): | for part in message.walk(): | ||||
if part.get_content_type() == "application/calendar+xml": | if part.get_content_type() == "application/calendar+xml": | ||||
payload = part.get_payload(decode=True) | payload = part.get_payload(decode=True) | ||||
event = event_from_string(payload) | event = event_from_string(payload) | ||||
# append attachment parts to Event object | # append attachment parts to Event object | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | class Event(object): | ||||
def _load_exceptions(self): | def _load_exceptions(self): | ||||
for ex in self.event.exceptions(): | for ex in self.event.exceptions(): | ||||
exception = Event() | exception = Event() | ||||
exception.uid = ex.uid() | exception.uid = ex.uid() | ||||
exception.event = ex | exception.event = ex | ||||
exception._load_attendees() | exception._load_attendees() | ||||
self._exceptions.append(exception) | self._exceptions.append(exception) | ||||
def add_attendee(self, email_or_attendee, name=None, rsvp=False, role=None, participant_status=None, cutype="INDIVIDUAL", params=None): | def add_attendee(self, email_or_attendee, name=None, rsvp=False, role=None, participant_status=None, cutype="INDIVIDUAL", params=None): | ||||
Lint: PEP8 E501 line too long (139 > 79 characters) Lint: PEP8 E501: line too long (139 > 79 characters) | |||||
if isinstance(email_or_attendee, Attendee): | if isinstance(email_or_attendee, Attendee): | ||||
attendee = email_or_attendee | attendee = email_or_attendee | ||||
else: | else: | ||||
attendee = Attendee(email_or_attendee, name, rsvp, role, participant_status, cutype, params) | attendee = Attendee(email_or_attendee, name, rsvp, role, participant_status, cutype, params) | ||||
Lint: PEP8 E501 line too long (104 > 79 characters) Lint: PEP8 E501: line too long (104 > 79 characters) | |||||
# apply update to self and all exceptions | # apply update to self and all exceptions | ||||
self.update_attendees([attendee], True) | self.update_attendees([attendee], True) | ||||
def add_category(self, category): | def add_category(self, category): | ||||
self._categories.append(ustr(category)) | self._categories.append(ustr(category)) | ||||
self.event.setCategories(self._categories) | self.event.setCategories(self._categories) | ||||
def add_recurrence_date(self, _datetime): | |||||
valid_datetime = False | |||||
if isinstance(_datetime, datetime.date): | |||||
valid_datetime = True | |||||
if isinstance(_datetime, datetime.datetime): | |||||
# If no timezone information is passed on, make it UTC | |||||
if _datetime.tzinfo is None: | |||||
_datetime = _datetime.replace(tzinfo=pytz.utc) | |||||
valid_datetime = True | |||||
if not valid_datetime: | |||||
raise InvalidEventDateError, _("Rdate needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | |||||
Lint: PEP8 W602 deprecated form of raising exception Lint: PEP8 W602: deprecated form of raising exception | |||||
Lint: PEP8 E501 line too long (129 > 79 characters) Lint: PEP8 E501: line too long (129 > 79 characters) | |||||
self.event.addRecurrenceDate(xmlutils.to_cdatetime(_datetime, True)) | |||||
def add_exception_date(self, _datetime): | def add_exception_date(self, _datetime): | ||||
valid_datetime = False | valid_datetime = False | ||||
if isinstance(_datetime, datetime.date): | if isinstance(_datetime, datetime.date): | ||||
valid_datetime = True | valid_datetime = True | ||||
if isinstance(_datetime, datetime.datetime): | if isinstance(_datetime, datetime.datetime): | ||||
# If no timezone information is passed on, make it UTC | # If no timezone information is passed on, make it UTC | ||||
if _datetime.tzinfo == None: | if _datetime.tzinfo == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_datetime = _datetime.replace(tzinfo=pytz.utc) | _datetime = _datetime.replace(tzinfo=pytz.utc) | ||||
valid_datetime = True | valid_datetime = True | ||||
if not valid_datetime: | if not valid_datetime: | ||||
raise InvalidEventDateError, _("Exdate needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | raise InvalidEventDateError, _("Exdate needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | ||||
Lint: PEP8 E501 line too long (130 > 79 characters) Lint: PEP8 E501: line too long (130 > 79 characters) | |||||
self.event.addExceptionDate(xmlutils.to_cdatetime(_datetime, True)) | self.event.addExceptionDate(xmlutils.to_cdatetime(_datetime, True)) | ||||
def add_exception(self, exception): | def add_exception(self, exception): | ||||
recurrence_id = exception.get_recurrence_id() | recurrence_id = exception.get_recurrence_id() | ||||
if recurrence_id is None: | if recurrence_id is None: | ||||
raise EventIntegrityError, "Recurrence exceptions require a Recurrence-ID property" | raise EventIntegrityError, "Recurrence exceptions require a Recurrence-ID property" | ||||
Lint: PEP8 E501 line too long (95 > 79 characters) Lint: PEP8 E501: line too long (95 > 79 characters) | |||||
# check if an exception with the given recurrence-id already exists | # check if an exception with the given recurrence-id already exists | ||||
append = True | append = True | ||||
vexceptions = self.event.exceptions() | vexceptions = self.event.exceptions() | ||||
for i, ex in enumerate(self._exceptions): | for i, ex in enumerate(self._exceptions): | ||||
if ex.get_recurrence_id() == recurrence_id and ex.thisandfuture == exception.thisandfuture: | if ex.get_recurrence_id() == recurrence_id and ex.thisandfuture == exception.thisandfuture: | ||||
Lint: PEP8 E501 line too long (103 > 79 characters) Lint: PEP8 E501: line too long (103 > 79 characters) | |||||
# update the existing exception | # update the existing exception | ||||
vexceptions[i] = exception.event | vexceptions[i] = exception.event | ||||
self._exceptions[i] = exception | self._exceptions[i] = exception | ||||
append = False | append = False | ||||
# check if main event matches the given recurrence-id | # check if main event matches the given recurrence-id | ||||
if append and self.get_recurrence_id() == recurrence_id: | if append and self.get_recurrence_id() == recurrence_id: | ||||
self.event = exception.event | self.event = exception.event | ||||
self._load_attendees() | self._load_attendees() | ||||
self._load_exceptions() | self._load_exceptions() | ||||
append = False | append = False | ||||
if append: | if append: | ||||
vexceptions.append(exception.event) | vexceptions.append(exception.event) | ||||
self._exceptions.append(exception) | self._exceptions.append(exception) | ||||
self.event.setExceptions(vexceptions) | self.event.setExceptions(vexceptions) | ||||
def del_exception(self, exception): | def del_exception(self, exception): | ||||
recurrence_id = exception.get_recurrence_id() | recurrence_id = exception.get_recurrence_id() | ||||
if recurrence_id is None: | if recurrence_id is None: | ||||
raise EventIntegrityError, "Recurrence exceptions require a Recurrence-ID property" | raise EventIntegrityError, "Recurrence exceptions require a Recurrence-ID property" | ||||
Lint: PEP8 E501 line too long (95 > 79 characters) Lint: PEP8 E501: line too long (95 > 79 characters) | |||||
updated = False | updated = False | ||||
vexceptions = self.event.exceptions() | vexceptions = self.event.exceptions() | ||||
for i, ex in enumerate(self._exceptions): | for i, ex in enumerate(self._exceptions): | ||||
if ex.get_recurrence_id() == recurrence_id and ex.thisandfuture == exception.thisandfuture: | if ex.get_recurrence_id() == recurrence_id and ex.thisandfuture == exception.thisandfuture: | ||||
Lint: PEP8 E501 line too long (103 > 79 characters) Lint: PEP8 E501: line too long (103 > 79 characters) | |||||
del vexceptions[i] | del vexceptions[i] | ||||
del self._exceptions[i] | del self._exceptions[i] | ||||
updated = True | updated = True | ||||
if updated: | if updated: | ||||
self.event.setExceptions(vexceptions) | self.event.setExceptions(vexceptions) | ||||
def as_string_itip(self, method="REQUEST"): | def as_string_itip(self, method="REQUEST"): | ||||
Lint: PEP8 E303 too many blank lines (2) Lint: PEP8 E303: too many blank lines (2) | |||||
cal = icalendar.Calendar() | cal = icalendar.Calendar() | ||||
cal.add( | cal.add( | ||||
'prodid', | 'prodid', | ||||
'-//pykolab-%s-%s//kolab.org//' % ( | '-//pykolab-%s-%s//kolab.org//' % ( | ||||
constants.__version__, | constants.__version__, | ||||
constants.__release__ | constants.__release__ | ||||
) | ) | ||||
) | ) | ||||
Show All 28 Lines | def to_ical(self): | ||||
# NOTE: Make sure to list(set()) or duplicates may arise | # NOTE: Make sure to list(set()) or duplicates may arise | ||||
for attr in list(set(event.singletons)): | for attr in list(set(event.singletons)): | ||||
_attr = attr.lower().replace('-', '') | _attr = attr.lower().replace('-', '') | ||||
ical_getter = 'get_ical_%s' % (_attr) | ical_getter = 'get_ical_%s' % (_attr) | ||||
default_getter = 'get_%s' % (_attr) | default_getter = 'get_%s' % (_attr) | ||||
retval = None | retval = None | ||||
if hasattr(self, ical_getter): | if hasattr(self, ical_getter): | ||||
retval = getattr(self, ical_getter)() | retval = getattr(self, ical_getter)() | ||||
if not retval == None and not retval == "": | if not retval == None and not retval == "": | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
event.add(attr.lower(), retval) | event.add(attr.lower(), retval) | ||||
elif hasattr(self, default_getter): | elif hasattr(self, default_getter): | ||||
retval = getattr(self, default_getter)() | retval = getattr(self, default_getter)() | ||||
if not retval == None and not retval == "": | if not retval == None and not retval == "": | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
event.add(attr.lower(), retval, encode=0) | event.add(attr.lower(), retval, encode=0) | ||||
# NOTE: Make sure to list(set()) or duplicates may arise | # NOTE: Make sure to list(set()) or duplicates may arise | ||||
for attr in list(set(event.multiple)): | for attr in list(set(event.multiple)): | ||||
_attr = attr.lower().replace('-', '') | _attr = attr.lower().replace('-', '') | ||||
ical_getter = 'get_ical_%s' % (_attr) | ical_getter = 'get_ical_%s' % (_attr) | ||||
default_getter = 'get_%s' % (_attr) | default_getter = 'get_%s' % (_attr) | ||||
retval = None | retval = None | ||||
Show All 23 Lines | def delegate(self, delegators, delegatees, names=None): | ||||
names = [names] | names = [names] | ||||
_delegators = [] | _delegators = [] | ||||
for delegator in delegators: | for delegator in delegators: | ||||
_delegators.append(self.get_attendee(delegator)) | _delegators.append(self.get_attendee(delegator)) | ||||
_delegatees = [] | _delegatees = [] | ||||
for i,delegatee in enumerate(delegatees): | for i,delegatee in enumerate(delegatees): | ||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
try: | try: | ||||
_delegatees.append(self.get_attendee(delegatee)) | _delegatees.append(self.get_attendee(delegatee)) | ||||
except: | except: | ||||
# TODO: An iTip needs to be sent out to the new attendee | # TODO: An iTip needs to be sent out to the new attendee | ||||
self.add_attendee(delegatee, names[i] if i < len(names) else None) | self.add_attendee(delegatee, names[i] if i < len(names) else None) | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
_delegatees.append(self.get_attendee(delegatee)) | _delegatees.append(self.get_attendee(delegatee)) | ||||
for delegator in _delegators: | for delegator in _delegators: | ||||
delegator.delegate_to(_delegatees) | delegator.delegate_to(_delegatees) | ||||
for delegatee in _delegatees: | for delegatee in _delegatees: | ||||
delegatee.delegate_from(_delegators) | delegatee.delegate_from(_delegators) | ||||
self.event.setAttendees(self._attendees) | self.event.setAttendees(self._attendees) | ||||
def from_ical(self, ical, raw=None): | def from_ical(self, ical, raw=None): | ||||
if isinstance(ical, icalendar.Event) or isinstance(ical, icalendar.Calendar): | if isinstance(ical, icalendar.Event) or isinstance(ical, icalendar.Calendar): | ||||
Lint: PEP8 E501 line too long (85 > 79 characters) Lint: PEP8 E501: line too long (85 > 79 characters) | |||||
ical_event = ical | ical_event = ical | ||||
elif hasattr(icalendar.Event, 'from_ical'): | elif hasattr(icalendar.Event, 'from_ical'): | ||||
ical_event = icalendar.Event.from_ical(ical) | ical_event = icalendar.Event.from_ical(ical) | ||||
elif hasattr(icalendar.Event, 'from_string'): | elif hasattr(icalendar.Event, 'from_string'): | ||||
ical_event = icalendar.Event.from_string(ical) | ical_event = icalendar.Event.from_string(ical) | ||||
# VCALENDAR block was given, find the first VEVENT item | # VCALENDAR block was given, find the first VEVENT item | ||||
if isinstance(ical_event, icalendar.Calendar): | if isinstance(ical_event, icalendar.Calendar): | ||||
for c in ical_event.walk(): | for c in ical_event.walk(): | ||||
if c.name == 'VEVENT': | if c.name == 'VEVENT': | ||||
ical_event = c | ical_event = c | ||||
break | break | ||||
# use the libkolab calendaring bindings to load the full iCal data | # use the libkolab calendaring bindings to load the full iCal data | ||||
if ical_event.has_key('RRULE') or ical_event.has_key('ATTACH') \ | if ical_event.has_key('RRULE') or ical_event.has_key('ATTACH') \ | ||||
or [part for part in ical_event.walk() if part.name == 'VALARM']: | or [part for part in ical_event.walk() if part.name == 'VALARM']: | ||||
Lint: PEP8 E127 continuation line over-indented for visual indent Lint: PEP8 E127: continuation line over-indented for visual indent | |||||
if raw is None or raw == "": | if raw is None or raw == "": | ||||
raw = ical if isinstance(ical, str) else ical.to_ical() | raw = ical if isinstance(ical, str) else ical.to_ical() | ||||
self._xml_from_ical(raw) | self._xml_from_ical(raw) | ||||
else: | else: | ||||
self.event = kolabformat.Event() | self.event = kolabformat.Event() | ||||
# TODO: Clause the timestamps for zulu suffix causing datetime.datetime | # TODO: Clause the timestamps for zulu suffix causing datetime.datetime | ||||
# to fail substitution. | # to fail substitution. | ||||
for attr in list(set(ical_event.required)): | for attr in list(set(ical_event.required)): | ||||
if ical_event.has_key(attr): | if ical_event.has_key(attr): | ||||
self.set_from_ical(attr.lower(), ical_event[attr]) | self.set_from_ical(attr.lower(), ical_event[attr]) | ||||
# NOTE: Make sure to list(set()) or duplicates may arise | # NOTE: Make sure to list(set()) or duplicates may arise | ||||
for attr in list(set(ical_event.singletons)): | for attr in list(set(ical_event.singletons)): | ||||
if ical_event.has_key(attr): | if ical_event.has_key(attr): | ||||
if isinstance(ical_event[attr], list): | if isinstance(ical_event[attr], list): | ||||
ical_event[attr] = ical_event[attr][0]; | ical_event[attr] = ical_event[attr][0]; | ||||
Lint: PEP8 E703 statement ends with a semicolon Lint: PEP8 E703: statement ends with a semicolon | |||||
self.set_from_ical(attr.lower(), ical_event[attr]) | self.set_from_ical(attr.lower(), ical_event[attr]) | ||||
# NOTE: Make sure to list(set()) or duplicates may arise | # NOTE: Make sure to list(set()) or duplicates may arise | ||||
for attr in list(set(ical_event.multiple)): | for attr in list(set(ical_event.multiple)): | ||||
if ical_event.has_key(attr): | if ical_event.has_key(attr): | ||||
self.set_from_ical(attr.lower(), ical_event[attr]) | self.set_from_ical(attr.lower(), ical_event[attr]) | ||||
def _xml_from_ical(self, ical): | def _xml_from_ical(self, ical): | ||||
if not "BEGIN:VCALENDAR" in ical: | if not "BEGIN:VCALENDAR" in ical: | ||||
Lint: PEP8 E713 test for membership should be 'not in' Lint: PEP8 E713: test for membership should be 'not in' | |||||
ical = "BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR" | ical = "BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR" | ||||
from kolab.calendaring import EventCal | from kolab.calendaring import EventCal | ||||
self.event = EventCal() | self.event = EventCal() | ||||
success = self.event.fromICal(ical) | success = self.event.fromICal(ical) | ||||
if success: | if success: | ||||
self._load_exceptions() | self._load_exceptions() | ||||
return success | return success | ||||
def get_attendee_participant_status(self, attendee): | def get_attendee_participant_status(self, attendee): | ||||
return attendee.get_participant_status() | return attendee.get_participant_status() | ||||
def get_attendee(self, attendee): | def get_attendee(self, attendee): | ||||
if isinstance(attendee, basestring): | if isinstance(attendee, basestring): | ||||
if attendee in [x.get_email() for x in self.get_attendees()]: | if attendee in [x.get_email() for x in self.get_attendees()]: | ||||
attendee = self.get_attendee_by_email(attendee) | attendee = self.get_attendee_by_email(attendee) | ||||
elif attendee in [x.get_name() for x in self.get_attendees()]: | elif attendee in [x.get_name() for x in self.get_attendees()]: | ||||
attendee = self.get_attendee_by_name(attendee) | attendee = self.get_attendee_by_name(attendee) | ||||
else: | else: | ||||
raise ValueError, _("No attendee with email or name %r") %(attendee) | raise ValueError, _("No attendee with email or name %r") %(attendee) | ||||
Lint: PEP8 E225 missing whitespace around operator Lint: PEP8 E225: missing whitespace around operator | |||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
return attendee | return attendee | ||||
elif isinstance(attendee, Attendee): | elif isinstance(attendee, Attendee): | ||||
return attendee | return attendee | ||||
else: | else: | ||||
raise ValueError, _("Invalid argument value attendee %r, must be basestring or Attendee") % (attendee) | raise ValueError, _("Invalid argument value attendee %r, must be basestring or Attendee") % (attendee) | ||||
Lint: PEP8 E501 line too long (114 > 79 characters) Lint: PEP8 E501: line too long (114 > 79 characters) | |||||
def find_attendee(self, attendee): | def find_attendee(self, attendee): | ||||
try: | try: | ||||
return self.get_attendee(attendee) | return self.get_attendee(attendee) | ||||
except: | except: | ||||
return None | return None | ||||
def get_attendee_by_email(self, email): | def get_attendee_by_email(self, email): | ||||
if email in [x.get_email() for x in self.get_attendees()]: | if email in [x.get_email() for x in self.get_attendees()]: | ||||
return [x for x in self.get_attendees() if x.get_email() == email][0] | return [x for x in self.get_attendees() if x.get_email() == email][0] | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
raise ValueError, _("No attendee with email %r") %(email) | raise ValueError, _("No attendee with email %r") %(email) | ||||
Lint: PEP8 E225 missing whitespace around operator Lint: PEP8 E225: missing whitespace around operator | |||||
def get_attendee_by_name(self, name): | def get_attendee_by_name(self, name): | ||||
if name in [x.get_name() for x in self.get_attendees()]: | if name in [x.get_name() for x in self.get_attendees()]: | ||||
return [x for x in self.get_attendees() if x.get_name() == name][0] | return [x for x in self.get_attendees() if x.get_name() == name][0] | ||||
raise ValueError, _("No attendee with name %r") %(name) | raise ValueError, _("No attendee with name %r") %(name) | ||||
Lint: PEP8 E225 missing whitespace around operator Lint: PEP8 E225: missing whitespace around operator | |||||
def get_attendees(self): | def get_attendees(self): | ||||
return self._attendees | return self._attendees | ||||
def get_categories(self): | def get_categories(self): | ||||
return [str(c) for c in self.event.categories()] | return [str(c) for c in self.event.categories()] | ||||
def get_classification(self): | def get_classification(self): | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | def get_date_text(self, date_format=None, time_format=None): | ||||
else: | else: | ||||
end_format = date_format + " " + time_format | end_format = date_format + " " + time_format | ||||
if all_day: | if all_day: | ||||
time_format = '' | time_format = '' | ||||
if start_date == end_date: | if start_date == end_date: | ||||
return start.strftime(date_format) | return start.strftime(date_format) | ||||
return "%s - %s" % (start.strftime(date_format + " " + time_format), end.strftime(end_format)) | return "%s - %s" % (start.strftime(date_format + " " + time_format), end.strftime(end_format)) | ||||
Lint: PEP8 E501 line too long (102 > 79 characters) Lint: PEP8 E501: line too long (102 > 79 characters) | |||||
def get_recurrence_dates(self): | |||||
return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.recurrenceDates()) | |||||
Lint: PEP8 E501 line too long (92 > 79 characters) Lint: PEP8 E501: line too long (92 > 79 characters) | |||||
def get_exception_dates(self): | def get_exception_dates(self): | ||||
return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates()) | return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates()) | ||||
Lint: PEP8 E501 line too long (91 > 79 characters) Lint: PEP8 E501: line too long (91 > 79 characters) | |||||
def get_exceptions(self): | def get_exceptions(self): | ||||
return self._exceptions | return self._exceptions | ||||
def has_exceptions(self): | def has_exceptions(self): | ||||
return len(self._exceptions) > 0 | return len(self._exceptions) > 0 | ||||
def get_attachments(self): | def get_attachments(self): | ||||
Show All 33 Lines | def get_ical_attendee(self): | ||||
partstat = attendee.get_participant_status() | partstat = attendee.get_participant_status() | ||||
cutype = attendee.get_cutype() | cutype = attendee.get_cutype() | ||||
delegators = attendee.get_delegated_from() | delegators = attendee.get_delegated_from() | ||||
delegatees = attendee.get_delegated_to() | delegatees = attendee.get_delegated_to() | ||||
if rsvp in attendee.rsvp_map.keys(): | if rsvp in attendee.rsvp_map.keys(): | ||||
_rsvp = rsvp | _rsvp = rsvp | ||||
elif rsvp in attendee.rsvp_map.values(): | elif rsvp in attendee.rsvp_map.values(): | ||||
_rsvp = [k for k, v in attendee.rsvp_map.iteritems() if v == rsvp][0] | _rsvp = [k for k, v in attendee.rsvp_map.iteritems() if v == rsvp][0] | ||||
Lint: PEP8 E501 line too long (85 > 79 characters) Lint: PEP8 E501: line too long (85 > 79 characters) | |||||
else: | else: | ||||
_rsvp = None | _rsvp = None | ||||
if role in attendee.role_map.keys(): | if role in attendee.role_map.keys(): | ||||
_role = role | _role = role | ||||
elif role in attendee.role_map.values(): | elif role in attendee.role_map.values(): | ||||
_role = [k for k, v in attendee.role_map.iteritems() if v == role][0] | _role = [k for k, v in attendee.role_map.iteritems() if v == role][0] | ||||
Lint: PEP8 E501 line too long (85 > 79 characters) Lint: PEP8 E501: line too long (85 > 79 characters) | |||||
else: | else: | ||||
_role = None | _role = None | ||||
if partstat in attendee.participant_status_map.keys(): | if partstat in attendee.participant_status_map.keys(): | ||||
_partstat = partstat | _partstat = partstat | ||||
elif partstat in attendee.participant_status_map.values(): | elif partstat in attendee.participant_status_map.values(): | ||||
_partstat = [k for k, v in attendee.participant_status_map.iteritems() if v == partstat][0] | _partstat = [k for k, v in attendee.participant_status_map.iteritems() if v == partstat][0] | ||||
Lint: PEP8 E501 line too long (107 > 79 characters) Lint: PEP8 E501: line too long (107 > 79 characters) | |||||
else: | else: | ||||
_partstat = None | _partstat = None | ||||
if cutype in attendee.cutype_map.keys(): | if cutype in attendee.cutype_map.keys(): | ||||
_cutype = cutype | _cutype = cutype | ||||
elif cutype in attendee.cutype_map.values(): | elif cutype in attendee.cutype_map.values(): | ||||
_cutype = [k for k, v in attendee.cutype_map.iteritems() if v == cutype][0] | _cutype = [k for k, v in attendee.cutype_map.iteritems() if v == cutype][0] | ||||
Lint: PEP8 E501 line too long (91 > 79 characters) Lint: PEP8 E501: line too long (91 > 79 characters) | |||||
else: | else: | ||||
_cutype = None | _cutype = None | ||||
_attendee = icalendar.vCalAddress("MAILTO:%s" % email) | _attendee = icalendar.vCalAddress("MAILTO:%s" % email) | ||||
if not name == None and not name == "": | if not name == None and not name == "": | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['CN'] = icalendar.vText(name) | _attendee.params['CN'] = icalendar.vText(name) | ||||
if not _rsvp == None: | if not _rsvp == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['RSVP'] = icalendar.vText(_rsvp) | _attendee.params['RSVP'] = icalendar.vText(_rsvp) | ||||
if not _role == None: | if not _role == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['ROLE'] = icalendar.vText(_role) | _attendee.params['ROLE'] = icalendar.vText(_role) | ||||
if not _partstat == None: | if not _partstat == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['PARTSTAT'] = icalendar.vText(_partstat) | _attendee.params['PARTSTAT'] = icalendar.vText(_partstat) | ||||
if not _cutype == None: | if not _cutype == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['CUTYPE'] = icalendar.vText(_cutype) | _attendee.params['CUTYPE'] = icalendar.vText(_cutype) | ||||
if not delegators == None and len(delegators) > 0: | if not delegators == None and len(delegators) > 0: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['DELEGATED-FROM'] = icalendar.vText(delegators[0].email()) | _attendee.params['DELEGATED-FROM'] = icalendar.vText(delegators[0].email()) | ||||
Lint: PEP8 E501 line too long (91 > 79 characters) Lint: PEP8 E501: line too long (91 > 79 characters) | |||||
if not delegatees == None and len(delegatees) > 0: | if not delegatees == None and len(delegatees) > 0: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_attendee.params['DELEGATED-TO'] = icalendar.vText(delegatees[0].email()) | _attendee.params['DELEGATED-TO'] = icalendar.vText(delegatees[0].email()) | ||||
Lint: PEP8 E501 line too long (89 > 79 characters) Lint: PEP8 E501: line too long (89 > 79 characters) | |||||
attendees.append(_attendee) | attendees.append(_attendee) | ||||
return attendees | return attendees | ||||
def get_ical_attendee_participant_status(self, attendee): | def get_ical_attendee_participant_status(self, attendee): | ||||
attendee = self.get_attendee(attendee) | attendee = self.get_attendee(attendee) | ||||
if attendee.get_participant_status() in attendee.participant_status_map.keys(): | if attendee.get_participant_status() in attendee.participant_status_map.keys(): | ||||
Lint: PEP8 E501 line too long (87 > 79 characters) Lint: PEP8 E501: line too long (87 > 79 characters) | |||||
return attendee.get_participant_status() | return attendee.get_participant_status() | ||||
elif attendee.get_participant_status() in attendee.participant_status_map.values(): | elif attendee.get_participant_status() in attendee.participant_status_map.values(): | ||||
Lint: PEP8 E501 line too long (91 > 79 characters) Lint: PEP8 E501: line too long (91 > 79 characters) | |||||
return [k for k, v in attendee.participant_status_map.iteritems() if v == attendee.get_participant_status()][0] | return [k for k, v in attendee.participant_status_map.iteritems() if v == attendee.get_participant_status()][0] | ||||
Lint: PEP8 E501 line too long (123 > 79 characters) Lint: PEP8 E501: line too long (123 > 79 characters) | |||||
else: | else: | ||||
raise ValueError, _("Invalid participant status") | raise ValueError, _("Invalid participant status") | ||||
def get_ical_created(self): | def get_ical_created(self): | ||||
return self.get_created() | return self.get_created() | ||||
def get_ical_dtend(self): | def get_ical_dtend(self): | ||||
dtend = self.get_end() | dtend = self.get_end() | ||||
# shift end by one day on all-day events | # shift end by one day on all-day events | ||||
if not hasattr(dtend, 'hour'): | if not hasattr(dtend, 'hour'): | ||||
dtend = dtend + datetime.timedelta(days=1) | dtend = dtend + datetime.timedelta(days=1) | ||||
return dtend | return dtend | ||||
def get_ical_dtstamp(self): | def get_ical_dtstamp(self): | ||||
try: | try: | ||||
retval = self.get_lastmodified() | retval = self.get_lastmodified() | ||||
if retval == None or retval == "": | if retval == None or retval == "": | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
return datetime.datetime.now() | return datetime.datetime.now() | ||||
except: | except: | ||||
return datetime.datetime.now() | return datetime.datetime.now() | ||||
def get_ical_lastmodified(self): | def get_ical_lastmodified(self): | ||||
return self.get_ical_dtstamp() | return self.get_ical_dtstamp() | ||||
def get_ical_dtstart(self): | def get_ical_dtstart(self): | ||||
return self.get_start() | return self.get_start() | ||||
def get_ical_organizer(self): | def get_ical_organizer(self): | ||||
contact = self.get_organizer() | contact = self.get_organizer() | ||||
organizer = icalendar.vCalAddress("MAILTO:%s" % contact.email()) | organizer = icalendar.vCalAddress("MAILTO:%s" % contact.email()) | ||||
name = contact.name() | name = contact.name() | ||||
if not name == None and not name == "": | if not name == None and not name == "": | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
organizer.params["CN"] = icalendar.vText(name) | organizer.params["CN"] = icalendar.vText(name) | ||||
return organizer | return organizer | ||||
def get_ical_status(self): | def get_ical_status(self): | ||||
status = self.event.status() | status = self.event.status() | ||||
if status in self.status_map.keys(): | if status in self.status_map.keys(): | ||||
return status | return status | ||||
return self._translate_value(status, self.status_map) if status else None | return self._translate_value(status, self.status_map) if status else None | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
def get_ical_class(self): | def get_ical_class(self): | ||||
class_ = self.event.classification() | class_ = self.event.classification() | ||||
return self._translate_value(class_, self.classification_map) if class_ else None | return self._translate_value(class_, self.classification_map) if class_ else None | ||||
Lint: PEP8 E501 line too long (89 > 79 characters) Lint: PEP8 E501: line too long (89 > 79 characters) | |||||
def get_ical_sequence(self): | def get_ical_sequence(self): | ||||
return str(self.event.sequence()) if self.event.sequence() else None | return str(self.event.sequence()) if self.event.sequence() else None | ||||
def get_ical_comment(self): | def get_ical_comment(self): | ||||
comment = self.get_comment() | comment = self.get_comment() | ||||
if comment is not None: | if comment is not None: | ||||
return [ comment ] | return [ comment ] | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
return None | return None | ||||
def get_ical_recurrenceid(self): | def get_ical_recurrenceid(self): | ||||
rid = self.get_recurrence_id() | rid = self.get_recurrence_id() | ||||
if isinstance(rid, datetime.datetime) or isinstance(rid, datetime.date): | if isinstance(rid, datetime.datetime) or isinstance(rid, datetime.date): | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
prop = icalendar.vDatetime(rid) if isinstance(rid, datetime.datetime) else icalendar.vDate(rid) | prop = icalendar.vDatetime(rid) if isinstance(rid, datetime.datetime) else icalendar.vDate(rid) | ||||
Lint: PEP8 E501 line too long (107 > 79 characters) Lint: PEP8 E501: line too long (107 > 79 characters) | |||||
if self.thisandfuture: | if self.thisandfuture: | ||||
prop.params.update({'RANGE':'THISANDFUTURE'}) | prop.params.update({'RANGE':'THISANDFUTURE'}) | ||||
Lint: PEP8 E231 missing whitespace after ':' Lint: PEP8 E231: missing whitespace after ':' | |||||
return prop | return prop | ||||
return None | return None | ||||
def get_ical_rrule(self): | def get_ical_rrule(self): | ||||
result = [] | result = [] | ||||
rrule = self.get_recurrence() | rrule = self.get_recurrence() | ||||
if rrule.isValid(): | if rrule.isValid(): | ||||
result.append(rrule.to_ical()) | result.append(rrule.to_ical()) | ||||
return result | return result | ||||
def get_ical_rdate(self): | |||||
rdates = self.get_recurrence_dates() | |||||
for i in range(len(rdates)): | |||||
rdates[i] = icalendar.prop.vDDDLists(rdates[i]) | |||||
return rdates | |||||
def get_location(self): | def get_location(self): | ||||
return self.event.location() | return self.event.location() | ||||
def get_lastmodified(self): | def get_lastmodified(self): | ||||
try: | try: | ||||
_datetime = self.event.lastModified() | _datetime = self.event.lastModified() | ||||
if _datetime == None or not _datetime.isValid(): | if _datetime == None or not _datetime.isValid(): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
self.__str__() | self.__str__() | ||||
except: | except: | ||||
self.__str__() | self.__str__() | ||||
return xmlutils.from_cdatetime(self.event.lastModified(), True) | return xmlutils.from_cdatetime(self.event.lastModified(), True) | ||||
def get_organizer(self): | def get_organizer(self): | ||||
organizer = self.event.organizer() | organizer = self.event.organizer() | ||||
return organizer | return organizer | ||||
def get_priority(self): | def get_priority(self): | ||||
return str(self.event.priority()) | return str(self.event.priority()) | ||||
def get_start(self): | def get_start(self): | ||||
return xmlutils.from_cdatetime(self.event.start(), True) | return xmlutils.from_cdatetime(self.event.start(), True) | ||||
def get_status(self, translated=False): | def get_status(self, translated=False): | ||||
status = self.event.status() | status = self.event.status() | ||||
if translated: | if translated: | ||||
return self._translate_value(status, self.status_map) if status else None | return self._translate_value(status, self.status_map) if status else None | ||||
Lint: PEP8 E501 line too long (85 > 79 characters) Lint: PEP8 E501: line too long (85 > 79 characters) | |||||
return status | return status | ||||
def get_summary(self): | def get_summary(self): | ||||
return self.event.summary() | return self.event.summary() | ||||
def get_uid(self): | def get_uid(self): | ||||
uid = self.event.uid() | uid = self.event.uid() | ||||
if not uid == '': | if not uid == '': | ||||
return uid | return uid | ||||
else: | else: | ||||
self.set_uid(uuid.uuid4()) | self.set_uid(uuid.uuid4()) | ||||
return self.get_uid() | return self.get_uid() | ||||
def get_recurrence_id(self): | def get_recurrence_id(self): | ||||
self.thisandfuture = self.event.thisAndFuture(); | self.thisandfuture = self.event.thisAndFuture(); | ||||
Lint: PEP8 E703 statement ends with a semicolon Lint: PEP8 E703: statement ends with a semicolon | |||||
recurrence_id = xmlutils.from_cdatetime(self.event.recurrenceID(), True) | recurrence_id = xmlutils.from_cdatetime(self.event.recurrenceID(), True) | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
# fix recurrence-id type if stored as date instead of datetime | # fix recurrence-id type if stored as date instead of datetime | ||||
if recurrence_id is not None and isinstance(recurrence_id, datetime.date): | if recurrence_id is not None and isinstance(recurrence_id, datetime.date): | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
dtstart = self.get_start() | dtstart = self.get_start() | ||||
if not type(recurrence_id) == type(dtstart): | if not type(recurrence_id) == type(dtstart): | ||||
recurrence_id = datetime.datetime.combine(recurrence_id, dtstart.time()).replace(tzinfo=dtstart.tzinfo) | recurrence_id = datetime.datetime.combine(recurrence_id, dtstart.time()).replace(tzinfo=dtstart.tzinfo) | ||||
Lint: PEP8 E501 line too long (119 > 79 characters) Lint: PEP8 E501: line too long (119 > 79 characters) | |||||
return recurrence_id | return recurrence_id | ||||
def get_thisandfuture(self): | def get_thisandfuture(self): | ||||
self.thisandfuture = self.event.thisAndFuture(); | self.thisandfuture = self.event.thisAndFuture(); | ||||
Lint: PEP8 E703 statement ends with a semicolon Lint: PEP8 E703: statement ends with a semicolon | |||||
return self.thisandfuture | return self.thisandfuture | ||||
def get_sequence(self): | def get_sequence(self): | ||||
return self.event.sequence() | return self.event.sequence() | ||||
def get_url(self): | def get_url(self): | ||||
return self.event.url() | return self.event.url() | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def merge_attendee_data(self, _attendees, append=True): | ||||
if not found and append: | if not found and append: | ||||
self._attendees.append(attendee) | self._attendees.append(attendee) | ||||
self.event.setAttendees(self._attendees) | self.event.setAttendees(self._attendees) | ||||
def set_classification(self, classification): | def set_classification(self, classification): | ||||
if classification in self.classification_map.keys(): | if classification in self.classification_map.keys(): | ||||
self.event.setClassification(self.classification_map[classification]) | self.event.setClassification(self.classification_map[classification]) | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
elif classification in self.classification_map.values(): | elif classification in self.classification_map.values(): | ||||
self.event.setClassification(status) | self.event.setClassification(status) | ||||
else: | else: | ||||
raise ValueError, _("Invalid classification %r") % (classification) | raise ValueError, _("Invalid classification %r") % (classification) | ||||
def set_created(self, _datetime=None): | def set_created(self, _datetime=None): | ||||
if _datetime == None: | if _datetime == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_datetime = datetime.datetime.utcnow() | _datetime = datetime.datetime.utcnow() | ||||
self.event.setCreated(xmlutils.to_cdatetime(_datetime, False, True)) | self.event.setCreated(xmlutils.to_cdatetime(_datetime, False, True)) | ||||
def set_description(self, description): | def set_description(self, description): | ||||
self.event.setDescription(ustr(description)) | self.event.setDescription(ustr(description)) | ||||
def set_comment(self, comment): | def set_comment(self, comment): | ||||
if hasattr(self.event, 'setComment'): | if hasattr(self.event, 'setComment'): | ||||
self.event.setComment(ustr(comment)) | self.event.setComment(ustr(comment)) | ||||
def set_dtstamp(self, _datetime): | def set_dtstamp(self, _datetime): | ||||
self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) | self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
def set_end(self, _datetime): | def set_end(self, _datetime): | ||||
valid_datetime = False | valid_datetime = False | ||||
if isinstance(_datetime, datetime.date): | if isinstance(_datetime, datetime.date): | ||||
valid_datetime = True | valid_datetime = True | ||||
if isinstance(_datetime, datetime.datetime): | if isinstance(_datetime, datetime.datetime): | ||||
# If no timezone information is passed on, make it UTC | # If no timezone information is passed on, make it UTC | ||||
if _datetime.tzinfo == None: | if _datetime.tzinfo == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_datetime = _datetime.replace(tzinfo=pytz.utc) | _datetime = _datetime.replace(tzinfo=pytz.utc) | ||||
valid_datetime = True | valid_datetime = True | ||||
if not valid_datetime: | if not valid_datetime: | ||||
raise InvalidEventDateError, _("Event end needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | raise InvalidEventDateError, _("Event end needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | ||||
Lint: PEP8 E501 line too long (133 > 79 characters) Lint: PEP8 E501: line too long (133 > 79 characters) | |||||
self.event.setEnd(xmlutils.to_cdatetime(_datetime, True)) | self.event.setEnd(xmlutils.to_cdatetime(_datetime, True)) | ||||
def set_exception_dates(self, _datetimes): | def set_exception_dates(self, _datetimes): | ||||
for _datetime in _datetimes: | for _datetime in _datetimes: | ||||
self.add_exception_date(_datetime) | self.add_exception_date(_datetime) | ||||
def set_recurrence_dates(self, _datetimes): | |||||
for _datetime in _datetimes: | |||||
self.add_recurrence_date(_datetime) | |||||
def add_custom_property(self, name, value): | def add_custom_property(self, name, value): | ||||
if not name.upper().startswith('X-'): | if not name.upper().startswith('X-'): | ||||
raise ValueError, _("Invalid custom property name %r") % (name) | raise ValueError, _("Invalid custom property name %r") % (name) | ||||
props = self.event.customProperties() | props = self.event.customProperties() | ||||
props.append(kolabformat.CustomProperty(name.upper(), value)) | props.append(kolabformat.CustomProperty(name.upper(), value)) | ||||
self.event.setCustomProperties(props) | self.event.setCustomProperties(props) | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def set_ical_attendee(self, _attendee): | ||||
else: | else: | ||||
rsvp = None | rsvp = None | ||||
if params.has_key('CUTYPE'): | if params.has_key('CUTYPE'): | ||||
cutype = params['CUTYPE'] | cutype = params['CUTYPE'] | ||||
else: | else: | ||||
cutype = kolabformat.CutypeIndividual | cutype = kolabformat.CutypeIndividual | ||||
att = self.add_attendee(address, name=name, rsvp=rsvp, role=role, participant_status=partstat, cutype=cutype, params=params) | att = self.add_attendee(address, name=name, rsvp=rsvp, role=role, participant_status=partstat, cutype=cutype, params=params) | ||||
Lint: PEP8 E501 line too long (140 > 79 characters) Lint: PEP8 E501: line too long (140 > 79 characters) | |||||
def set_ical_dtend(self, dtend): | def set_ical_dtend(self, dtend): | ||||
# shift end by one day on all-day events | # shift end by one day on all-day events | ||||
if not hasattr(dtend, 'hour'): | if not hasattr(dtend, 'hour'): | ||||
dtend = dtend - datetime.timedelta(days=1) | dtend = dtend - datetime.timedelta(days=1) | ||||
self.set_end(dtend) | self.set_end(dtend) | ||||
def set_ical_dtstamp(self, dtstamp): | def set_ical_dtstamp(self, dtstamp): | ||||
Show All 34 Lines | def set_ical_sequence(self, sequence): | ||||
self.set_sequence(sequence) | self.set_sequence(sequence) | ||||
def set_ical_summary(self, summary): | def set_ical_summary(self, summary): | ||||
self.set_summary(ustr(summary)) | self.set_summary(ustr(summary)) | ||||
def set_ical_uid(self, uid): | def set_ical_uid(self, uid): | ||||
self.set_uid(str(uid)) | self.set_uid(str(uid)) | ||||
def set_ical_rdate(self, rdate): | |||||
rdates = [] | |||||
# rdate here can be vDDDLists or a list of vDDDLists, why?! | |||||
if isinstance(rdate, icalendar.prop.vDDDLists): | |||||
rdate = [rdate] | |||||
for _rdate in rdate: | |||||
if isinstance(_rdate, icalendar.prop.vDDDLists): | |||||
tzid = None | |||||
if hasattr(_rdate, 'params') and 'TZID' in _rdate.params: | |||||
Not Done Inline ActionsDoes the existence of an _rdate.params attribute imply that the 'TZID' key is set? vanmeeuwen: Does the existence of an `_rdate.params` attribute imply that the 'TZID' key is set? | |||||
Not Done Inline ActionsYes, it does. According to icalendar code, but I'll add additional check. machniak: Yes, it does. According to icalendar code, but I'll add additional check. | |||||
tzid = _rdate.params['TZID'] | |||||
dts = icalendar.prop.vDDDLists.from_ical(_rdate.to_ical(), tzid) | |||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
for datetime in dts: | |||||
rdates.append(datetime) | |||||
self.set_recurrence_dates(rdates) | |||||
def set_ical_recurrenceid(self, value, params): | def set_ical_recurrenceid(self, value, params): | ||||
try: | try: | ||||
self.thisandfuture = params.get('RANGE', '') == 'THISANDFUTURE' | self.thisandfuture = params.get('RANGE', '') == 'THISANDFUTURE' | ||||
self.set_recurrence_id(value, self.thisandfuture) | self.set_recurrence_id(value, self.thisandfuture) | ||||
except InvalidEventDateError, e: | except InvalidEventDateError, e: | ||||
pass | pass | ||||
def set_lastmodified(self, _datetime=None): | def set_lastmodified(self, _datetime=None): | ||||
valid_datetime = False | valid_datetime = False | ||||
if isinstance(_datetime, datetime.date): | if isinstance(_datetime, datetime.date): | ||||
valid_datetime = True | valid_datetime = True | ||||
if isinstance(_datetime, datetime.datetime): | if isinstance(_datetime, datetime.datetime): | ||||
valid_datetime = True | valid_datetime = True | ||||
if _datetime == None: | if _datetime == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
valid_datetime = True | valid_datetime = True | ||||
_datetime = datetime.datetime.utcnow() | _datetime = datetime.datetime.utcnow() | ||||
if not valid_datetime: | if not valid_datetime: | ||||
raise InvalidEventDateError, _("Event last-modified needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | raise InvalidEventDateError, _("Event last-modified needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | ||||
Lint: PEP8 E501 line too long (143 > 79 characters) Lint: PEP8 E501: line too long (143 > 79 characters) | |||||
self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) | self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
def set_location(self, location): | def set_location(self, location): | ||||
self.event.setLocation(ustr(location)) | self.event.setLocation(ustr(location)) | ||||
def set_organizer(self, email, name=None): | def set_organizer(self, email, name=None): | ||||
contactreference = ContactReference(email) | contactreference = ContactReference(email) | ||||
if not name == None: | if not name == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
contactreference.setName(name) | contactreference.setName(name) | ||||
self.event.setOrganizer(contactreference) | self.event.setOrganizer(contactreference) | ||||
def set_priority(self, priority): | def set_priority(self, priority): | ||||
self.event.setPriority(priority) | self.event.setPriority(priority) | ||||
def set_sequence(self, sequence): | def set_sequence(self, sequence): | ||||
Show All 11 Lines | |||||
def set_start(self, _datetime): | def set_start(self, _datetime): | ||||
valid_datetime = False | valid_datetime = False | ||||
if isinstance(_datetime, datetime.date): | if isinstance(_datetime, datetime.date): | ||||
valid_datetime = True | valid_datetime = True | ||||
if isinstance(_datetime, datetime.datetime): | if isinstance(_datetime, datetime.datetime): | ||||
# If no timezone information is passed on, make it UTC | # If no timezone information is passed on, make it UTC | ||||
if _datetime.tzinfo == None: | if _datetime.tzinfo == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_datetime = _datetime.replace(tzinfo=pytz.utc) | _datetime = _datetime.replace(tzinfo=pytz.utc) | ||||
valid_datetime = True | valid_datetime = True | ||||
if not valid_datetime: | if not valid_datetime: | ||||
raise InvalidEventDateError, _("Event start needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | raise InvalidEventDateError, _("Event start needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) | ||||
Lint: PEP8 E501 line too long (135 > 79 characters) Lint: PEP8 E501: line too long (135 > 79 characters) | |||||
self.event.setStart(xmlutils.to_cdatetime(_datetime, True)) | self.event.setStart(xmlutils.to_cdatetime(_datetime, True)) | ||||
def set_status(self, status): | def set_status(self, status): | ||||
if status in self.status_map.keys(): | if status in self.status_map.keys(): | ||||
self.event.setStatus(self.status_map[status]) | self.event.setStatus(self.status_map[status]) | ||||
elif status in self.status_map.values(): | elif status in self.status_map.values(): | ||||
self.event.setStatus(status) | self.event.setStatus(status) | ||||
elif not status == kolabformat.StatusUndefined: | elif not status == kolabformat.StatusUndefined: | ||||
raise InvalidEventStatusError, _("Invalid status set: %r") % (status) | raise InvalidEventStatusError, _("Invalid status set: %r") % (status) | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
def set_summary(self, summary): | def set_summary(self, summary): | ||||
self.event.setSummary(summary) | self.event.setSummary(summary) | ||||
def set_uid(self, uid): | def set_uid(self, uid): | ||||
self.uid = uid | self.uid = uid | ||||
self.event.setUid(str(uid)) | self.event.setUid(str(uid)) | ||||
def set_recurrence_id(self, _datetime, _thisandfuture=None): | def set_recurrence_id(self, _datetime, _thisandfuture=None): | ||||
valid_datetime = False | valid_datetime = False | ||||
if isinstance(_datetime, datetime.date): | if isinstance(_datetime, datetime.date): | ||||
valid_datetime = True | valid_datetime = True | ||||
if isinstance(_datetime, datetime.datetime): | if isinstance(_datetime, datetime.datetime): | ||||
# If no timezone information is passed on, use the one from event start | # If no timezone information is passed on, use the one from event start | ||||
Lint: PEP8 E501 line too long (83 > 79 characters) Lint: PEP8 E501: line too long (83 > 79 characters) | |||||
if _datetime.tzinfo == None: | if _datetime.tzinfo == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
_start = self.get_start() | _start = self.get_start() | ||||
_datetime = _datetime.replace(tzinfo=_start.tzinfo) | _datetime = _datetime.replace(tzinfo=_start.tzinfo) | ||||
valid_datetime = True | valid_datetime = True | ||||
if not valid_datetime: | if not valid_datetime: | ||||
raise InvalidEventDateError, _("Event recurrence-id needs datetime.datetime instance") | raise InvalidEventDateError, _("Event recurrence-id needs datetime.datetime instance") | ||||
Lint: PEP8 E501 line too long (98 > 79 characters) Lint: PEP8 E501: line too long (98 > 79 characters) | |||||
if _thisandfuture is None: | if _thisandfuture is None: | ||||
_thisandfuture = self.thisandfuture | _thisandfuture = self.thisandfuture | ||||
self.event.setRecurrenceID(xmlutils.to_cdatetime(_datetime), _thisandfuture) | self.event.setRecurrenceID(xmlutils.to_cdatetime(_datetime), _thisandfuture) | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
def set_transparency(self, transp): | def set_transparency(self, transp): | ||||
return self.event.setTransparency(transp) | return self.event.setTransparency(transp) | ||||
def __str__(self): | def __str__(self): | ||||
event_xml = kolabformat.writeEvent(self.event) | event_xml = kolabformat.writeEvent(self.event) | ||||
error = kolabformat.error() | error = kolabformat.error() | ||||
if error == None or not error: | if error == None or not error: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
return event_xml | return event_xml | ||||
else: | else: | ||||
raise EventIntegrityError, kolabformat.errorMessage() | raise EventIntegrityError, kolabformat.errorMessage() | ||||
def to_dict(self): | def to_dict(self): | ||||
data = dict() | data = dict() | ||||
for p, getter in self.properties_map.iteritems(): | for p, getter in self.properties_map.iteritems(): | ||||
Show All 13 Lines | def to_dict(self): | ||||
for x in val: | for x in val: | ||||
data[x.identifier] = x.value | data[x.identifier] = x.value | ||||
val = None | val = None | ||||
elif isinstance(val, kolabformat.ContactReference): | elif isinstance(val, kolabformat.ContactReference): | ||||
val = ContactReference(val).to_dict() | val = ContactReference(val).to_dict() | ||||
elif isinstance(val, kolabformat.RecurrenceRule): | elif isinstance(val, kolabformat.RecurrenceRule): | ||||
val = RecurrenceRule(val).to_dict() | val = RecurrenceRule(val).to_dict() | ||||
elif isinstance(val, kolabformat.vectorattachment): | elif isinstance(val, kolabformat.vectorattachment): | ||||
val = [dict(fmttype=x.mimetype(), label=x.label(), uri=x.uri()) for x in val] | val = [dict(fmttype=x.mimetype(), label=x.label(), uri=x.uri()) for x in val] | ||||
Lint: PEP8 E501 line too long (93 > 79 characters) Lint: PEP8 E501: line too long (93 > 79 characters) | |||||
elif isinstance(val, kolabformat.vectoralarm): | elif isinstance(val, kolabformat.vectoralarm): | ||||
val = [self._alarm_to_dict(x) for x in val] | val = [self._alarm_to_dict(x) for x in val] | ||||
elif isinstance(val, list): | elif isinstance(val, list): | ||||
val = [x.to_dict() for x in val if hasattr(x, 'to_dict')] | val = [x.to_dict() for x in val if hasattr(x, 'to_dict')] | ||||
if val is not None: | if val is not None: | ||||
data[p] = val | data[p] = val | ||||
return data | return data | ||||
def _alarm_to_dict(self, alarm): | def _alarm_to_dict(self, alarm): | ||||
ret = dict( | ret = dict( | ||||
action=self._translate_value(alarm.type(), self.alarm_type_map), | action=self._translate_value(alarm.type(), self.alarm_type_map), | ||||
summary=alarm.summary(), | summary=alarm.summary(), | ||||
description=alarm.description(), | description=alarm.description(), | ||||
trigger=None | trigger=None | ||||
) | ) | ||||
start = alarm.start() | start = alarm.start() | ||||
if start and start.isValid(): | if start and start.isValid(): | ||||
ret['trigger'] = xmlutils.from_cdatetime(start, True) | ret['trigger'] = xmlutils.from_cdatetime(start, True) | ||||
else: | else: | ||||
ret['trigger'] = dict(related=self._translate_value(alarm.relativeTo(), self.related_map)) | ret['trigger'] = dict(related=self._translate_value(alarm.relativeTo(), self.related_map)) | ||||
Lint: PEP8 E501 line too long (102 > 79 characters) Lint: PEP8 E501: line too long (102 > 79 characters) | |||||
duration = alarm.relativeStart() | duration = alarm.relativeStart() | ||||
if duration and duration.isValid(): | if duration and duration.isValid(): | ||||
prefix = '-' if duration.isNegative() else '+' | prefix = '-' if duration.isNegative() else '+' | ||||
value = prefix + "P%dW%dDT%dH%dM%dS" % ( | value = prefix + "P%dW%dDT%dH%dM%dS" % ( | ||||
duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds() | duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds() | ||||
Lint: PEP8 E501 line too long (111 > 79 characters) Lint: PEP8 E501: line too long (111 > 79 characters) | |||||
) | ) | ||||
ret['trigger']['value'] = re.sub(r"T$", '', re.sub(r"0[WDHMS]", '', value)) | ret['trigger']['value'] = re.sub(r"T$", '', re.sub(r"0[WDHMS]", '', value)) | ||||
Lint: PEP8 E501 line too long (91 > 79 characters) Lint: PEP8 E501: line too long (91 > 79 characters) | |||||
if alarm.type() == kolabformat.Alarm.EMailAlarm: | if alarm.type() == kolabformat.Alarm.EMailAlarm: | ||||
ret['attendee'] = [ContactReference(a).to_dict() for a in alarm.attendees()] | ret['attendee'] = [ContactReference(a).to_dict() for a in alarm.attendees()] | ||||
Lint: PEP8 E501 line too long (88 > 79 characters) Lint: PEP8 E501: line too long (88 > 79 characters) | |||||
return ret | return ret | ||||
def _translate_value(self, val, map): | def _translate_value(self, val, map): | ||||
name_map = dict([(v, k) for (k, v) in map.iteritems()]) | name_map = dict([(v, k) for (k, v) in map.iteritems()]) | ||||
return name_map[val] if name_map.has_key(val) else 'UNKNOWN' | return name_map[val] if name_map.has_key(val) else 'UNKNOWN' | ||||
def to_message(self, creator=None): | def to_message(self, creator=None): | ||||
Show All 22 Lines | def to_message(self, creator=None): | ||||
text = utils.multiline_message(""" | text = utils.multiline_message(""" | ||||
This is a Kolab Groupware object. To view this object you | This is a Kolab Groupware object. To view this object you | ||||
will need an email client that understands the Kolab | will need an email client that understands the Kolab | ||||
Groupware format. For a list of such email clients please | Groupware format. For a list of such email clients please | ||||
visit http://www.kolab.org/ | visit http://www.kolab.org/ | ||||
""") | """) | ||||
msg.attach( MIMEText(text) ) | msg.attach( MIMEText(text) ) | ||||
Lint: PEP8 E201 whitespace after '(' Lint: PEP8 E201: whitespace after '(' | |||||
Lint: PEP8 E202 whitespace before ')' Lint: PEP8 E202: whitespace before ')' | |||||
part = MIMEBase('application', "calendar+xml") | part = MIMEBase('application', "calendar+xml") | ||||
part.set_charset('UTF-8') | part.set_charset('UTF-8') | ||||
msg["Subject"] = self.get_uid() | msg["Subject"] = self.get_uid() | ||||
# extract attachment data into separate MIME parts | # extract attachment data into separate MIME parts | ||||
vattach = self.event.attachments() | vattach = self.event.attachments() | ||||
i = 0 | i = 0 | ||||
for attach in vattach: | for attach in vattach: | ||||
if attach.uri(): | if attach.uri(): | ||||
continue | continue | ||||
mimetype = attach.mimetype() | mimetype = attach.mimetype() | ||||
(primary, seconday) = mimetype.split('/') | (primary, seconday) = mimetype.split('/') | ||||
name = attach.label() | name = attach.label() | ||||
if not name: | if not name: | ||||
name = 'unknown.x' | name = 'unknown.x' | ||||
(basename, suffix) = path.splitext(name) | (basename, suffix) = path.splitext(name) | ||||
t = datetime.datetime.now() | t = datetime.datetime.now() | ||||
cid = "%s.%s.%s%s" % (basename, time.mktime(t.timetuple()), t.microsecond + len(self._attachment_parts), suffix) | cid = "%s.%s.%s%s" % (basename, time.mktime(t.timetuple()), t.microsecond + len(self._attachment_parts), suffix) | ||||
Lint: PEP8 E501 line too long (124 > 79 characters) Lint: PEP8 E501: line too long (124 > 79 characters) | |||||
p = MIMEBase(primary, seconday) | p = MIMEBase(primary, seconday) | ||||
p.add_header('Content-Disposition', 'attachment', filename=name) | p.add_header('Content-Disposition', 'attachment', filename=name) | ||||
p.add_header('Content-Transfer-Encoding', 'base64') | p.add_header('Content-Transfer-Encoding', 'base64') | ||||
p.add_header('Content-ID', '<' + cid + '>') | p.add_header('Content-ID', '<' + cid + '>') | ||||
p.set_payload(base64.b64encode(attach.data())) | p.set_payload(base64.b64encode(attach.data())) | ||||
self._attachment_parts.append(p) | self._attachment_parts.append(p) | ||||
# modify attachment object | # modify attachment object | ||||
attach.setData('', mimetype) | attach.setData('', mimetype) | ||||
attach.setUri('cid:' + cid, mimetype) | attach.setUri('cid:' + cid, mimetype) | ||||
vattach[i] = attach | vattach[i] = attach | ||||
i += 1 | i += 1 | ||||
self.event.setAttachments(vattach) | self.event.setAttachments(vattach) | ||||
part.set_payload(str(self)) | part.set_payload(str(self)) | ||||
part.add_header('Content-Disposition', 'attachment; filename="kolab.xml"') | part.add_header('Content-Disposition', 'attachment; filename="kolab.xml"') | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
part.replace_header('Content-Transfer-Encoding', '8bit') | part.replace_header('Content-Transfer-Encoding', '8bit') | ||||
msg.attach(part) | msg.attach(part) | ||||
# append attachment parts | # append attachment parts | ||||
for p in self._attachment_parts: | for p in self._attachment_parts: | ||||
msg.attach(p) | msg.attach(p) | ||||
return msg | return msg | ||||
def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED", subject=None, message_text=None): | def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED", subject=None, message_text=None): | ||||
Lint: PEP8 E501 line too long (126 > 79 characters) Lint: PEP8 E501: line too long (126 > 79 characters) | |||||
from email.MIMEMultipart import MIMEMultipart | from email.MIMEMultipart import MIMEMultipart | ||||
from email.MIMEBase import MIMEBase | from email.MIMEBase import MIMEBase | ||||
from email.MIMEText import MIMEText | from email.MIMEText import MIMEText | ||||
from email.Utils import COMMASPACE, formatdate | from email.Utils import COMMASPACE, formatdate | ||||
# encode unicode strings with quoted-printable | # encode unicode strings with quoted-printable | ||||
from email import charset | from email import charset | ||||
charset.add_charset('utf-8', charset.SHORTEST, charset.QP) | charset.add_charset('utf-8', charset.SHORTEST, charset.QP) | ||||
Show All 29 Lines | def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED", subject=None, message_text=None): | ||||
elif from_address in attendee.get_delegated_from(True): | elif from_address in attendee.get_delegated_from(True): | ||||
reply_attendees.append(attendee) | reply_attendees.append(attendee) | ||||
# keep only replying (and delegated) attendee(s) | # keep only replying (and delegated) attendee(s) | ||||
self._attendees = reply_attendees | self._attendees = reply_attendees | ||||
self.event.setAttendees(self._attendees) | self.event.setAttendees(self._attendees) | ||||
if msg_from == None: | if msg_from == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
organizer = self.get_organizer() | organizer = self.get_organizer() | ||||
email = organizer.email() | email = organizer.email() | ||||
name = organizer.name() | name = organizer.name() | ||||
if email == from_address: | if email == from_address: | ||||
if not name: | if not name: | ||||
msg_from = email | msg_from = email | ||||
else: | else: | ||||
msg_from = '"%s" <%s>' % (name, email) | msg_from = '"%s" <%s>' % (name, email) | ||||
elif method == "REQUEST": | elif method == "REQUEST": | ||||
organizer = self.get_organizer() | organizer = self.get_organizer() | ||||
email = organizer.email() | email = organizer.email() | ||||
name = organizer.name() | name = organizer.name() | ||||
if not name: | if not name: | ||||
msg_from = email | msg_from = email | ||||
else: | else: | ||||
msg_from = '"%s" <%s>' % (name, email) | msg_from = '"%s" <%s>' % (name, email) | ||||
if msg_from == None: | if msg_from == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if from_address == None: | if from_address == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.error(_("No sender specified")) | log.error(_("No sender specified")) | ||||
else: | else: | ||||
msg_from = from_address | msg_from = from_address | ||||
msg['From'] = utils.str2unicode(msg_from) | msg['From'] = utils.str2unicode(msg_from) | ||||
msg['Date'] = formatdate(localtime=True) | msg['Date'] = formatdate(localtime=True) | ||||
if subject is None: | if subject is None: | ||||
subject = _("Invitation for %s was %s") % (self.get_summary(), participant_status_label(participant_status)) | subject = _("Invitation for %s was %s") % (self.get_summary(), participant_status_label(participant_status)) | ||||
Lint: PEP8 E501 line too long (120 > 79 characters) Lint: PEP8 E501: line too long (120 > 79 characters) | |||||
msg['Subject'] = utils.str2unicode(subject) | msg['Subject'] = utils.str2unicode(subject) | ||||
if message_text is None: | if message_text is None: | ||||
message_text = _("""This is an automated response to one of your event requests.""") | message_text = _("""This is an automated response to one of your event requests.""") | ||||
Lint: PEP8 E501 line too long (96 > 79 characters) Lint: PEP8 E501: line too long (96 > 79 characters) | |||||
msg.attach(MIMEText(utils.stripped_message(message_text), _charset='utf-8')) | msg.attach(MIMEText(utils.stripped_message(message_text), _charset='utf-8')) | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
part = MIMEBase('text', 'calendar', charset='UTF-8', method=method) | part = MIMEBase('text', 'calendar', charset='UTF-8', method=method) | ||||
del part['MIME-Version'] # mime parts don't need this | del part['MIME-Version'] # mime parts don't need this | ||||
part.set_payload(self.as_string_itip(method=method)) | part.set_payload(self.as_string_itip(method=method)) | ||||
part.add_header('Content-Disposition', 'attachment; filename="event.ics"') | part.add_header('Content-Disposition', 'attachment; filename="event.ics"') | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
part.add_header('Content-Transfer-Encoding', '8bit') | part.add_header('Content-Transfer-Encoding', '8bit') | ||||
msg.attach(part) | msg.attach(part) | ||||
# restore the original list of attendees | # restore the original list of attendees | ||||
# attendees being reduced to the replying attendee above | # attendees being reduced to the replying attendee above | ||||
if attendees is not None: | if attendees is not None: | ||||
self._attendees = attendees | self._attendees = attendees | ||||
self.event.setAttendees(self._attendees) | self.event.setAttendees(self._attendees) | ||||
return msg | return msg | ||||
def is_recurring(self): | def is_recurring(self): | ||||
return self.event.recurrenceRule().isValid() | return self.event.recurrenceRule().isValid() or len(self.get_recurrence_dates()) > 0 | ||||
Lint: PEP8 E501 line too long (92 > 79 characters) Lint: PEP8 E501: line too long (92 > 79 characters) | |||||
Not Done Inline ActionsShould not both clauses in this || statement evaluate to True? It seems that for a recurring event, .isValid() should be true as well as (implicitly) a positive number of occurrences should exist. Note also that a "recurring" event with only one occurrence would validate len() > 0, which may not yield the expected results. Also note that self.event (the lower-level XML level) and self.get_recurrence_dates() work on two different in-memory representations of the event, allowing for race-conditions. Perhaps it is best to ensure the complete event is read and parsed, which should logically lead to two equals copies. vanmeeuwen: Should not both clauses in this `||` statement evaluate to True? It seems that for a recurring… | |||||
Not Done Inline ActionsRDATE specified additional occurrences. So if there's one RDATE it is recurring event. There can be an event with RDATE but no recurrence rule. So, I think this is correct. I don't get the last paragraph. get_recurrence_dates() also uses self.event. machniak: RDATE specified additional occurrences. So if there's one RDATE it is recurring event. There… | |||||
def to_event_cal(self): | def to_event_cal(self): | ||||
from kolab.calendaring import EventCal | from kolab.calendaring import EventCal | ||||
return EventCal(self.event) | return EventCal(self.event) | ||||
def get_next_occurence(self, _datetime): | def get_next_occurence(self, _datetime): | ||||
if not hasattr(self, 'eventcal'): | if not hasattr(self, 'eventcal'): | ||||
self.eventcal = self.to_event_cal() | self.eventcal = self.to_event_cal() | ||||
next_cdatetime = self.eventcal.getNextOccurence(xmlutils.to_cdatetime(_datetime, True)) | next_cdatetime = self.eventcal.getNextOccurence(xmlutils.to_cdatetime(_datetime, True)) | ||||
Lint: PEP8 E501 line too long (95 > 79 characters) Lint: PEP8 E501: line too long (95 > 79 characters) | |||||
next_datetime = xmlutils.from_cdatetime(next_cdatetime, True) if next_cdatetime is not None else None | next_datetime = xmlutils.from_cdatetime(next_cdatetime, True) if next_cdatetime is not None else None | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E501 line too long (110 > 79 characters) Lint: PEP8 E501: line too long (110 > 79 characters) | |||||
# cut infinite recurrence at a reasonable point | # cut infinite recurrence at a reasonable point | ||||
if next_datetime and not self.get_last_occurrence() and next_datetime > xmlutils.to_dt(self._recurrence_end()): | if next_datetime and not self.get_last_occurrence() and next_datetime > xmlutils.to_dt(self._recurrence_end()): | ||||
Lint: PEP8 E501 line too long (119 > 79 characters) Lint: PEP8 E501: line too long (119 > 79 characters) | |||||
next_datetime = None | next_datetime = None | ||||
# next_datetime is always a cdatetime, convert to date if necessary | # next_datetime is always a cdatetime, convert to date if necessary | ||||
if next_datetime and not isinstance(self.get_start(), datetime.datetime): | if next_datetime and not isinstance(self.get_start(), datetime.datetime): | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
next_datetime = datetime.date(next_datetime.year, next_datetime.month, next_datetime.day) | next_datetime = datetime.date(next_datetime.year, next_datetime.month, next_datetime.day) | ||||
Lint: PEP8 E501 line too long (101 > 79 characters) Lint: PEP8 E501: line too long (101 > 79 characters) | |||||
return next_datetime | return next_datetime | ||||
def get_occurence_end_date(self, datetime): | def get_occurence_end_date(self, datetime): | ||||
if not datetime: | if not datetime: | ||||
return None | return None | ||||
if not hasattr(self, 'eventcal'): | if not hasattr(self, 'eventcal'): | ||||
return None | return None | ||||
end_cdatetime = self.eventcal.getOccurenceEndDate(xmlutils.to_cdatetime(datetime, True)) | end_cdatetime = self.eventcal.getOccurenceEndDate(xmlutils.to_cdatetime(datetime, True)) | ||||
Lint: PEP8 E501 line too long (96 > 79 characters) Lint: PEP8 E501: line too long (96 > 79 characters) | |||||
return xmlutils.from_cdatetime(end_cdatetime, True) if end_cdatetime is not None else None | return xmlutils.from_cdatetime(end_cdatetime, True) if end_cdatetime is not None else None | ||||
Lint: PEP8 E501 line too long (98 > 79 characters) Lint: PEP8 E501: line too long (98 > 79 characters) | |||||
def get_last_occurrence(self, force=False): | def get_last_occurrence(self, force=False): | ||||
if not hasattr(self, 'eventcal'): | if not hasattr(self, 'eventcal'): | ||||
self.eventcal = self.to_event_cal() | self.eventcal = self.to_event_cal() | ||||
last = self.eventcal.getLastOccurrence() | last = self.eventcal.getLastOccurrence() | ||||
last_datetime = xmlutils.from_cdatetime(last, True) if last is not None else None | last_datetime = xmlutils.from_cdatetime(last, True) if last is not None else None | ||||
Lint: PEP8 E501 line too long (89 > 79 characters) Lint: PEP8 E501: line too long (89 > 79 characters) | |||||
# we're forced to return some date | # we're forced to return some date | ||||
if last_datetime is None and force: | if last_datetime is None and force: | ||||
last_datetime = self._recurrence_end() | last_datetime = self._recurrence_end() | ||||
return last_datetime | return last_datetime | ||||
def get_next_instance(self, datetime): | def get_next_instance(self, datetime): | ||||
next_start = self.get_next_occurence(datetime) | next_start = self.get_next_occurence(datetime) | ||||
if next_start: | if next_start: | ||||
instance = Event(from_string=str(self)) | instance = Event(from_string=str(self)) | ||||
instance.set_start(next_start) | instance.set_start(next_start) | ||||
instance.event.setRecurrenceID(xmlutils.to_cdatetime(next_start), False) | instance.event.setRecurrenceID(xmlutils.to_cdatetime(next_start), False) | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
next_end = self.get_occurence_end_date(next_start) | next_end = self.get_occurence_end_date(next_start) | ||||
if next_end: | if next_end: | ||||
instance.set_end(next_end) | instance.set_end(next_end) | ||||
# unset recurrence rule and exceptions | # unset recurrence rule and exceptions | ||||
instance.set_recurrence(kolabformat.RecurrenceRule()) | instance.set_recurrence(kolabformat.RecurrenceRule()) | ||||
instance.event.setExceptions(kolabformat.vectorevent()) | instance.event.setExceptions(kolabformat.vectorevent()) | ||||
instance.event.setExceptionDates(kolabformat.vectordatetime()) | instance.event.setExceptionDates(kolabformat.vectordatetime()) | ||||
instance._exceptions = [] | instance._exceptions = [] | ||||
instance._isexception = False | instance._isexception = False | ||||
# unset attachments list (only stored in main event) | # unset attachments list (only stored in main event) | ||||
instance.event.setAttachments(kolabformat.vectorattachment()) | instance.event.setAttachments(kolabformat.vectorattachment()) | ||||
# copy data from matching exception | # copy data from matching exception | ||||
# (give precedence to single occurrence exceptions over thisandfuture) | # (give precedence to single occurrence exceptions over thisandfuture) | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
for exception in self._exceptions: | for exception in self._exceptions: | ||||
recurrence_id = exception.get_recurrence_id() | recurrence_id = exception.get_recurrence_id() | ||||
if recurrence_id == next_start and (not exception.thisandfuture or not instance._isexception): | if recurrence_id == next_start and (not exception.thisandfuture or not instance._isexception): | ||||
Lint: PEP8 E501 line too long (110 > 79 characters) Lint: PEP8 E501: line too long (110 > 79 characters) | |||||
instance = exception | instance = exception | ||||
instance._isexception = True | instance._isexception = True | ||||
if not exception.thisandfuture: | if not exception.thisandfuture: | ||||
break | break | ||||
elif exception.thisandfuture and next_start > recurrence_id: | elif exception.thisandfuture and next_start > recurrence_id: | ||||
# TODO: merge exception properties over this instance + adjust start/end with the according offset | # TODO: merge exception properties over this instance + adjust start/end with the according offset | ||||
Lint: PEP8 E501 line too long (118 > 79 characters) Lint: PEP8 E501: line too long (118 > 79 characters) | |||||
pass | pass | ||||
return instance | return instance | ||||
return None | return None | ||||
def get_instance(self, _datetime): | def get_instance(self, _datetime): | ||||
# If no timezone information is given, use the one from event start | # If no timezone information is given, use the one from event start | ||||
if isinstance(_datetime, datetime.datetime) and _datetime.tzinfo == None: | if isinstance(_datetime, datetime.datetime) and _datetime.tzinfo == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
_start = self.get_start() | _start = self.get_start() | ||||
if hasattr(_start, 'tzinfo'): | if hasattr(_start, 'tzinfo'): | ||||
_datetime = _datetime.replace(tzinfo=_start.tzinfo) | _datetime = _datetime.replace(tzinfo=_start.tzinfo) | ||||
if self.is_recurring(): | if self.is_recurring(): | ||||
instance = self.get_next_instance(_datetime - datetime.timedelta(days=1)) | instance = self.get_next_instance(_datetime - datetime.timedelta(days=1)) | ||||
Lint: PEP8 E501 line too long (85 > 79 characters) Lint: PEP8 E501: line too long (85 > 79 characters) | |||||
while instance: | while instance: | ||||
recurrence_id = instance.get_recurrence_id() | recurrence_id = instance.get_recurrence_id() | ||||
if type(recurrence_id) == type(_datetime) and recurrence_id <= _datetime: | if type(recurrence_id) == type(_datetime) and recurrence_id <= _datetime: | ||||
Lint: PEP8 E501 line too long (89 > 79 characters) Lint: PEP8 E501: line too long (89 > 79 characters) | |||||
if xmlutils.dates_equal(recurrence_id, _datetime): | if xmlutils.dates_equal(recurrence_id, _datetime): | ||||
return instance | return instance | ||||
instance = self.get_next_instance(instance.get_start()) | instance = self.get_next_instance(instance.get_start()) | ||||
else: | else: | ||||
break | break | ||||
elif self.has_exceptions(): | elif self.has_exceptions(): | ||||
for exception in self._exceptions: | for exception in self._exceptions: | ||||
recurrence_id = exception.get_recurrence_id() | recurrence_id = exception.get_recurrence_id() | ||||
if type(recurrence_id) == type(_datetime) and xmlutils.dates_equal(recurrence_id, _datetime): | if type(recurrence_id) == type(_datetime) and xmlutils.dates_equal(recurrence_id, _datetime): | ||||
Lint: PEP8 E501 line too long (109 > 79 characters) Lint: PEP8 E501: line too long (109 > 79 characters) | |||||
return exception | return exception | ||||
if self.get_recurrence_id(): | if self.get_recurrence_id(): | ||||
recurrence_id = self.get_recurrence_id() | recurrence_id = self.get_recurrence_id() | ||||
if type(recurrence_id) == type(_datetime) and xmlutils.dates_equal(recurrence_id, _datetime): | if type(recurrence_id) == type(_datetime) and xmlutils.dates_equal(recurrence_id, _datetime): | ||||
Lint: PEP8 E501 line too long (105 > 79 characters) Lint: PEP8 E501: line too long (105 > 79 characters) | |||||
return self | return self | ||||
return None | return None | ||||
def _recurrence_end(self): | def _recurrence_end(self): | ||||
""" | """ | ||||
Determine a reasonable end date for infinitely recurring events | Determine a reasonable end date for infinitely recurring events | ||||
""" | """ | ||||
rrule = self.event.recurrenceRule() | rrule = self.event.recurrenceRule() | ||||
if rrule.isValid() and rrule.count() < 0 and not rrule.end().isValid(): | if rrule.isValid() and rrule.count() < 0 and not rrule.end().isValid(): | ||||
now = datetime.datetime.now() | now = datetime.datetime.now() | ||||
switch = { | switch = { | ||||
kolabformat.RecurrenceRule.Yearly: 100, | kolabformat.RecurrenceRule.Yearly: 100, | ||||
kolabformat.RecurrenceRule.Monthly: 20 | kolabformat.RecurrenceRule.Monthly: 20 | ||||
} | } | ||||
intvl = switch[rrule.frequency()] if rrule.frequency() in switch else 10 | intvl = switch[rrule.frequency()] if rrule.frequency() in switch else 10 | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
return self.get_start().replace(year=now.year + intvl) | return self.get_start().replace(year=now.year + intvl) | ||||
return xmlutils.from_cdatetime(rrule.end(), True) | return xmlutils.from_cdatetime(rrule.end(), True) | ||||
class EventIntegrityError(Exception): | class EventIntegrityError(Exception): | ||||
def __init__(self, message): | def __init__(self, message): | ||||
Exception.__init__(self, message) | Exception.__init__(self, message) | ||||
class InvalidEventDateError(Exception): | class InvalidEventDateError(Exception): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
def __init__(self, message): | def __init__(self, message): | ||||
Exception.__init__(self, message) | Exception.__init__(self, message) | ||||
class InvalidEventStatusError(Exception): | class InvalidEventStatusError(Exception): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
def __init__(self, message): | def __init__(self, message): | ||||
Exception.__init__(self, message) | Exception.__init__(self, message) | ||||
expected 2 blank lines, found 1