Beispiel #1
0
    def processAvailabilityFreeBusy(self, calendar, fbinfo):
        """
        Extract free-busy data from a VAVAILABILITY component.

        @param calendar: the L{Component} that is the VCALENDAR containing the VAVAILABILITY's.
        @param fbinfo: the tuple used to store the three types of fb data.
        """

        for vav in [
                x for x in calendar.subcomponents()
                if x.name() == "VAVAILABILITY"
        ]:

            # Get overall start/end
            start = vav.getStartDateUTC()
            if start is None:
                start = DateTime(1900,
                                 1,
                                 1,
                                 0,
                                 0,
                                 0,
                                 tzid=Timezone.UTCTimezone)
            end = vav.getEndDateUTC()
            if end is None:
                end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone.UTCTimezone)
            period = Period(start, end)
            overall = clipPeriod(period, self.timerange)
            if overall is None:
                continue

            # Now get periods for each instance of AVAILABLE sub-components
            periods = self.processAvailablePeriods(vav)

            # Now invert the periods and store in accumulator
            busyperiods = []
            last_end = self.timerange.getStart()
            for period in periods:
                if last_end < period.getStart():
                    busyperiods.append(Period(last_end, period.getStart()))
                last_end = period.getEnd()
            if last_end < self.timerange.getEnd():
                busyperiods.append(Period(last_end, self.timerange.getEnd()))

            # Add to actual results mapped by busy type
            fbtype = vav.propertyValue("BUSYTYPE")
            if fbtype is None:
                fbtype = "BUSY-UNAVAILABLE"

            getattr(fbinfo,
                    self.FBInfo_mapper.get(fbtype,
                                           "unavailable")).extend(busyperiods)
Beispiel #2
0
    def _getNormalizedDateTimeProperties(self, component):

        # Basic time properties
        if component.name() in ("VEVENT", "VJOURNAL", "VPOLL"):
            dtstart = component.getProperty("DTSTART")
            dtend = component.getProperty("DTEND")
            duration = component.getProperty("DURATION")

            timeRange = Period(
                start=dtstart.value()  if dtstart  is not None else None,
                end=dtend.value()    if dtend    is not None else None,
                duration=duration.value() if duration is not None else None,
            )
            newdue = None

        elif component.name() == "VTODO":
            dtstart = component.getProperty("DTSTART")
            duration = component.getProperty("DURATION")

            if dtstart or duration:
                timeRange = Period(
                    start=dtstart.value()  if dtstart  is not None else None,
                    duration=duration.value() if duration is not None else None,
                )
            else:
                timeRange = Period()

            newdue = component.getProperty("DUE")
            if newdue is not None:
                newdue = newdue.value().duplicate().adjustToUTC()
        else:
            timeRange = Period()
            newdue = None

        # Recurrence rules - we need to normalize the order of the value parts
        newrrules = set()
        rrules = component.properties("RRULE")
        for rrule in rrules:
            indexedTokens = {}
            indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().getText().split(";")])
            sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
            newrrules.add(sortedValue)

        # RDATEs
        newrdates = set()
        rdates = component.properties("RDATE")
        for rdate in rdates:
            for value in rdate.value():
                if isinstance(value, DateTime):
                    value = value.duplicate().adjustToUTC()
                newrdates.add(value)

        # EXDATEs
        newexdates = set()
        exdates = component.properties("EXDATE")
        for exdate in exdates:
            newexdates.update([exvalue.getValue().duplicate().adjustToUTC() for exvalue in exdate.value()])

        return timeRange.getStart(), timeRange.getEnd(), newdue, newrrules, newrdates, newexdates
Beispiel #3
0
    def _getNormalizedDateTimeProperties(self, component):

        # Basic time properties
        if component.name() in ("VEVENT", "VJOURNAL", "VPOLL"):
            dtstart = component.getProperty("DTSTART")
            dtend = component.getProperty("DTEND")
            duration = component.getProperty("DURATION")

            timeRange = Period(
                start=dtstart.value() if dtstart is not None else None,
                end=dtend.value() if dtend is not None else None,
                duration=duration.value() if duration is not None else None,
            )
            newdue = None

        elif component.name() == "VTODO":
            dtstart = component.getProperty("DTSTART")
            duration = component.getProperty("DURATION")

            if dtstart or duration:
                timeRange = Period(
                    start=dtstart.value() if dtstart is not None else None,
                    duration=duration.value() if duration is not None else None,
                )
            else:
                timeRange = Period()

            newdue = component.getProperty("DUE")
            if newdue is not None:
                newdue = newdue.value().duplicate().adjustToUTC()
        else:
            timeRange = Period()
            newdue = None

        # Recurrence rules - we need to normalize the order of the value parts
        newrrules = set()
        rrules = component.properties("RRULE")
        for rrule in rrules:
            indexedTokens = {}
            indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().getText().split(";")])
            sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
            newrrules.add(sortedValue)

        # RDATEs
        newrdates = set()
        rdates = component.properties("RDATE")
        for rdate in rdates:
            for value in rdate.value():
                if isinstance(value, DateTime):
                    value = value.duplicate().adjustToUTC()
                newrdates.add(value)

        # EXDATEs
        newexdates = set()
        exdates = component.properties("EXDATE")
        for exdate in exdates:
            newexdates.update([exvalue.getValue().duplicate().adjustToUTC() for exvalue in exdate.value()])

        return timeRange.getStart(), timeRange.getEnd(), newdue, newrrules, newrdates, newexdates
Beispiel #4
0
    def getVFreeBusyFB(self, period, fb):
        # First create expanded set
        # TODO: fix this
        # list = ExpandedComponents()
        self.getVEvents(period, list)
        if len(list) == 0:
            return

        # Get start/end list for each non-all-day expanded components
        dtstart = []
        dtend = []
        for dt in list:

            # Ignore if all-day
            if dt.getInstanceStart().isDateOnly():
                continue

            # Ignore if transparent to free-busy
            transp = ""
            if dt.getOwner().getProperty(
                    definitions.cICalProperty_TRANSP,
                    transp) and (transp
                                 == definitions.cICalProperty_TRANSPARENT):
                continue

            # Add start/end to list
            dtstart.append(dt.getInstanceStart())
            dtend.append(dt.getInstanceEnd())

        # No longer need the expanded items
        list.clear()

        # Create non-overlapping periods as properties in the freebusy component
        temp = Period(dtstart.front(), dtend.front())
        dtstart_iter = dtstart.iter()
        dtstart_iter.next()
        dtend_iter = dtend.iter()
        dtend_iter.next()
        for i in i:

            # Check for non-overlap
            if dtstart_iter > temp.getEnd():

                # Current period is complete
                fb.addProperty(
                    Property(definitions.cICalProperty_FREEBUSY, temp))

                # Reset period to new range
                temp = Period(dtstart_iter, dtend_iter)

            # They overlap - check for extended end
            if dtend_iter > temp.getEnd():

                # Extend the end
                temp = Period(temp.getStart(), dtend_iter)

        # Add remaining period as property
        fb.addProperty(Property(definitions.cICalProperty_FREEBUSY, temp))
Beispiel #5
0
    def getVFreeBusyFB(self, period, fb):
        # First create expanded set
        # TODO: fix this
        # list = ExpandedComponents()
        self.getVEvents(period, list)
        if len(list) == 0:
            return

        # Get start/end list for each non-all-day expanded components
        dtstart = []
        dtend = []
        for dt in list:

            # Ignore if all-day
            if dt.getInstanceStart().isDateOnly():
                continue

            # Ignore if transparent to free-busy
            transp = ""
            if dt.getOwner().getProperty(definitions.cICalProperty_TRANSP, transp) and (transp == definitions.cICalProperty_TRANSPARENT):
                continue

            # Add start/end to list
            dtstart.append(dt.getInstanceStart())
            dtend.append(dt.getInstanceEnd())

        # No longer need the expanded items
        list.clear()

        # Create non-overlapping periods as properties in the freebusy component
        temp = Period(dtstart.front(), dtend.front())
        dtstart_iter = dtstart.iter()
        dtstart_iter.next()
        dtend_iter = dtend.iter()
        dtend_iter.next()
        for i in i:

            # Check for non-overlap
            if dtstart_iter > temp.getEnd():

                # Current period is complete
                fb.addProperty(Property(definitions.cICalProperty_FREEBUSY, temp))

                # Reset period to new range
                temp = Period(dtstart_iter, dtend_iter)

            # They overlap - check for extended end
            if dtend_iter > temp.getEnd():

                # Extend the end
                temp = Period(temp.getStart(), dtend_iter)

        # Add remaining period as property
        fb.addProperty(Property(definitions.cICalProperty_FREEBUSY, temp))
Beispiel #6
0
def processAvailabilityFreeBusy(calendar, fbinfo, timerange):
    """
    Extract free-busy data from a VAVAILABILITY component.
    @param calendar: the L{Component} that is the VCALENDAR containing the VAVAILABILITY's.
    @param fbinfo: the tuple used to store the three types of fb data.
    @param timerange: the time range to restrict free busy data to.
    """

    for vav in [x for x in calendar.subcomponents() if x.name() == "VAVAILABILITY"]:

        # Get overall start/end
        start = vav.getStartDateUTC()
        if start is None:
            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
        end = vav.getEndDateUTC()
        if end is None:
            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
        period = Period(start, end)
        overall = clipPeriod(period, Period(timerange.start, timerange.end))
        if overall is None:
            continue

        # Now get periods for each instance of AVAILABLE sub-components
        periods = processAvailablePeriods(vav, timerange)

        # Now invert the periods and store in accumulator
        busyperiods = []
        last_end = timerange.start
        for period in periods:
            if last_end < period.getStart():
                busyperiods.append(Period(last_end, period.getStart()))
            last_end = period.getEnd()
        if last_end < timerange.end:
            busyperiods.append(Period(last_end, timerange.end))

        # Add to actual results mapped by busy type
        fbtype = vav.propertyValue("BUSYTYPE")
        if fbtype is None:
            fbtype = "BUSY-UNAVAILABLE"

        fbinfo[fbtype_mapper.get(fbtype, 2)].extend(busyperiods)