[CalendarServer-changes] [7862] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Aug 9 12:35:22 PDT 2011
Revision: 7862
http://trac.macosforge.org/projects/calendarserver/changeset/7862
Author: cdaboo at apple.com
Date: 2011-08-09 12:35:21 -0700 (Tue, 09 Aug 2011)
Log Message:
-----------
No more vobject dependency.
Modified Paths:
--------------
CalendarServer/trunk/contrib/performance/_event_create.py
CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py
CalendarServer/trunk/contrib/performance/loadtest/ical.py
CalendarServer/trunk/contrib/performance/loadtest/population.py
CalendarServer/trunk/contrib/performance/loadtest/profiles.py
CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py
CalendarServer/trunk/contrib/performance/stats.py
CalendarServer/trunk/contrib/performance/test_stats.py
CalendarServer/trunk/support/build.sh
CalendarServer/trunk/support/patchapply
CalendarServer/trunk/support/patchmaker
CalendarServer/trunk/twistedcaldav/ical.py
Removed Paths:
-------------
CalendarServer/trunk/lib-patches/vobject/
Modified: CalendarServer/trunk/contrib/performance/_event_create.py
===================================================================
--- CalendarServer/trunk/contrib/performance/_event_create.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/_event_create.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -33,7 +33,7 @@
from httpclient import StringProducer
-# XXX Represent these as vobjects? Would make it easier to add more vevents.
+# XXX Represent these as pycalendar objects? Would make it easier to add more vevents.
event = """\
BEGIN:VCALENDAR
VERSION:2.0
@@ -107,7 +107,7 @@
rrule = ""
else:
rrule = recurrence + "\n"
- return event % {
+ cal = event % {
'VEVENTS': vevent % {
'UID': uid,
'START': formatDate(start),
@@ -118,6 +118,7 @@
'RRULE': rrule,
},
}
+ return cal.replace("\n", "\r\n")
def makeEvent(i, organizerSequence, attendeeCount):
Modified: CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -33,7 +33,7 @@
from contrib.performance.httpclient import StringProducer
from contrib.performance.benchlib import initialize, sample
-# XXX Represent these as vobjects? Would make it easier to add more vevents.
+# XXX Represent these as pycalendar objects? Would make it easier to add more vevents.
event = """\
BEGIN:VCALENDAR
VERSION:2.0
@@ -102,7 +102,7 @@
"""
interval = timedelta(hours=2)
duration = timedelta(hours=1)
- return event % {
+ data = event % {
'VEVENTS': s % {
'UID': uuid4(),
'START': formatDate(base + i * interval),
@@ -110,8 +110,8 @@
'SEQUENCE': i,
},
}
+ return data.replace("\n", "\r\n")
-
def makeEvents(base, n):
return [makeEventNear(base, i) for i in range(n)]
@@ -146,13 +146,15 @@
"content-type": ["text/calendar"],
"originator": ["mailto:%s at example.com" % (user,)],
"recipient": ["urn:uuid:%s, urn:uuid:user02" % (user,)]})
- body = StringProducer(VFREEBUSY % {
+
+ vfb = VFREEBUSY % {
"attendees": "".join([
"ATTENDEE:urn:uuid:%s\n" % (user,),
"ATTENDEE:urn:uuid:user02\n"]),
"start": formatDate(baseTime.replace(hour=0, minute=0)) + 'Z',
"end": formatDate(
- baseTime.replace(hour=0, minute=0) + timedelta(days=1)) + 'Z'})
+ baseTime.replace(hour=0, minute=0) + timedelta(days=1)) + 'Z'}
+ body = StringProducer(vfb.replace("\n", "\r\n"))
samples = yield sample(
dtrace, samples,
Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -16,16 +16,15 @@
##
from uuid import uuid4
-from datetime import timedelta, datetime
from urlparse import urlparse, urlunparse
from xml.etree import ElementTree
+from twistedcaldav.ical import Component, Property
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import PyCalendarDateTime
ElementTree.QName.__repr__ = lambda self: '<QName %r>' % (self.text,)
-from vobject import readComponents
-from vobject.base import ContentLine
-from vobject.icalendar import VEvent, dateTimeToString
-
from twisted.python.log import addObserver, err, msg
from twisted.python.filepath import FilePath
from twisted.python.failure import Failure
@@ -98,8 +97,7 @@
Return the UID from the vevent, if there is one.
"""
if self.vevent is not None:
- uid = self.vevent.contents['vevent'][0].contents['uid'][0]
- return uid.value
+ return self.vevent.resourceUID()
return None
@@ -443,7 +441,7 @@
event.etag = etag
if scheduleTag is not None:
event.scheduleTag = scheduleTag
- event.vevent = list(readComponents(body))[0]
+ event.vevent = Component.fromString(body)
self.catalog["eventChanged"].issue(href)
@@ -623,33 +621,33 @@
def _makeSelfAttendee(self):
- attendee = ContentLine(
- name=u'ATTENDEE', params=[
- [u'CN', self.record.commonName],
- [u'CUTYPE', u'INDIVIDUAL'],
- [u'PARTSTAT', u'ACCEPTED'],
- ],
+ attendee = Property(
+ name=u'ATTENDEE',
value=self.uuid,
- encoded=True)
- attendee.parentBehavior = VEvent
+ params={
+ 'CN': self.record.commonName,
+ 'CUTYPE': 'INDIVIDUAL',
+ 'PARTSTAT': 'ACCEPTED',
+ },
+ )
return attendee
def _makeSelfOrganizer(self):
- organizer = ContentLine(
- name=u'ORGANIZER', params=[
- [u'CN', self.record.commonName],
- ],
+ organizer = Property(
+ name=u'ORGANIZER',
value=self.uuid,
- encoded=True)
- organizer.parentBehavior = VEvent
+ params={
+ 'CN': self.record.commonName,
+ },
+ )
return organizer
def addEventAttendee(self, href, attendee):
- name = attendee.params[u'CN'][0].encode('utf-8')
+ name = attendee.parameterValue('CN')
prefix = name[:4].lower()
- email = attendee.params[u'EMAIL'][0].encode('utf-8')
+ email = attendee.parameterValue('EMAIL')
event = self._events[href]
vevent = event.vevent
@@ -683,21 +681,21 @@
def specific(ignored):
# Now learn about the attendee's availability
return self.requestAvailability(
- vevent.contents[u'vevent'][0].contents[u'dtstart'][0].value,
- vevent.contents[u'vevent'][0].contents[u'dtend'][0].value,
+ vevent.mainComponent.getStartDateUTC(),
+ vevent.mainComponent.getEndDateUTC(),
[self.email, u'mailto:' + email],
- [vevent.contents[u'vevent'][0].contents[u'uid'][0].value])
+ [vevent.resourceUID()])
return d
d.addCallback(specific)
def availability(ignored):
# If the event has no attendees, add ourselves as an attendee.
- attendees = vevent.contents[u'vevent'][0].contents.setdefault(u'attendee', [])
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
if len(attendees) == 0:
# First add ourselves as a participant and as the
# organizer. In the future for this event we should
# already have those roles.
- attendees.append(self._makeSelfAttendee())
- vevent.contents[u'vevent'][0].contents[u'organizer'] = [self._makeSelfOrganizer()]
+ vevent.mainComponent().addProperty(self._makeSelfOrganizer())
+ vevent.mainComponent().addProperty(self._makeSelfAttendee())
attendees.append(attendee)
# At last, upload the new event definition
@@ -719,9 +717,8 @@
vevent = event.vevent
# Change the event to have the new attendee instead of the old attendee
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
- attendees.remove(oldAttendee)
- attendees.append(newAttendee)
+ vevent.mainComponent().removeProperty(oldAttendee)
+ vevent.mainComponent().addProperty(newAttendee)
headers = Headers({
'content-type': ['text/calendar'],
})
@@ -730,7 +727,7 @@
d = self._request(
NO_CONTENT, 'PUT', self.root + href[1:].encode('utf-8'),
- headers, StringProducer(vevent.serialize()))
+ headers, StringProducer(vevent.getTextWithTimezones(includeTimezones=True)))
d.addCallback(self._updateEvent, href)
return d
@@ -756,7 +753,7 @@
})
d = self._request(
CREATED, 'PUT', self.root + href[1:].encode('utf-8'),
- headers, StringProducer(vcalendar.serialize()))
+ headers, StringProducer(vcalendar.getTextWithTimezones(includeTimezones=True)))
d.addCallback(self._localUpdateEvent, href, vcalendar)
return d
@@ -824,25 +821,18 @@
for uuid in users]) + '\r\n'
# iCal issues 24 hour wide vfreebusy requests, starting and ending at 4am.
- if start.date() != end.date():
+ if start.compareDate(end):
msg("Availability request spanning multiple days (%r to %r), "
"dropping the end date." % (start, end))
- start = start.replace(hour=0, minute=0, second=0, microsecond=0)
- end = start + timedelta(hours=24)
+ start.setTimezone(PyCalendarTimezone(utc=True))
+ start.setHHMMSS(0, 0, 0)
+ end = start + PyCalendarDuration(hours=24)
- start = dateTimeToString(start, convertToUTC=True)
- end = dateTimeToString(end, convertToUTC=True)
- now = dateTimeToString(datetime.now(), convertToUTC=True)
+ start = start.getText()
+ end = end.getText()
+ now = PyCalendarDateTime.getNowUTC().getText()
- # XXX Why does it not end up UTC sometimes?
- if not start.endswith('Z'):
- start = start + 'Z'
- if not end.endswith('Z'):
- end = end + 'Z'
- if not now.endswith('Z'):
- now = now + 'Z'
-
d = self._request(
OK, 'POST', outbox,
Headers({
Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/population.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -29,6 +29,8 @@
from twisted.python.util import FancyEqMixin
from twisted.python.log import msg, err
+from twistedcaldav.timezones import TimezoneCache
+
from contrib.performance.stats import mean, median, stddev, mad
from contrib.performance.loadtest.trafficlogger import loggedReactor
from contrib.performance.loadtest.logger import SummarizingMixin
@@ -156,6 +158,7 @@
self._user = 0
self._stopped = False
+ TimezoneCache.create()
def getUserRecord(self, index):
return self._records[index]
Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -24,12 +24,6 @@
import sys, random
from uuid import uuid4
-from datetime import datetime, timedelta
-
-from vobject import readComponents
-from vobject.base import Component, ContentLine
-from vobject.icalendar import VEvent
-
from caldavclientlibrary.protocol.caldav.definitions import caldavxml
from twisted.python import context
@@ -39,10 +33,14 @@
from twisted.internet.task import LoopingCall
from twisted.web.http import PRECONDITION_FAILED
+from twistedcaldav.ical import Property, Component
+
from contrib.performance.stats import NearFutureDistribution, NormalDistribution, UniformDiscreteDistribution, mean, median
from contrib.performance.loadtest.logger import SummarizingMixin
from contrib.performance.loadtest.ical import IncorrectResponseCode
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
class ProfileBase(object):
"""
@@ -77,7 +75,7 @@
C{self._client}'s identifiers. Return C{True} if something matches,
C{False} otherwise.
"""
- return attendee.params[u'EMAIL'][0] == self._client.email[len('mailto:'):]
+ return attendee.parameterValue('EMAIL') == self._client.email[len('mailto:'):]
def _newOperation(self, label, deferred):
@@ -158,7 +156,7 @@
selfRecord = self._sim.getUserRecord(self._number)
invitees = set([u'urn:uuid:%s' % (selfRecord.uid,)])
for att in attendees:
- invitees.add(att.value)
+ invitees.add(att.value())
for _ignore_i in range(10):
invitee = max(
@@ -173,19 +171,19 @@
else:
return fail(CannotAddAttendee("Can't find uninvited user to invite."))
- attendee = ContentLine(
- name=u'ATTENDEE', params=[
- [u'CN', record.commonName],
- [u'CUTYPE', u'INDIVIDUAL'],
- [u'EMAIL', record.email],
- [u'PARTSTAT', u'NEEDS-ACTION'],
- [u'ROLE', u'REQ-PARTICIPANT'],
- [u'RSVP', u'TRUE'],
- # [u'SCHEDULE-STATUS', u'1.2'],
- ],
+ attendee = Property(
+ name=u'ATTENDEE',
value=uuid,
- encoded=True)
- attendee.parentBehavior = VEvent
+ params={
+ 'CN': record.commonName,
+ 'CUTYPE': 'INDIVIDUAL',
+ 'EMAIL': record.email,
+ 'PARTSTAT': 'NEEDS-ACTION',
+ 'ROLE': 'REQ-PARTICIPANT',
+ 'RSVP': 'TRUE',
+ #'SCHEDULE-STATUS': '1.2',
+ },
+ )
return succeed(attendee)
@@ -219,8 +217,8 @@
if event is None:
continue
- vevent = event.contents[u'vevent'][0]
- organizer = vevent.contents.get('organizer', [None])[0]
+ vevent = event.mainComponent()
+ organizer = vevent.getOrganizerProperty()
if organizer is not None and not self._isSelfAttendee(organizer):
# This event was organized by someone else, don't try to invite someone to it.
continue
@@ -228,7 +226,7 @@
href = calendar.url + uuid
# Find out who might attend
- attendees = vevent.contents.get('attendee', [])
+ attendees = tuple(vevent.properties('ATTENDEE'))
d = self._addAttendee(event, attendees)
d.addCallbacks(
@@ -287,10 +285,10 @@
vevent = self._client._events[href].vevent
# Check to see if this user is in the attendee list in the
# NEEDS-ACTION PARTSTAT.
- attendees = vevent.contents['vevent'][0].contents.get('attendee', [])
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
for attendee in attendees:
if self._isSelfAttendee(attendee):
- if attendee.params[u'PARTSTAT'][0] == 'NEEDS-ACTION':
+ if attendee.parameterValue('PARTSTAT') == 'NEEDS-ACTION':
delay = self._acceptDelayDistribution.sample()
self._accepting.add(href)
self._reactor.callLater(
@@ -302,7 +300,7 @@
return
vevent = self._client._events[href].vevent
- method = vevent.contents.get('method')[0].value
+ method = vevent.propertyValue('METHOD')
if method == "REPLY":
# Replies are immediately deleted
self._accepting.add(href)
@@ -391,12 +389,9 @@
def _makeAcceptedAttendee(self, attendee):
- accepted = ContentLine.duplicate(attendee)
- accepted.params[u'PARTSTAT'] = [u'ACCEPTED']
- try:
- del accepted.params[u'RSVP']
- except KeyError:
- msg("Duplicated an attendee with no RSVP: %r" % (attendee,))
+ accepted = attendee.duplicate()
+ accepted.setParameter('PARTSTAT', 'ACCEPTED')
+ accepted.removeParameter('RSVP')
return accepted
@@ -405,28 +400,11 @@
"""
A Calendar user who creates new events.
"""
- _eventTemplate = list(readComponents("""\
+ _eventTemplate = Component.fromString("""\
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//iCal 4.0.3//EN
CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:America/New_York
-BEGIN:DAYLIGHT
-TZOFFSETFROM:-0500
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-DTSTART:20070311T020000
-TZNAME:EDT
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-TZOFFSETFROM:-0400
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-DTSTART:20071104T020000
-TZNAME:EST
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
BEGIN:VEVENT
CREATED:20101018T155431Z
UID:C98AD237-55AD-4F7D-9009-0D355D835822
@@ -438,7 +416,7 @@
SEQUENCE:2
END:VEVENT
END:VCALENDAR
-"""))[0]
+""".replace("\n", "\r\n"))
def setParameters(
self,
@@ -472,20 +450,18 @@
# Copy the template event and fill in some of its fields
# to make a new event to create on the calendar.
- vcalendar = Component.duplicate(self._eventTemplate)
- vevent = vcalendar.contents[u'vevent'][0]
- tz = vevent.contents[u'created'][0].value.tzinfo
- dtstamp = datetime.now(tz)
- dtstart = datetime.fromtimestamp(self._eventStartDistribution.sample(), tz)
- dtend = dtstart + timedelta(seconds=self._eventDurationDistribution.sample())
- vevent.contents[u'created'][0].value = dtstamp
- vevent.contents[u'dtstamp'][0].value = dtstamp
- vevent.contents[u'dtstart'][0].value = dtstart
- vevent.contents[u'dtend'][0].value = dtend
- vevent.contents[u'uid'][0].value = unicode(uuid4())
+ vcalendar = self._eventTemplate.duplicate()
+ vevent = vcalendar.mainComponent()
+ uid = str(uuid4())
+ dtstart = self._eventStartDistribution.sample()
+ dtend = dtstart + PyCalendarDuration(seconds=self._eventDurationDistribution.sample())
+ vevent.replaceProperty(Property("CREATED", PyCalendarDateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTART", dtstart))
+ vevent.replaceProperty(Property("DTEND", dtend))
+ vevent.replaceProperty(Property("UID", uid))
- href = '%s%s.ics' % (
- calendar.url, vevent.contents[u'uid'][0].value)
+ href = '%s%s.ics' % (calendar.url, uid)
d = self._client.addEvent(href, vcalendar)
return self._newOperation("create", d)
Modified: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_ical.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_ical.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -15,12 +15,6 @@
#
##
-from datetime import datetime
-
-from vobject import readComponents
-from vobject.base import Component, ContentLine
-from vobject.icalendar import dateTimeToString
-
from twisted.python.failure import Failure
from twisted.internet.defer import Deferred
from twisted.trial.unittest import TestCase
@@ -37,6 +31,10 @@
from contrib.performance.loadtest.ical import XMPPPush, Event, Calendar, SnowLeopard
from contrib.performance.loadtest.sim import _DirectoryRecord
from contrib.performance.httpclient import MemoryConsumer, StringProducer
+from twistedcaldav.ical import Component
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
+from twistedcaldav.timezones import TimezoneCache
EVENT_UID = 'D94F247D-7433-43AF-B84B-ADD684D023B0'
@@ -45,23 +43,6 @@
VERSION:2.0
PRODID:-//Apple Inc.//iCal 4.0.3//EN
CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:America/New_York
-BEGIN:DAYLIGHT
-TZOFFSETFROM:-0500
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-DTSTART:20070311T020000
-TZNAME:EDT
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-TZOFFSETFROM:-0400
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-DTSTART:20071104T020000
-TZNAME:EST
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
BEGIN:VEVENT
CREATED:20101018T155454Z
UID:%(UID)s
@@ -79,9 +60,176 @@
SEQUENCE:3
END:VEVENT
END:VCALENDAR
-""" % {'UID': EVENT_UID}
+""".replace("\n", "\r\n") % {'UID': EVENT_UID}
+EVENT_AND_TIMEZONE = """\
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:America/New_York
+X-LIC-LOCATION:America/New_York
+BEGIN:STANDARD
+DTSTART:18831118T120358
+RDATE:18831118T120358
+TZNAME:EST
+TZOFFSETFROM:-045602
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19180331T020000
+RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19181027T020000
+RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:STANDARD
+DTSTART:19200101T000000
+RDATE:19200101T000000
+RDATE:19420101T000000
+RDATE:19460101T000000
+RDATE:19670101T000000
+TZNAME:EST
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19200328T020000
+RDATE:19200328T020000
+RDATE:19740106T020000
+RDATE:19750223T020000
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19201031T020000
+RDATE:19201031T020000
+RDATE:19450930T020000
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19210424T020000
+RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19210925T020000
+RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19420209T020000
+RDATE:19420209T020000
+TZNAME:EWT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+DTSTART:19450814T190000
+RDATE:19450814T190000
+TZNAME:EPT
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+DTSTART:19460428T020000
+RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19460929T020000
+RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:STANDARD
+DTSTART:19551030T020000
+RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19670430T020000
+RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19671029T020000
+RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:19760425T020000
+RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+DTSTART:19870405T020000
+RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20101018T155454Z
+UID:%(UID)s
+DTEND;TZID=America/New_York:20101028T130000
+ATTENDEE;CN="User 03";CUTYPE=INDIVIDUAL;EMAIL="user03 at example.com";PARTS
+ TAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user03 at example.co
+ m
+ATTENDEE;CN="User 01";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:user01@
+ example.com
+TRANSP:OPAQUE
+SUMMARY:Attended Event
+DTSTART;TZID=America/New_York:20101028T120000
+DTSTAMP:20101018T155513Z
+ORGANIZER;CN="User 01":mailto:user01 at example.com
+SEQUENCE:3
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {'UID': EVENT_UID}
+
class EventTests(TestCase):
"""
Tests for L{Event}.
@@ -91,7 +239,7 @@
When the C{vevent} attribute of an L{Event} instance is set,
L{Event.getUID} returns the UID value from it.
"""
- event = Event(u'/foo/bar', u'etag', list(readComponents(EVENT))[0])
+ event = Event(u'/foo/bar', u'etag', Component.fromString(EVENT))
self.assertEquals(event.getUID(), EVENT_UID)
@@ -834,6 +982,7 @@
Mixin for L{TestCase}s for L{SnowLeopard}.
"""
def setUp(self):
+ TimezoneCache.create()
self.record = _DirectoryRecord(
u"user91", u"user91", u"User 91", u"user91 at example.org")
self.client = SnowLeopard(None, "http://127.0.0.1/", self.record, None)
@@ -962,11 +1111,11 @@
"""
requests = self.interceptRequests()
- vevent = list(readComponents(EVENT))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ vevent = Component.fromString(EVENT)
+ attendees = tuple(vevent.mainComponent().properties("ATTENDEE"))
old = attendees[0]
- new = ContentLine.duplicate(old)
- new.params[u'CN'] = [u'Some Other Guy']
+ new = old.duplicate()
+ new.setParameter('CN', 'Some Other Guy')
event = Event(u'/some/calendar/1234.ics', None, vevent)
self.client._events[event.url] = event
self.client.changeEventAttendee(event.url, old, new)
@@ -983,11 +1132,11 @@
consumer = MemoryConsumer()
finished = body.startProducing(consumer)
def cbFinished(ignored):
- vevent = list(readComponents(consumer.value()))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ vevent = Component.fromString(consumer.value())
+ attendees = tuple(vevent.mainComponent().properties("ATTENDEE"))
self.assertEquals(len(attendees), 2)
- self.assertEquals(attendees[0].params[u'CN'], [u'User 01'])
- self.assertEquals(attendees[1].params[u'CN'], [u'Some Other Guy'])
+ self.assertEquals(attendees[0].parameterValue('CN'), 'User 01')
+ self.assertEquals(attendees[1].parameterValue('CN'), 'Some Other Guy')
finished.addCallback(cbFinished)
return finished
@@ -1002,7 +1151,7 @@
calendar = Calendar(caldavxml.calendar, u'calendar', u'/mumble/', None)
self.client._calendars[calendar.url] = calendar
- vcalendar = list(readComponents(EVENT))[0]
+ vcalendar = Component.fromString(EVENT)
d = self.client.addEvent(u'/mumble/frotz.ics', vcalendar)
result, req = requests.pop(0)
@@ -1018,9 +1167,9 @@
consumer = MemoryConsumer()
finished = body.startProducing(consumer)
def cbFinished(ignored):
- self.assertComponentsEqual(
- list(readComponents(consumer.value()))[0],
- vcalendar)
+ self.assertEqual(
+ Component.fromString(consumer.value()),
+ Component.fromString(EVENT_AND_TIMEZONE))
finished.addCallback(cbFinished)
def requested(ignored):
@@ -1067,39 +1216,6 @@
return d
- def assertComponentsEqual(self, first, second):
- self.assertEquals(first.name, second.name, "Component names not equal")
- self.assertEquals(first.behavior, second.behavior, "Component behaviors not equal")
-
- for k in first.contents:
- if k not in second.contents:
- self.fail("Content %r present in first but not second" % (k,))
- self.assertEquals(
- len(first.contents[k]), len(second.contents[k]), "Different length content %r" % (k,))
- for (a, b) in zip(first.contents[k], second.contents[k]):
- if isinstance(a, ContentLine):
- f = self.assertContentLinesEqual
- elif isinstance(a, Component):
- f = self.assertComponentsEqual
- else:
- f = self.assertEquals
- f(a, b)
- for k in second.contents:
- if k not in first.contents:
- self.fail("Content %r present in second but not first" % (k,))
-
-
- def assertContentLinesEqual(self, first, second):
- self.assertEquals(first.name, second.name, "ContentLine names not equal")
- self.assertEquals(first.behavior, second.behavior, "ContentLine behaviors not equal")
- self.assertEquals(first.value, second.value, "ContentLine values not equal")
- self.assertEquals(first.params, second.params, "ContentLine params not equal")
- self.assertEquals(
- first.singletonparams, second.singletonparams,
- "ContentLine singletonparams not equal")
-
-
-
class UpdateCalendarTests(SnowLeopardMixin, TestCase):
"""
Tests for L{SnowLeopard._updateCalendar}.
@@ -1336,8 +1452,8 @@
self.client.email = u'mailto:user01 at example.com'
requests = self.interceptRequests()
- start = datetime(2011, 6, 10, 10, 45, 0)
- end = datetime(2011, 6, 10, 11, 15, 0)
+ start = PyCalendarDateTime(2011, 6, 10, 10, 45, 0, tzid=PyCalendarTimezone(utc=True))
+ end = PyCalendarDateTime(2011, 6, 10, 11, 15, 0, tzid=PyCalendarTimezone(utc=True))
d = self.client.requestAvailability(
start, end, [u"urn:uuid:user05", u"urn:uuid:user10"])
@@ -1357,10 +1473,10 @@
consumer = MemoryConsumer()
finished = body.startProducing(consumer)
def cbFinished(ignored):
- vevent = list(readComponents(consumer.value()))[0]
- uid = vevent.contents[u'vfreebusy'][0].contents[u'uid'][0].value.encode('utf-8')
- dtstamp = vevent.contents[u'vfreebusy'][0].contents[u'dtstamp'][0].value
- dtstamp = dateTimeToString(dtstamp, False)
+ vevent = Component.fromString(consumer.value())
+ uid = vevent.resourceUID()
+ dtstamp = vevent.mainComponent().propertyValue("DTSTAMP")
+ dtstamp = dtstamp.getText()
self.assertEqual(
"""\
BEGIN:VCALENDAR
Modified: CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -21,8 +21,6 @@
from StringIO import StringIO
-from vobject import readComponents
-
from caldavclientlibrary.protocol.caldav.definitions import caldavxml, csxml
from twisted.trial.unittest import TestCase
@@ -31,6 +29,8 @@
from twisted.web.http import NO_CONTENT, PRECONDITION_FAILED
from twisted.web.client import Response
+from twistedcaldav.ical import Component
+
from contrib.performance.loadtest.profiles import Eventer, Inviter, Accepter, OperationLogger
from contrib.performance.loadtest.population import Populator, CalendarClientSimulator
from contrib.performance.loadtest.ical import IncorrectResponseCode, Calendar, Event, BaseClient
@@ -225,8 +225,7 @@
def addEventAttendee(self, href, attendee):
vevent = self._events[href].vevent
- attendees = vevent.contents[u'vevent'][0].contents.setdefault(u'attendee', [])
- attendees.append(attendee)
+ vevent.mainComponent().addProperty(attendee)
def changeEventAttendee(self, href, old, new):
@@ -238,9 +237,8 @@
'Precondition Failed', None, None)))
vevent = self._events[href].vevent
- attendees = vevent.contents[u'vevent'][0].contents.setdefault(u'attendee', [])
- attendees.remove(old)
- attendees.append(new)
+ vevent.mainComponent().removeProperty(old)
+ vevent.mainComponent().addProperty(new)
return succeed(None)
@@ -265,7 +263,7 @@
def _simpleAccount(self, userNumber, eventText):
- vevent = list(readComponents(eventText))[0]
+ vevent = Component.fromString(eventText)
calendar = Calendar(
caldavxml.calendar, u'calendar', u'/cal/', None)
event = Event(calendar.url + u'1234.ics', None, vevent)
@@ -293,12 +291,12 @@
attempt is made to add attendees to an event on that calendar.
"""
userNumber = 10
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, calendar, client = self._simpleAccount(
userNumber, SIMPLE_EVENT)
calendar.resourceType = caldavxml.schedule_inbox
inviter = Inviter(None, self.sim, client, userNumber)
inviter._invite()
- self.assertNotIn(u'attendee', vevent.contents[u'vevent'][0].contents)
+ self.assertFalse(vevent.mainComponent().hasProperty('ATTENDEE'))
def test_doNotAddAttendeeToNoCalendars(self):
@@ -321,7 +319,7 @@
invitees to that event.
"""
userNumber = 19
- vevent, event, calendar, client = self._simpleAccount(
+ _ignore_vevent, event, calendar, client = self._simpleAccount(
userNumber, SIMPLE_EVENT)
event.vevent = event.etag = event.scheduleTag = None
inviter = Inviter(None, self.sim, client, userNumber)
@@ -336,20 +334,23 @@
attendee to it.
"""
userNumber = 16
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
userNumber, SIMPLE_EVENT)
inviter = Inviter(Clock(), self.sim, client, userNumber)
inviter.setParameters(inviteeDistanceDistribution=Deterministic(1))
inviter._invite()
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 1)
- self.assertEquals(attendees[0].params, {
- u'CN': [u'User %d' % (userNumber + 1,)],
- u'CUTYPE': [u'INDIVIDUAL'],
- u'EMAIL': [u'user%d at example.com' % (userNumber + 1,)],
- u'PARTSTAT': [u'NEEDS-ACTION'],
- u'ROLE': [u'REQ-PARTICIPANT'],
- u'RSVP': [u'TRUE']})
+ for paramname, paramvalue in {
+ 'CN': 'User %d' % (userNumber + 1,),
+ 'CUTYPE': 'INDIVIDUAL',
+ 'EMAIL': 'user%d at example.com' % (userNumber + 1,),
+ 'PARTSTAT': 'NEEDS-ACTION',
+ 'ROLE': 'REQ-PARTICIPANT',
+ 'RSVP': 'TRUE'
+ }.items():
+ self.assertTrue(attendees[0].hasParameter(paramname))
+ self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
@@ -359,7 +360,7 @@
the attendee list, a different user is added instead.
"""
selfNumber = 12
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
selfNumber, SIMPLE_EVENT)
otherNumber = 20
@@ -368,15 +369,18 @@
inviter = Inviter(Clock(), self.sim, client, selfNumber)
inviter.setParameters(inviteeDistanceDistribution=SequentialDistribution(values))
inviter._invite()
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 1)
- self.assertEquals(attendees[0].params, {
- u'CN': [u'User %d' % (otherNumber,)],
- u'CUTYPE': [u'INDIVIDUAL'],
- u'EMAIL': [u'user%d at example.com' % (otherNumber,)],
- u'PARTSTAT': [u'NEEDS-ACTION'],
- u'ROLE': [u'REQ-PARTICIPANT'],
- u'RSVP': [u'TRUE']})
+ for paramname, paramvalue in {
+ 'CN': 'User %d' % (otherNumber,),
+ 'CUTYPE': 'INDIVIDUAL',
+ 'EMAIL': 'user%d at example.com' % (otherNumber,),
+ 'PARTSTAT': 'NEEDS-ACTION',
+ 'ROLE': 'REQ-PARTICIPANT',
+ 'RSVP': 'TRUE'
+ }.items():
+ self.assertTrue(attendees[0].hasParameter(paramname))
+ self.assertEqual(attendees[0].parameterValue(paramname), paramvalue)
@@ -386,26 +390,29 @@
invitee on the event, a different user is added instead.
"""
selfNumber = 1
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
selfNumber, INVITED_EVENT)
- invitee = vevent.contents[u'vevent'][0].contents[u'attendee'][0]
- inviteeNumber = int(invitee.params[u'CN'][0].split()[1])
+ invitee = tuple(vevent.mainComponent().properties('ATTENDEE'))[0]
+ inviteeNumber = int(invitee.parameterValue('CN').split()[1])
anotherNumber = inviteeNumber + 5
values = [inviteeNumber - selfNumber, anotherNumber - selfNumber]
inviter = Inviter(Clock(), self.sim, client, selfNumber)
inviter.setParameters(inviteeDistanceDistribution=SequentialDistribution(values))
inviter._invite()
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 3)
- self.assertEquals(attendees[2].params, {
- u'CN': [u'User %02d' % (anotherNumber,)],
- u'CUTYPE': [u'INDIVIDUAL'],
- u'EMAIL': [u'user%02d at example.com' % (anotherNumber,)],
- u'PARTSTAT': [u'NEEDS-ACTION'],
- u'ROLE': [u'REQ-PARTICIPANT'],
- u'RSVP': [u'TRUE']})
+ for paramname, paramvalue in {
+ 'CN': 'User %02d' % (anotherNumber,),
+ 'CUTYPE': 'INDIVIDUAL',
+ 'EMAIL': 'user%02d at example.com' % (anotherNumber,),
+ 'PARTSTAT': 'NEEDS-ACTION',
+ 'ROLE': 'REQ-PARTICIPANT',
+ 'RSVP': 'TRUE'
+ }.items():
+ self.assertTrue(attendees[2].hasParameter(paramname))
+ self.assertEqual(attendees[2].parameterValue(paramname), paramvalue)
def test_everybodyInvitedAlready(self):
@@ -415,13 +422,13 @@
abandoned.
"""
selfNumber = 1
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
selfNumber, INVITED_EVENT)
inviter = Inviter(Clock(), self.sim, client, selfNumber)
# Always return a user number which has already been invited.
inviter.setParameters(inviteeDistanceDistribution=Deterministic(2 - selfNumber))
inviter._invite()
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 2)
@@ -432,17 +439,17 @@
users to them.
"""
selfNumber = 2
- vevent, event, calendar, client = self._simpleAccount(
+ vevent, _ignore_event, _ignore_calendar, client = self._simpleAccount(
selfNumber, INVITED_EVENT)
inviter = Inviter(None, self.sim, client, selfNumber)
# Try to send an invitation, but with only one event on the
# calendar, of which we are not the organizer. It should be
# unchanged afterwards.
inviter._invite()
- attendees = event.vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEqual(len(attendees), 2)
- self.assertEqual(attendees[0].params['CN'], [u'User 01'])
- self.assertEqual(attendees[1].params['CN'], [u'User 02'])
+ self.assertEqual(attendees[0].parameterValue('CN'), 'User 01')
+ self.assertEqual(attendees[1].parameterValue('CN'), 'User 02')
@@ -495,9 +502,9 @@
If the client is an attendee on an event but the PARTSTAT is
not NEEDS-ACTION, the event is ignored.
"""
- vevent = list(readComponents(ACCEPTED_EVENT))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
- userNumber = int(attendees[1].params[u'CN'][0].split(None, 1)[1])
+ vevent = Component.fromString(ACCEPTED_EVENT)
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+ userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1])
calendarURL = '/some/calendar/'
calendar = Calendar(
caldavxml.calendar, u'calendar', calendarURL, None)
@@ -518,9 +525,9 @@
"""
clock = Clock()
randomDelay = 7
- vevent = list(readComponents(INVITED_EVENT))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
- userNumber = int(attendees[1].params[u'CN'][0].split(None, 1)[1])
+ vevent = Component.fromString(INVITED_EVENT)
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+ userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1])
calendarURL = '/some/calendar/'
calendar = Calendar(
caldavxml.calendar, u'calendar', calendarURL, None)
@@ -545,9 +552,9 @@
"""
clock = Clock()
randomDelay = 7
- vevent = list(readComponents(INVITED_EVENT))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
- userNumber = int(attendees[1].params[u'CN'][0].split(None, 1)[1])
+ vevent = Component.fromString(INVITED_EVENT)
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+ userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1])
client = StubClient(userNumber)
calendarURL = '/some/calendar/'
@@ -572,13 +579,13 @@
clock.advance(randomDelay)
vevent = client._events[event.url].vevent
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 2)
self.assertEquals(
- attendees[1].params[u'CN'], [u'User %02d' % (userNumber,)])
+ attendees[1].parameterValue('CN'), 'User %02d' % (userNumber,))
self.assertEquals(
- attendees[1].params[u'PARTSTAT'], [u'ACCEPTED'])
- self.assertNotIn(u'RSVP', attendees[1].params)
+ attendees[1].parameterValue('PARTSTAT'), 'ACCEPTED')
+ self.assertFalse(attendees[1].hasParameter('RSVP'))
self.assertNotIn(inboxEvent.url, client._events)
self.assertNotIn('4321.ics', inbox.events)
@@ -592,9 +599,9 @@
"""
clock = Clock()
randomDelay = 7
- vevent = list(readComponents(INVITED_EVENT))[0]
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
- userNumber = int(attendees[1].params[u'CN'][0].split(None, 1)[1])
+ vevent = Component.fromString(INVITED_EVENT)
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
+ userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1])
calendarURL = '/some/calendar/'
calendar = Calendar(
caldavxml.calendar, u'calendar', calendarURL, None)
@@ -608,7 +615,7 @@
clock.advance(randomDelay)
# Now re-set the event so it has to be accepted again
- event.vevent = list(readComponents(INVITED_EVENT))[0]
+ event.vevent = Component.fromString(INVITED_EVENT)
# And now re-deliver it
accepter.eventChanged(event.url)
@@ -616,13 +623,13 @@
# And ensure that it was accepted again
vevent = client._events[event.url].vevent
- attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
+ attendees = tuple(vevent.mainComponent().properties('ATTENDEE'))
self.assertEquals(len(attendees), 2)
self.assertEquals(
- attendees[1].params[u'CN'], [u'User %02d' % (userNumber,)])
+ attendees[1].parameterValue('CN'), 'User %02d' % (userNumber,))
self.assertEquals(
- attendees[1].params[u'PARTSTAT'], [u'ACCEPTED'])
- self.assertNotIn(u'RSVP', attendees[1].params)
+ attendees[1].parameterValue('PARTSTAT'), 'ACCEPTED')
+ self.assertFalse(attendees[1].hasParameter('RSVP'))
def test_changeEventAttendeePreconditionFailed(self):
@@ -641,7 +648,7 @@
caldavxml.calendar, u'calendar', calendarURL, None)
client._calendars[calendarURL] = calendar
- vevent = list(readComponents(INVITED_EVENT))[0]
+ vevent = Component.fromString(INVITED_EVENT)
event = Event(calendarURL + u'1234.ics', None, vevent)
client._setEvent(event.url, event)
@@ -754,7 +761,7 @@
describing that issue.
"""
logger = OperationLogger(outfile=StringIO())
- for i in range(98):
+ for _ignore in range(98):
logger.observe(dict(
type='operation', phase='end', user='user01',
duration=0.25, label='testing', success=True))
Modified: CalendarServer/trunk/contrib/performance/stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/stats.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/stats.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,15 +14,16 @@
# limitations under the License.
##
-import random, time, datetime
+import random, time
-import pytz
-
from zope.interface import Interface, implements
from twisted.python.util import FancyEqMixin
import sqlparse
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.timezone import PyCalendarTimezone
NANO = 1000000000.0
@@ -275,7 +276,9 @@
def sample(self):
- return time.time() + self._offset.sample()
+ now = PyCalendarDateTime.getNowUTC()
+ now.offsetSeconds(int(self._offset.sample()))
+ return now
@@ -313,20 +316,19 @@
class WorkDistribution(object, FancyEqMixin):
compareAttributes = ["_daysOfWeek", "_beginHour", "_endHour"]
- _weekdayNames = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
+ _weekdayNames = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"]
- now = staticmethod(datetime.datetime.now)
-
def __init__(self, daysOfWeek=["mon", "tue", "wed", "thu", "fri"], beginHour=8, endHour=17, tzname="UTC"):
self._daysOfWeek = [self._weekdayNames.index(day) for day in daysOfWeek]
self._beginHour = beginHour
self._endHour = endHour
- self._tzinfo = pytz.timezone(tzname)
+ self._tzname = tzname
self._helperDistribution = NormalDistribution(
# Mean 6 workdays in the future
60 * 60 * 8 * 6,
# Standard deviation of 4 workdays
60 * 60 * 8 * 4)
+ self.now = PyCalendarDateTime.getNow
def astimestamp(self, dt):
@@ -340,29 +342,29 @@
be equal to when.
"""
# Find a workday that follows the timestamp
- weekday = when.weekday()
+ weekday = when.getDayOfWeek()
for i in range(NUM_WEEKDAYS):
- day = when + datetime.timedelta(days=i)
+ day = when + PyCalendarDuration(days=i)
if (weekday + i) % NUM_WEEKDAYS in self._daysOfWeek:
# Joy, a day on which work might occur. Find the first hour on
# this day when work may start.
- begin = day.replace(
- hour=self._beginHour, minute=0, second=0, microsecond=0)
- end = begin.replace(hour=self._endHour)
+ day.setHHMMSS(self._beginHour, 0, 0)
+ begin = day
+ end = begin.duplicate()
+ end.setHHMMSS(self._endHour, 0, 0)
if end > when:
return begin, end
def sample(self):
- offset = datetime.timedelta(seconds=self._helperDistribution.sample())
- beginning = self.now(self._tzinfo)
+ offset = PyCalendarDuration(seconds=int(self._helperDistribution.sample()))
+ beginning = self.now(PyCalendarTimezone(tzid=self._tzname))
while offset:
start, end = self._findWorkAfter(beginning)
if end - start > offset:
result = start + offset
- return self.astimestamp(
- result.replace(
- minute=result.minute // 15 * 15,
- second=0, microsecond=0))
- offset -= (end - start)
+ result.setMinutes(result.getMinutes() // 15 * 15)
+ result.setSeconds(0)
+ return result
+ offset.setDuration(offset.getTotalSeconds() - (end - start).getTotalSeconds())
beginning = end
Modified: CalendarServer/trunk/contrib/performance/test_stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/test_stats.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/contrib/performance/test_stats.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -14,14 +14,13 @@
# limitations under the License.
##
-import pytz
-from datetime import datetime
-
from twisted.trial.unittest import TestCase
from stats import (
SQLDuration, LogNormalDistribution, UniformDiscreteDistribution,
UniformIntegerDistribution, WorkDistribution, quantize)
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
class SQLDurationTests(TestCase):
def setUp(self):
@@ -50,7 +49,7 @@
class DistributionTests(TestCase):
def test_lognormal(self):
dist = LogNormalDistribution(1, 1)
- for i in range(100):
+ for _ignore_i in range(100):
value = dist.sample()
self.assertIsInstance(value, float)
self.assertTrue(value >= 0.0, "negative value %r" % (value,))
@@ -61,35 +60,40 @@
population = [1, 5, 6, 9]
counts = dict.fromkeys(population, 0)
dist = UniformDiscreteDistribution(population)
- for i in range(len(population) * 10):
+ for _ignore_i in range(len(population) * 10):
counts[dist.sample()] += 1
self.assertEqual(dict.fromkeys(population, 10), counts)
def test_workdistribution(self):
tzname = "US/Eastern"
- tzinfo = pytz.timezone(tzname)
dist = WorkDistribution(["mon", "wed", "thu", "sat"], 10, 20, tzname)
dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
- dist.now = lambda tz=None: datetime(2011, 5, 29, 18, 5, 36, tzinfo=tz)
+ dist.now = lambda tzname=None: PyCalendarDateTime(2011, 5, 29, 18, 5, 36, tzid=tzname)
value = dist.sample()
self.assertEqual(
# Move past three workdays - monday, wednesday, thursday - using 30
# of the hours, and then five and a half hours into the fourth
# workday, saturday. Workday starts at 10am, so the sample value
# is 3:30pm, ie 1530 hours.
- datetime(2011, 6, 4, 15, 30, 0, tzinfo=tzinfo),
- datetime.fromtimestamp(value, tzinfo))
+ PyCalendarDateTime(2011, 6, 4, 15, 30, 0, tzid=PyCalendarTimezone(tzname)),
+ value
+ )
+ dist = WorkDistribution(["mon", "tue", "wed", "thu", "fri"], 10, 20, tzname)
+ dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
+ value = dist.sample()
+ self.assertTrue(isinstance(value, PyCalendarDateTime))
+
# twisted.trial.unittest.FailTest: not equal:
# a = datetime.datetime(2011, 6, 4, 15, 30, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
# b = datetime.datetime(2011, 6, 4, 19, 30, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
- test_workdistribution.todo = "Somehow timezones mess this up"
+ #test_workdistribution.todo = "Somehow timezones mess this up"
def test_uniform(self):
dist = UniformIntegerDistribution(-5, 10)
- for i in range(100):
+ for _ignore_i in range(100):
value = dist.sample()
self.assertTrue(-5 <= value < 10)
self.assertIsInstance(value, int)
Modified: CalendarServer/trunk/support/build.sh
===================================================================
--- CalendarServer/trunk/support/build.sh 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/support/build.sh 2011-08-09 19:35:21 UTC (rev 7862)
@@ -418,7 +418,7 @@
local inplace=""; # Do development in-place; don't run setup.py to
# build, and instead add the source directory plus the
# given relative path directly to sys.path. twisted
- # and vobject are developed often enough that this is
+ # and pycalendar are developed often enough that this is
# convenient.
local skip_egg="false"; # Skip even the 'egg_info' step, because nothing needs
# to be built.
@@ -717,13 +717,8 @@
"python-ldap" "ldap" "${ld}" \
"${pypi}/p/python-ldap/${ld}.tar.gz";
- # XXX actually vObject should be imported in-place.
- py_dependency -fe -i "" -r 219 \
- "vobject" "vobject" "vobject" \
- "http://svn.osafoundation.org/vobject/trunk";
-
# XXX actually PyCalendar should be imported in-place.
- py_dependency -fe -i "src" -r 169 \
+ py_dependency -fe -i "src" -r 171 \
"pycalendar" "pycalendar" "pycalendar" \
"http://svn.mulberrymail.com/repos/PyCalendar/branches/server";
Modified: CalendarServer/trunk/support/patchapply
===================================================================
--- CalendarServer/trunk/support/patchapply 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/support/patchapply 2011-08-09 19:35:21 UTC (rev 7862)
@@ -23,8 +23,8 @@
# Apply patches to dependent projects.
#
-#projects = ("Twisted", "vobject", "dateutil", "xattr")
-projects = ("vobject",)
+#projects = ("Twisted", "dateutil", "xattr")
+projects = ()
cwd = os.getcwd()
libpatches = os.path.join(cwd, "lib-patches")
Modified: CalendarServer/trunk/support/patchmaker
===================================================================
--- CalendarServer/trunk/support/patchmaker 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/support/patchmaker 2011-08-09 19:35:21 UTC (rev 7862)
@@ -23,8 +23,8 @@
# Create a new set of patch files for dependent projects.
#
-#projects = ("Twisted", "vobject", "dateutil", "xattr")
-projects = ("vobject",)
+#projects = ("Twisted", "dateutil", "xattr")
+projects = ()
cwd = os.getcwd()
libpatches = os.path.join(cwd, "lib-patches")
Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py 2011-08-09 02:30:51 UTC (rev 7861)
+++ CalendarServer/trunk/twistedcaldav/ical.py 2011-08-09 19:35:21 UTC (rev 7862)
@@ -195,6 +195,13 @@
def __ge__(self, other): return self.__eq__(other) or self.__gt__(other)
def __le__(self, other): return self.__eq__(other) or self.__lt__(other)
+ def duplicate(self):
+ """
+ Duplicate this object and all its contents.
+ @return: the duplicated calendar.
+ """
+ return Property(None, None, None, pycalendar=self._pycalendar.duplicate())
+
def name (self): return self._pycalendar.getName()
def value (self): return self._pycalendar.getValue().getValue()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110809/9f3ebe23/attachment-0001.html>
More information about the calendarserver-changes
mailing list