def editStatus(self, status): # Only if it is different if self.mStatus != status: # Updated cached values self.mStatus = status # Remove existing STATUS & COMPLETED items self.removeProperties(definitions.cICalProperty_STATUS) self.removeProperties(definitions.cICalProperty_COMPLETED) self.mHasCompleted = False # Now create properties value = None if status == definitions.eStatus_VToDo_NeedsAction: value = definitions.cICalProperty_STATUS_NEEDS_ACTION if status == definitions.eStatus_VToDo_Completed: value = definitions.cICalProperty_STATUS_COMPLETED # Add the completed item self.mCompleted.setNowUTC() self.mHasCompleted = True prop = Property(definitions.cICalProperty_STATUS_COMPLETED, self.mCompleted) self.addProperty(prop) elif status == definitions.eStatus_VToDo_InProcess: value = definitions.cICalProperty_STATUS_IN_PROCESS elif status == definitions.eStatus_VToDo_Cancelled: value = definitions.cICalProperty_STATUS_CANCELLED prop = Property(definitions.cICalProperty_STATUS, value) self.addProperty(prop)
def alarmTriggered(self, dt): # Remove existing self.removeProperties(definitions.cICalProperty_ALARM_X_LASTTRIGGER) self.removeProperties(definitions.cICalProperty_ALARM_X_ALARMSTATUS) # Updated cached values self.mLastTrigger.copy(dt) if self.mDoneCount < self.mRepeats: self.mNextTrigger = self.mLastTrigger + self.mRepeatInterval dt.copy(self.mNextTrigger) self.mDoneCount += 1 self.mAlarmStatus = definitions.eAlarm_Status_Pending else: self.mAlarmStatus = definitions.eAlarm_Status_Completed # Add new self.addProperty( Property(definitions.cICalProperty_ALARM_X_LASTTRIGGER, dt)) status = "" if self.mAlarmStatus == definitions.eAlarm_Status_Pending: status = definitions.cICalProperty_ALARM_X_ALARMSTATUS_PENDING elif self.mAlarmStatus == definitions.eAlarm_Status_Completed: status = definitions.cICalProperty_ALARM_X_ALARMSTATUS_COMPLETED elif self.mAlarmStatus == definitions.eAlarm_Status_Disabled: status = definitions.cICalProperty_ALARM_X_ALARMSTATUS_DISABLED self.addProperty( Property(definitions.cICalProperty_ALARM_X_ALARMSTATUS, status)) # Now update dt to the next alarm time return self.mAlarmStatus == definitions.eAlarm_Status_Pending
def editRecurrenceSet(self, recurs): # Must have items if self.mRecurrences is None: self.mRecurrences = RecurrenceSet() # Updated cached values self.mRecurrences = recurs # Remove existing RRULE, EXRULE, RDATE & EXDATE self.removeProperties(definitions.cICalProperty_RRULE) self.removeProperties(definitions.cICalProperty_EXRULE) self.removeProperties(definitions.cICalProperty_RDATE) self.removeProperties(definitions.cICalProperty_EXDATE) # Now create properties for iter in self.mRecurrences.getRules(): prop = Property(definitions.cICalProperty_RRULE, iter) self.addProperty(prop) for iter in self.getExrules(): prop = Property(definitions.cICalProperty_EXRULE, iter) self.addProperty(prop) for iter in self.mRecurrences.getDates(): prop = Property(definitions.cICalProperty_RDATE, iter) self.addProperty(prop) for iter in self.mRecurrences.getExdates(): prop = Property(definitions.cICalProperty_EXDATE, iter) self.addProperty(prop)
def vtimezone(self, vtz, zonerule, start, end, offsetfrom, offsetto): # Determine type of component based on offset comp = Standard(parent=vtz) # Do offsets tzoffsetfrom = UTCOffsetValue(offsetfrom) tzoffsetto = UTCOffsetValue(offsetto) comp.addProperty( Property(definitions.cICalProperty_TZOFFSETFROM, tzoffsetfrom)) comp.addProperty( Property(definitions.cICalProperty_TZOFFSETTO, tzoffsetto)) # Do TZNAME if self.format.find("%") != -1: tzname = self.format % ("S", ) else: tzname = self.format comp.addProperty(Property(definitions.cICalProperty_TZNAME, tzname)) # Do DTSTART comp.addProperty(Property(definitions.cICalProperty_DTSTART, start)) # Recurrence comp.addProperty(Property(definitions.cICalProperty_RDATE, start)) comp.finalise() vtz.addComponent(comp)
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))
def deriveComponent(self, recurrenceID): """ Derive an overridden component for the associated RECURRENCE-ID. This assumes that the R-ID is valid for the actual recurrence being used. @param recurrenceID: the recurrence instance @type recurrenceID: L{DateTime} @return: the derived component @rtype: L{ComponentRecur} or L{None} """ master = self.masterComponent() if master is None: return None # Create the derived instance newcomp = master.duplicate() # Strip out unwanted recurrence properties for propname in ( definitions.cICalProperty_RRULE, definitions.cICalProperty_RDATE, definitions.cICalProperty_EXRULE, definitions.cICalProperty_EXDATE, definitions.cICalProperty_RECURRENCE_ID, ): newcomp.removeProperties(propname) # New DTSTART is the RECURRENCE-ID we are deriving but adjusted to the # original DTSTART's localtime dtstart = newcomp.getStart() dtend = newcomp.getEnd() oldduration = dtend - dtstart newdtstartValue = recurrenceID.duplicate() if not dtstart.isDateOnly(): if dtstart.local(): newdtstartValue.adjustTimezone(dtstart.getTimezone()) else: newdtstartValue.setDateOnly(True) newcomp.removeProperties(definitions.cICalProperty_DTSTART) newcomp.removeProperties(definitions.cICalProperty_DTEND) prop = Property(definitions.cICalProperty_DTSTART, newdtstartValue) newcomp.addProperty(prop) if not newcomp.useDuration(): prop = Property(definitions.cICalProperty_DTEND, newdtstartValue + oldduration) newcomp.addProperty(prop) newcomp.addProperty(Property("RECURRENCE-ID", newdtstartValue)) # After creating/changing a component we need to do this to keep PyCalendar happy newcomp.finalise() return newcomp
def editRepeats(self, repeat, interval): # Remove existing self.removeProperties(definitions.cICalProperty_REPEAT) self.removeProperties(definitions.cICalProperty_DURATION) # Updated cached values self.mRepeats = repeat self.mRepeatInterval = interval # Add new if self.mRepeats > 0: self.addProperty(Property(definitions.cICalProperty_REPEAT, repeat)) self.addProperty(Property(definitions.cICalProperty_DURATION, interval))
def add(self, valarm): # Delete existing then add self.remove(valarm) prop = Property(definitions.cICalProperty_DESCRIPTION, self.mDescription) valarm.addProperty(prop) prop = Property(definitions.cICalProperty_SUMMARY, self.mSummary) valarm.addProperty(prop) for iter in self.mAttendees: prop = Property(definitions.cICalProperty_ATTENDEE, iter, Value.VALUETYPE_CALADDRESS) valarm.addProperty(prop)
def testUnknownValueRoundtrip(self): data = "X-FOO:Text, not escaped" prop = Property.parseText(data) self.assertEqual(str(prop), data + "\r\n") prop = Property("X-FOO", "Text, not escaped") self.assertEqual(str(prop), data + "\r\n") data = "X-FOO:Text\\, escaped\\n" prop = Property.parseText(data) self.assertEqual(str(prop), data + "\r\n") prop = Property("X-FOO", "Text\\, escaped\\n") self.assertEqual(str(prop), data + "\r\n")
def add(self, valarm): # Delete existing then add self.remove(valarm) prop = Property(definitions.cICalProperty_ACTION_X_SPEAKTEXT, self.mSpeakText) valarm.addProperty(prop)
def check_cardinality_STATUS_Fix(self, fixed, unfixed, doFix): """ Special for bug with STATUS where STATUS:CANCELLED is added alongside another STATUS. In this case we want STATUS:CANCELLED to win. """ for propname in self.propertyCardinality_STATUS_Fix: if self.countProperty(propname) > 1: logProblem = "[%s] Too many properties: %s" % (self.getType(), propname) if doFix: # Check that one of them is STATUS:CANCELLED for prop in self.getProperties(propname): if prop.getTextValue().getValue().upper( ) == definitions.cICalProperty_STATUS_CANCELLED: self.removeProperties(propname) self.addProperty( Property( propname, definitions. cICalProperty_STATUS_CANCELLED)) fixed.append(logProblem) break else: unfixed.append(logProblem) else: unfixed.append(logProblem)
def add(self, valarm): # Delete existing then add self.remove(valarm) prop = Property(definitions.cICalProperty_DESCRIPTION, self.mDescription) valarm.addProperty(prop)
def setSeq(self, seq): self.mSeq = seq self.removeProperties(definitions.cICalProperty_SEQUENCE) prop = Property(definitions.cICalProperty_SEQUENCE, self.mSeq) self.addProperty(prop)
def editStatus(self, status): # Only if it is different if self.mStatus != status: # Updated cached values self.mStatus = status # Remove existing STATUS items self.removeProperties(definitions.cICalProperty_STATUS) # Now create properties value = None if status == definitions.eStatus_VEvent_None: pass elif status == definitions.eStatus_VEvent_Tentative: value = definitions.cICalProperty_STATUS_TENTATIVE elif status == definitions.eStatus_VEvent_Confirmed: value = definitions.cICalProperty_STATUS_CONFIRMED elif status == definitions.eStatus_VEvent_Cancelled: value = definitions.cICalProperty_STATUS_CANCELLED else: pass if value is not None: prop = Property(definitions.cICalProperty_STATUS, value) self.addProperty(prop)
def _doNonEquality(caldata): cal1 = Calendar() cal1.parse(StringIO.StringIO(caldata)) cal2 = Calendar() cal2.parse(StringIO.StringIO(caldata)) cal2.addProperty(Property("X-FOO", "BAR")) self.assertNotEqual(cal1, cal2)
def excludeFutureRecurrence(self, start): # Must have items if self.mRecurrences is None: return # Adjust RRULES to end before start self.mRecurrences.excludeFutureRecurrence(start) # Remove existing RRULE & RDATE self.removeProperties(definitions.cICalProperty_RRULE) self.removeProperties(definitions.cICalProperty_RDATE) # Now create properties for iter in self.mRecurrences.getRules(): prop = Property(definitions.cICalProperty_RRULE, iter) self.addProperty(prop) for iter in self.mRecurrences.getDates(): prop = Property(definitions.cICalProperty_RDATE, iter) self.addProperty(prop)
def testNewRegistrationValueRoundtrip(self): Property.registerDefaultValue("X-SPECIAL-REGISTRATION", Value.VALUETYPE_TEXT) data = "X-SPECIAL-REGISTRATION:Text\\, escaped\\n" prop = Property.parseText(data) self.assertEqual(str(prop), "X-SPECIAL-REGISTRATION:Text\\, escaped\\n\r\n") prop = Property("X-SPECIAL-REGISTRATION", "Text, escaped\n") self.assertEqual(str(prop), "X-SPECIAL-REGISTRATION:Text\\, escaped\\n\r\n")
def excludeRecurrence(self, start): # Must have items if self.mRecurrences is None: return # Add to recurrence set and clear cache self.mRecurrences.subtract(start) # Add property prop = Property(definitions.cICalProperty_EXDATE, start) self.addProperty(prop)
def editDescription(self, description): if self.mDescription != description: # Updated cached value self.mDescription = description # Remove existing items self.removeProperties(definitions.cICalProperty_XWRCALDESC) # Now create properties if len(description): self.addProperty(Property(definitions.cICalProperty_XWRCALDESC, description))
def editTriggerOn(self, dt): # Remove existing self.removeProperties(definitions.cICalProperty_TRIGGER) # Updated cached values self.mTriggerAbsolute = True self.mTriggerOn = dt # Add new prop = Property(definitions.cICalProperty_TRIGGER, dt) self.addProperty(prop)
def editName(self, name): if self.mName != name: # Updated cached value self.mName = name # Remove existing items self.removeProperties(definitions.cICalProperty_XWRCALNAME) # Now create properties if len(name): self.ddProperty(Property(definitions.cICalProperty_XWRCALNAME, name))
def editCompleted(self, completed): # Remove existing COMPLETED item self.removeProperties(definitions.cICalProperty_COMPLETED) self.mHasCompleted = False # Always UTC self.mCompleted = completed.duplicate() self.mCompleted.adjustToUTC() self.mHasCompleted = True prop = Property(definitions.cICalProperty_STATUS_COMPLETED, self.mCompleted) self.addProperty(prop)
def editTimingStartEnd(self, start, end): # Updated cached values self.mHasStart = self.mHasEnd = True self.mStart = start self.mEnd = end self.mDuration = False self.FixStartEnd() # Remove existing DTSTART & DTEND & DURATION & DUE items self.removeProperties(definitions.cICalProperty_DTSTART) self.removeProperties(definitions.cICalProperty_DTEND) self.removeProperties(definitions.cICalProperty_DURATION) self.removeProperties(definitions.cICalProperty_DUE) # Now create properties prop = Property(definitions.cICalProperty_DTSTART, start) self.addProperty(prop) # If its an all day event and the end one day after the start, ignore it temp = start.duplicate() temp.offsetDay(1) if not start.isDateOnly() or end != temp: prop = Property(definitions.cICalProperty_DTEND, end) self.addProperty(prop)
def editTimingStartDuration(self, start, duration): # Updated cached values self.mHasStart = True self.mHasEnd = False self.mStart = start self.mEnd = start + duration self.mDuration = True # Remove existing DTSTART & DTEND & DURATION & DUE items self.removeProperties(definitions.cICalProperty_DTSTART) self.removeProperties(definitions.cICalProperty_DTEND) self.removeProperties(definitions.cICalProperty_DURATION) self.removeProperties(definitions.cICalProperty_DUE) # Now create properties prop = Property(definitions.cICalProperty_DTSTART, start) self.addProperty(prop) # If its an all day event and the duration is one day, ignore it if (not start.isDateOnly() or (duration.getWeeks() != 0) or (duration.getDays() > 1)): prop = Property(definitions.cICalProperty_DURATION, duration) self.addProperty(prop)
def testDefaultValueCreate(self): test_data = ( ("ATTENDEE", "mailto:[email protected]", "ATTENDEE:mailto:[email protected]\r\n"), ("ATTENDEE", u"mailto:[email protected]", "ATTENDEE:mailto:[email protected]\r\n"), ("attendee", "mailto:[email protected]", "attendee:mailto:[email protected]\r\n"), ("ORGANIZER", "mailto:[email protected]", "ORGANIZER:mailto:[email protected]\r\n"), ("ORGANizer", "mailto:[email protected]", "ORGANizer:mailto:[email protected]\r\n"), ("URL", "http://example.com/tz1", "URL:http://example.com/tz1\r\n"), ("TZURL", "http://example.com/tz2", "TZURL:http://example.com/tz2\r\n"), ) for propname, propvalue, result in test_data: prop = Property(name=propname, value=propvalue) self.assertEqual(str(prop), result)
def editStatus(self, status): # Remove existing self.removeProperties(definitions.cICalProperty_ALARM_X_ALARMSTATUS) # Updated cached values self.mAlarmStatus = status # Add new status_txt = "" if self.mAlarmStatus == definitions.eAlarm_Status_Pending: status_txt = definitions.cICalProperty_ALARM_X_ALARMSTATUS_PENDING elif self.mAlarmStatus == definitions.eAlarm_Status_Completed: status_txt = definitions.cICalProperty_ALARM_X_ALARMSTATUS_COMPLETED elif self.mAlarmStatus == definitions.eAlarm_Status_Disabled: status_txt = definitions.cICalProperty_ALARM_X_ALARMSTATUS_DISABLED self.addProperty(Property(definitions.cICalProperty_ALARM_X_ALARMSTATUS, status_txt))
def editTriggerBy(self, duration, trigger_start): # Remove existing self.removeProperties(definitions.cICalProperty_TRIGGER) # Updated cached values self.mTriggerAbsolute = False self.mTriggerBy = duration self.mTriggerOnStart = trigger_start # Add new (with parameter) prop = Property(definitions.cICalProperty_TRIGGER, duration) attr = Parameter( definitions.cICalParameter_RELATED, (definitions.cICalParameter_RELATED_START, definitions.cICalParameter_RELATED_END)[not trigger_start]) prop.addParameter(attr) self.addProperty(prop)
def editAction(self, action, data): # Remove existing self.removeProperties(definitions.cICalProperty_ACTION) self.mActionData.remove(self) self.mActionData = None # Updated cached values self.mAction = action self.mActionData = data # Add new properties to alarm action_txt = VAlarm.sActionValueMap.get(self.mAction, definitions.cICalProperty_ACTION_PROCEDURE) prop = Property(definitions.cICalProperty_ACTION, action_txt) self.addProperty(prop) self.mActionData.add(self)
def editTimingDue(self, due): # Updated cached values self.mHasStart = False self.mHasEnd = True self.mDuration = False self.mStart = due self.mEnd = due # Remove existing DUE & DTSTART & DTEND & DURATION items self.removeProperties(definitions.cICalProperty_DUE) self.removeProperties(definitions.cICalProperty_DTSTART) self.removeProperties(definitions.cICalProperty_DTEND) self.removeProperties(definitions.cICalProperty_DURATION) # Now create properties prop = Property(definitions.cICalProperty_DUE, due) self.addProperty(prop)
def testParameterEncodingDecoding(self): prop = Property("X-FOO", "Test") prop.addParameter(Parameter("X-BAR", "\"Check\"")) self.assertEqual(str(prop), "X-FOO;X-BAR=^'Check^':Test\r\n") prop.addParameter(Parameter("X-BAR2", "Check\nThis\tOut\n")) self.assertEqual(str(prop), "X-FOO;X-BAR=^'Check^';X-BAR2=Check^nThis\tOut^n:Test\r\n") data = "X-FOO;X-BAR=^'Check^':Test" prop = Property.parseText(data) self.assertEqual(prop.getParameterValue("X-BAR"), "\"Check\"") data = "X-FOO;X-BAR=^'Check^';X-BAR2=Check^nThis\tOut^n:Test" prop = Property.parseText(data) self.assertEqual(prop.getParameterValue("X-BAR"), "\"Check\"") self.assertEqual(prop.getParameterValue("X-BAR2"), "Check\nThis\tOut\n")