def testParseProperty(self): # Restore BACKSLASH_IN_URI_VALUE after test old_state = ParserContext.BACKSLASH_IN_URI_VALUE self.addCleanup(setattr, ParserContext, "BACKSLASH_IN_URI_VALUE", old_state) # Test with BACKSLASH_IN_URI_VALUE = PARSER_FIX ParserContext.BACKSLASH_IN_URI_VALUE = ParserContext.PARSER_FIX items = ( ("URL:http://example.com", "URL:http://example.com"), ("URL:http://example.com&abd\\,def", "URL:http://example.com&abd,def"), ) for item, result in items: prop = Property.parseText(item) test = prop.getText() self.assertEqual(test, result + "\r\n", "Failed to parse and re-generate '%s'" % (item,)) # Test with BACKSLASH_IN_URI_VALUE = PARSER_ALLOW ParserContext.BACKSLASH_IN_URI_VALUE = ParserContext.PARSER_ALLOW items = ( ("URL:http://example.com", "URL:http://example.com"), ("URL:http://example.com&abd\\,def", "URL:http://example.com&abd\\,def"), ) for item, result in items: prop = Property.parseText(item) test = prop.getText() self.assertEqual(test, result + "\r\n", "Failed to parse and re-generate '%s'" % (item,))
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 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 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 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 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 add(self, valarm): # Delete existing then add self.remove(valarm) prop = Property(definitions.cICalProperty_DESCRIPTION, self.mDescription) 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 setSeq(self, seq): self.mSeq = seq self.removeProperties(definitions.cICalProperty_SEQUENCE) prop = Property(definitions.cICalProperty_SEQUENCE, self.mSeq) self.addProperty(prop)
def add(self, valarm): # Delete existing then add self.remove(valarm) prop = Property(definitions.cICalProperty_ACTION_X_SPEAKTEXT, self.mSpeakText) valarm.addProperty(prop)
def test_positiveIntegerOrZero(self): props = ( ( "SUMMARY:Test", False, ), ( "REPEAT:0", True, ), ( "REPEAT:100", True, ), ( "REPEAT:-1", False, ), ) for prop, result in props: property = Property.parseText(prop) self.assertEqual( PropertyValueChecks.positiveIntegerOrZero(property), result)
def testParseGenerate(self): for data in TestJSONProperty.test_data: prop = Property.parseJSON(data) jobject = [] prop.writeJSON(jobject) self.assertEqual(jobject[0], data, "Failed parse/generate: %s to %s" % (data, jobject[0],))
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")
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 testHash(self): hashes = [] for item in TestProperty.test_data: prop = Property.parseText(item) hashes.append(hash(prop)) hashes.sort() for i in range(1, len(hashes)): self.assertNotEqual(hashes[i - 1], hashes[i])
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 sample(self): if self._allowRecurrence: index = self._helperDistribution.sample() rrule = self._rrules[index] if rrule: prop = Property.parseText(rrule) return prop return None
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 testParseGenerate(self): for data in TestProperty.test_data: prop = Property.parseText(data) propstr = str(prop).replace("\r\n ", "") self.assertEqual( propstr[:-2], data, "Failed parse/generate: %s to %s" % ( data, propstr, ))
def testParseProperty(self): items = ( ("GEO:-12.345;67.890", "GEO:-12.345;67.89"), ("GEO:-12.345\\;67.890", "GEO:-12.345;67.89"), ) for item, result in items: prop = Property.parseText(item) test = prop.getText() self.assertEqual(test, result + "\r\n", "Failed to parse and re-generate '%s'" % (item,))
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 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 testParseGenerate(self): for data in TestJSONProperty.test_data: prop = Property.parseJSON(data) jobject = [] prop.writeJSON(jobject) self.assertEqual( jobject[0], data, "Failed parse/generate: %s to %s" % ( data, jobject[0], ))
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 test_stringValue(self): props = ( ("SUMMARY:Test", "Test", True,), ("SUMMARY:Test", "TEST", True,), ("DTSTART:20110623T174806", "Test", False), ) for prop, test, result in props: property = Property.parseText(prop) self.assertEqual(PropertyValueChecks.stringValue(test, property), result)
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 testParseProperty(self): items = ( ("GEO:-12.345;67.890", "GEO:-12.345;67.89"), ("GEO:-12.345\\;67.890", "GEO:-12.345;67.89"), ) for item, result in items: prop = Property.parseText(item) test = prop.getText() self.assertEqual(test, result + "\r\n", "Failed to parse and re-generate '%s'" % (item, ))
def test_alwaysUTC(self): props = ( ("SUMMARY:Test", False,), ("DTSTART:20110623T174806", False), ("DTSTART;VALUE=DATE:20110623", False), ("DTSTART:20110623T174806Z", True), ) for prop, result in props: property = Property.parseText(prop) self.assertEqual(PropertyValueChecks.alwaysUTC(property), result)
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 test_positiveIntegerOrZero(self): props = ( ("SUMMARY:Test", False,), ("REPEAT:0", True,), ("REPEAT:100", True,), ("REPEAT:-1", False,), ) for prop, result in props: property = Property.parseText(prop) self.assertEqual(PropertyValueChecks.positiveIntegerOrZero(property), result)
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 testParseProperty(self): items = ( "REQUEST-STATUS:2.0;Success", "REQUEST-STATUS:2.0;Success\;here", "REQUEST-STATUS:2.0;Success;Extra", "REQUEST-STATUS:2.0;Success\;here;Extra", "REQUEST-STATUS:2.0;Success;Extra\;here", "REQUEST-STATUS:2.0;Success\;here;Extra\;here too", ) for item in items: req = Property.parseText(item) self.assertEqual(req.getText(), item + "\r\n", "Failed to parse and re-generate '%s'" % (item,))
def test_numericRange(self): props = ( ("SUMMARY:Test", 0, 100, False,), ("PERCENT-COMPLETE:0", 0, 100, True,), ("PERCENT-COMPLETE:100", 0, 100, True,), ("PERCENT-COMPLETE:50", 0, 100, True,), ("PERCENT-COMPLETE:200", 0, 100, False,), ("PERCENT-COMPLETE:-1", 0, 100, False,), ) for prop, low, high, result in props: property = Property.parseText(prop) self.assertEqual(PropertyValueChecks.numericRange(low, high, property), result)
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 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 test_alwaysUTC(self): props = ( ( "SUMMARY:Test", False, ), ("DTSTART:20110623T174806", False), ("DTSTART;VALUE=DATE:20110623", False), ("DTSTART:20110623T174806Z", True), ) for prop, result in props: property = Property.parseText(prop) self.assertEqual(PropertyValueChecks.alwaysUTC(property), 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 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 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 testEquality(self): for data in TestProperty.test_data: prop1 = Property.parseText(data) prop2 = Property.parseText(data) self.assertEqual(prop1, prop2, "Failed equality: %s" % (data,))
import twistedcaldav.customxml import twistedcaldav.timezonexml twistedcaldav # Shhh.. pyflakes # # DefaultHTTPHandler # from txweb2.http_headers import DefaultHTTPHandler, last, singleHeader DefaultHTTPHandler.updateParsers({ "If-Schedule-Tag-Match": (last, str), }) DefaultHTTPHandler.updateGenerators({ "Schedule-Tag": (str, singleHeader), }) # Do some PyCalendar init from pycalendar.icalendar.calendar import Calendar from pycalendar.icalendar.property import Property from pycalendar.vcard.card import Card from pycalendar.value import Value Calendar.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN") Card.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN") # These are properties we use directly and we want the default value type set for TEXT Property.registerDefaultValue("X-CALENDARSERVER-PRIVATE-COMMENT", Value.VALUETYPE_TEXT) Property.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", Value.VALUETYPE_TEXT)
def testGEOValueRoundtrip(self): data = "GEO:123.456;789.101" prop = Property.parseText(data) self.assertEqual(str(prop), data + "\r\n")
def testParseGenerate(self): for data in TestProperty.test_data: prop = Property.parseText(data) propstr = str(prop).replace("\r\n ", "") self.assertEqual(propstr[:-2], data, "Failed parse/generate: %s to %s" % (data, propstr,))
# # DefaultHTTPHandler # from txweb2.http_headers import DefaultHTTPHandler, last, singleHeader DefaultHTTPHandler.updateParsers({ "If-Schedule-Tag-Match": (last, str), }) DefaultHTTPHandler.updateGenerators({ "Schedule-Tag": (str, singleHeader), }) # Do some PyCalendar init from pycalendar.icalendar.calendar import Calendar from pycalendar.icalendar.property import Property from pycalendar.vcard.card import Card from pycalendar.value import Value Calendar.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN") Card.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN") # These are properties we use directly and we want the default value type set for TEXT Property.registerDefaultValue("X-CALENDARSERVER-PRIVATE-COMMENT", Value.VALUETYPE_TEXT) Property.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", Value.VALUETYPE_TEXT) Property.registerDefaultValue("X-APPLE-TRAVEL-DURATION", Value.VALUETYPE_DURATION, always_write_value=True) Property.registerDefaultValue("X-APPLE-TRAVEL-START", Value.VALUETYPE_DATETIME, always_write_value=True) Property.registerDefaultValue("X-APPLE-TRAVEL-RETURN-DURATION", Value.VALUETYPE_DURATION, always_write_value=True) Property.registerDefaultValue("X-APPLE-TRAVEL-RETURN", Value.VALUETYPE_DATETIME, always_write_value=True)