Exemplo n.º 1
0
def addTaskStamp(item):
    ts = TaskStamp(item)
    ts.add()

    ts.summary = uw("Test Task Summary")
    ts.itsItem.setTriageStatus(randomEnum(pim.TriageEnum))
    return ts
Exemplo n.º 2
0
def addTaskStamp(item):
    ts = TaskStamp(item)
    ts.add()

    ts.summary = uw("Test Task Summary")
    ts.itsItem.setTriageStatus(randomEnum(pim.TriageEnum))
    return ts
Exemplo n.º 3
0
def parseTaskInfo(mailStamp):
    assert isinstance(mailStamp, MailStamp)

    if has_stamp(mailStamp.itsItem, TaskStamp):
        # The message has already been stamped as
        # a task
        return

    taskStamp = TaskStamp(mailStamp.itsItem)
    taskStamp.add()
Exemplo n.º 4
0
def parseTaskInfo(mailStamp):
    assert isinstance(mailStamp, MailStamp)

    if has_stamp(mailStamp.itsItem, TaskStamp):
        # The message has already been stamped as
        # a task
        return

    taskStamp = TaskStamp(mailStamp.itsItem)
    taskStamp.add()
Exemplo n.º 5
0
def itemsToVObject(view, items, cal=None, filters=None):
    """
    Iterate through items, add to cal, create a new vcalendar if needed.

    Consider only master events (then serialize all modifications).  For now,
    set all timezones to Pacific.

    """

    if filters is None:
        filters = () # we want filters to be iterable
    
    def makeDateTimeValue(dt, asDate=False):
        if asDate:
            return dt.date()
        elif dt.tzinfo == view.tzinfo.floating:
            return dt.replace(tzinfo=None)
        else:
            return dt

    
    def populateCommon(comp, item):
        """
        Populate the given vevent or vtodo vobject with values for
        attributes common to Events or Tasks).
        """
        
        if getattr(item, Note.icalUID.name, None) is None:
            item.icalUID = unicode(item.itsUUID)
        comp.add('uid').value = item.icalUID

        # displayName --> SUMMARY
        try:
            summary = item.displayName
        except AttributeError:
            pass
        else:
            comp.add('summary').value = summary
            
        # body --> DESCRIPTION
        try:
            description = item.body
        except AttributeError:
            pass
        else:
            if description:
                comp.add('description').value = description
                
        # userReminder --> VALARM
        if Remindable.reminders.name not in filters:
            firstReminder = item.getUserReminder()
            if firstReminder is not None:
                if firstReminder.absoluteTime is not None:
                    value = firstReminder.absoluteTime
                else:
                    # @@@ For now, all relative reminders are relative to starttime
                    assert firstReminder.relativeTo == EventStamp.effectiveStartTime.name
                    value = firstReminder.delta
                comp.add('valarm').add('trigger').value = value
                
    def populateCustom(comp, item):
        # custom properties
        for name, value in item.icalendarProperties.iteritems():
            prop = comp.add(name)

            # for unrecognized properties, import stores strings, not
            # native types like datetimes.  So value should just be a
            # string, not a more complicated python data structure.  Don't
            # try to transform the value when serializing
            prop.isNative = False
            
            # encoding escapes characters like backslash and comma and
            # combines list values into a single string.  This was already
            # done when the icalendar was imported, so don't escape again
            prop.encoded = True
            
            prop.value = value
                
        for name, paramstring in item.icalendarParameters.iteritems():
            paramdict = comp.contents[name][0].params
            for paramlist in vobject.base.parseParams(paramstring):
                # parseParams gives a list of lists of parameters, with the
                # first element of each list being the name of the
                # parameter, followed by the parameter values, if any
                paramname = paramlist[0].upper()
                if paramname.lower() in parametersUnderstood:
                    # parameters understood by Chandler shouldn't be stored
                    # in icalendarParameters, but changes to which
                    # parameters Chandler understands can lead to spurious
                    # parameters, ignore them
                    continue
                paramvalues = paramdict.setdefault(paramname, [])
                paramvalues.extend(paramlist[1:])
        
        

    
    def populateEvent(comp, event):
        """Populate the given vobject vevent with data from event."""
        
        populateCommon(comp, event.itsItem)
        
        try:
            dtstartLine = comp.add('dtstart')
            
            # allDay-ness overrides anyTime-ness
            if event.anyTime and not event.allDay:
                dtstartLine.x_osaf_anytime_param = 'TRUE'
                
            dtstartLine.value = makeDateTimeValue(event.startTime,
                                    event.anyTime or event.allDay)

        except AttributeError:
            comp.dtstart = [] # delete the dtstart that was added
        
        try:
            if not (event.duration == datetime.timedelta(0) or (
                    (event.anyTime or event.allDay) and 
                    event.duration <= oneDay)):
                dtendLine = comp.add('dtend')
                #convert Chandler's notion of allDay duration to iCalendar's
                if event.allDay:
                    dtendLine.value = event.endTime.date() + oneDay
                else:
                    if event.anyTime:
                        dtendLine.x_osaf_anytime_param = 'TRUE'

                    # anyTime should be exported as allDay for non-Chandler apps
                    dtendLine.value = makeDateTimeValue(event.endTime,
                                                        event.anyTime)

        except AttributeError:
            comp.dtend = [] # delete the dtend that was added
            

        if EventStamp.transparency.name not in filters:
            try:
                status = event.transparency.upper()
                # anytime events should be interpreted as not taking up time,
                # but all-day shouldn't
                if status == 'FYI' or (not event.allDay and event.anyTime):
                    status = 'CANCELLED'
                comp.add('status').value = status
            except AttributeError:
                pass

        try:
            comp.add('location').value = event.location.displayName
        except AttributeError:
            pass
        
        view = event.itsItem.itsView
        timestamp = datetime.datetime.utcnow()
        comp.add('dtstamp').value = timestamp.replace(tzinfo=view.tzinfo.UTC)

        if event.modificationFor is not None:
            recurrenceid = comp.add('recurrence-id')
            masterEvent = event.getMaster()
            allDay = masterEvent.allDay or masterEvent.anyTime
            
            recurrenceid.value = makeDateTimeValue(event.recurrenceID, allDay)
        
        # logic for serializing rrules needs to move to vobject
        try: # hack, create RRULE line last, because it means running transformFromNative
            if event.getMaster() == event and event.rruleset is not None:
                # False because we don't want to ignore isCount for export
                # True because we don't want to use view.tzinfo.floating
                cal.vevent_list[-1].rruleset = event.createDateUtilFromRule(False, True, False)
        except AttributeError:
            logger.error('Failed to export RRULE for %s' % event.itsItem.itsUUID)
        # end of populateEvent function
        
        populateCustom(comp, event.itsItem)


    def populateModifications(event, cal):
        for modification in itertools.imap(EventStamp, event.modifications):
            for attr, val in modification.itsItem.iterModifiedAttributes():
                if attr in attributesUsedWhenExporting and attr not in filters:
                    populateEvent(cal.add('vevent'), modification)
                    break
        #end helper functions
        
    def populateTask(comp, task):
        """Populate the given vobject vtodo with data from task."""
        populateCommon(comp, task.itsItem)

        # @@@ [grant] Once we start writing out Event+Tasks as
        # VTODO, write out DUE (or maybe DTSTART) here.

        if Note._triageStatus.name not in filters:
            triageStatus = task.itsItem._triageStatus
            
            # VTODO STATUS mapping:
            # ---------------------
            #
            #  [ICalendar]            [Triage Enum]
            #  <no value>/IN-PROCESS    now  (needsReply=False)
            #  NEEDS-ACTION             now  (needsReply=True)
            #  COMPLETED                done
            #  CANCELLED                later
            
            if triageStatus == TriageEnum.now:
                if task.itsItem.needsReply:
                    comp.add('status').value = 'needs-action'
                else:
                    comp.add('status').value = 'in-process'
            elif triageStatus == TriageEnum.later:
                comp.add('status').value = 'cancelled'
            else:
                comp.add('status').value = 'completed'
                
        populateCustom(comp, task.itsItem)

    if cal is None:
        cal = vobject.iCalendar()
    for item in items: # main loop
        try:
            # ignore any events that aren't masters
            #
            # Note: [grant]
            # At the moment, we allow Event-ness to take precedence over
            # Task-ness. So, we serialize Event+Task objects as VEVENTs.
            # Part of the reason for this is that recurring VTODOs aren't
            # so well-supported by other iCalendar clients. For RFC 2445
            # issues with VTODO+RRULE, see e.g.
            # <http://lists.osafoundation.org/pipermail/ietf-calsify/2006-August/001134.html>
            if has_stamp(item, EventStamp):
                event = EventStamp(item)
                if event.getMaster() == event:
                  populateEvent(cal.add('vevent'), event)
                populateModifications(event, cal)
            elif has_stamp(item, TaskStamp):
                  populateTask(cal.add('vtodo'), TaskStamp(item))
        except:
            logger.exception("Exception while exporting %s" % item)
            continue

    return cal