[CalendarServer-changes] [14669] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Thu Apr 9 09:57:35 PDT 2015
Revision: 14669
http://trac.calendarserver.org//changeset/14669
Author: cdaboo at apple.com
Date: 2015-04-09 09:57:35 -0700 (Thu, 09 Apr 2015)
Log Message:
-----------
Support timezone-id properties for timezones-by-reference.
Modified Paths:
--------------
CalendarServer/trunk/requirements-dev.txt
CalendarServer/trunk/twistedcaldav/caldavxml.py
CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/storebridge.py
CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py
Modified: CalendarServer/trunk/requirements-dev.txt
===================================================================
--- CalendarServer/trunk/requirements-dev.txt 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/requirements-dev.txt 2015-04-09 16:57:35 UTC (rev 14669)
@@ -8,4 +8,4 @@
q
tl.eggdeps
--editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk@13420#egg=CalDAVClientLibrary
---editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14659#egg=CalDAVTester
+--editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14668#egg=CalDAVTester
Modified: CalendarServer/trunk/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/caldavxml.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/twistedcaldav/caldavxml.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -212,6 +212,7 @@
"""
Returns the calendar data derived from this element.
"""
+ data = None
for data in self.children:
if not isinstance(data, PCDATAElement):
return None
@@ -318,6 +319,17 @@
@registerElement
+class CalendarTimeZoneID (CalDAVTextElement):
+ """
+ Specifies a time zone id on a calendar collection.
+ (draft-ietf-tzdist-caldav-timezone-ref-01, Section-5.2)
+ """
+ name = "calendar-timezone-id"
+ hidden = True
+
+
+
+ at registerElement
class SupportedCalendarComponentSets (CalDAVElement):
"""
Indicates what set of calendar components the server is willing to allow
@@ -469,6 +481,7 @@
(dav_namespace, "propname"): (0, None),
(dav_namespace, "prop"): (0, None),
(caldav_namespace, "timezone"): (0, 1),
+ (caldav_namespace, "timezone-id"): (0, 1),
(caldav_namespace, "filter"): (0, 1), # Actually (1, 1) unless element is empty
}
@@ -479,6 +492,7 @@
props = None
filter = None
timezone = None
+ timezone_id = None
for child in self.children:
qname = child.qname()
@@ -496,8 +510,15 @@
filter = child
elif qname == (caldav_namespace, "timezone"):
+ if timezone_id is not None:
+ raise ValueError("Only one of CalDAV:timezone and CalDAV:timezone-id allowed")
timezone = child
+ elif qname == (caldav_namespace, "timezone-id"):
+ if timezone is not None:
+ raise ValueError("Only one of CalDAV:timezone and CalDAV:timezone-id allowed")
+ timezone_id = child
+
else:
raise AssertionError("We shouldn't be here")
@@ -508,6 +529,7 @@
self.props = props
self.filter = filter
self.timezone = timezone
+ self.timezone_id = timezone_id
@@ -906,6 +928,16 @@
@registerElement
+class TimeZoneID (CalDAVTextElement):
+ """
+ Specifies a time zone id.
+ (draft-ietf-tzdist-caldav-timezone-ref-01, Section-5.2)
+ """
+ name = "timezone-id"
+
+
+
+ at registerElement
class TimeRange (CalDAVTimeRangeElement):
"""
Specifies a time for testing components against.
Modified: CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from twistedcaldav.timezones import TimezoneException, readVTZ
+from twistedcaldav.ical import Component
"""
CalDAV calendar-query report
@@ -72,18 +74,30 @@
# Get the original timezone provided in the query, if any, and validate it now
query_timezone = None
- query_tz = calendar_query.timezone
- if query_tz is not None and not query_tz.valid():
- msg = "CalDAV:timezone must contain one VTIMEZONE component only: %s" % (query_tz,)
- log.error(msg)
- raise HTTPError(ErrorResponse(
- responsecode.FORBIDDEN,
- (caldav_namespace, "valid-calendar-data"),
- "Invalid calendar-data",
- ))
- if query_tz:
+ if calendar_query.timezone:
+ query_tz = calendar_query.timezone
+ if not query_tz.valid():
+ msg = "CalDAV:timezone must contain one VTIMEZONE component only: %s" % (query_tz,)
+ log.error(msg)
+ raise HTTPError(ErrorResponse(
+ responsecode.FORBIDDEN,
+ (caldav_namespace, "valid-calendar-data"),
+ "Invalid calendar-data",
+ ))
filter.settimezone(query_tz)
- query_timezone = tuple(calendar_query.timezone.calendar().subcomponents())[0]
+ query_timezone = tuple(query_tz.calendar().subcomponents())[0]
+ elif calendar_query.timezone_id:
+ query_tzid = calendar_query.timezone_id.toString()
+ try:
+ query_tz = Component(None, pycalendar=readVTZ(query_tzid))
+ except TimezoneException:
+ raise HTTPError(ErrorResponse(
+ responsecode.FORBIDDEN,
+ (caldav_namespace, "valid-timezone"),
+ "Invalid timezone-id",
+ ))
+ filter.settimezone(query_tz)
+ query_timezone = tuple(query_tz.subcomponents())[0]
if props.qname() == ("DAV:", "allprop"):
propertiesForResource = report_common.allPropertiesForResource
@@ -171,12 +185,13 @@
if calresource.isPseudoCalendarCollection():
# Get the timezone property from the collection if one was not set in the query,
# and store in the query filter for later use
- has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
timezone = query_timezone
- if query_tz is None and has_prop:
- tz = (yield calresource.readProperty(CalendarTimeZone(), request))
- filter.settimezone(tz)
- timezone = tuple(tz.calendar().subcomponents())[0]
+ if timezone is None:
+ has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
+ if has_prop:
+ tz = (yield calresource.readProperty(CalendarTimeZone(), request))
+ filter.settimezone(tz)
+ timezone = tuple(tz.calendar().subcomponents())[0]
# Do some optimization of access control calculation by determining any inherited ACLs outside of
# the child resource loop and supply those to the checkPrivileges on each child.
@@ -226,7 +241,7 @@
# Get the timezone property from the collection if one was not set in the query,
# and store in the query object for later use
timezone = query_timezone
- if query_tz is None:
+ if timezone is None:
parent = (yield calresource.locateParent(request, uri))
assert parent is not None and parent.isPseudoCalendarCollection()
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -690,11 +690,11 @@
"Component %s is not supported by this server" % (component.toxml(),)
))
- # Strictly speaking CalDAV:timezone is a live property in the sense that the
- # server enforces what can be stored, however it need not actually
- # exist so we cannot list it in liveProperties on this resource, since its
- # its presence there means that hasProperty will always return True for it.
- elif property.qname() == caldavxml.CalendarTimeZone.qname():
+ # Strictly speaking CalDAV:calendar-timezone and CalDAV:calendar-timezone-id are live properties
+ # in the sense that the server enforces what can be stored, however they need not actually
+ # exist so we cannot list them in liveProperties on this resource, since their presence there
+ # means that hasProperty will always return True for it.
+ elif property.qname() in (caldavxml.CalendarTimeZone.qname(), caldavxml.CalendarTimeZoneID.qname(),):
if not self.isCalendarCollection():
raise HTTPError(StatusResponse(
responsecode.FORBIDDEN,
Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -96,6 +96,7 @@
BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE
)
from txweb2.stream import ProducerStream, readStream, MemoryStream
+from twistedcaldav.timezones import TimezoneException
"""
@@ -1199,6 +1200,7 @@
DefaultAlarmPropertyMixin.ALARM_PROPERTIES.keys()
) + (
caldavxml.CalendarTimeZone.qname(),
+ caldavxml.CalendarTimeZoneID.qname(),
)
@@ -1212,7 +1214,7 @@
if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
return succeed(self.getDefaultAlarmProperty(qname) is not None)
- elif qname == caldavxml.CalendarTimeZone.qname():
+ elif qname in (caldavxml.CalendarTimeZone.qname(), caldavxml.CalendarTimeZoneID.qname(),):
return succeed(self._newStoreObject.getTimezone() is not None)
else:
@@ -1234,6 +1236,10 @@
format = property.content_type if isinstance(property, caldavxml.CalendarTimeZone) else None
returnValue(caldavxml.CalendarTimeZone.fromCalendar(timezone, format=format) if timezone else None)
+ elif qname == caldavxml.CalendarTimeZoneID.qname():
+ tzid = self._newStoreObject.getTimezoneID()
+ returnValue(caldavxml.CalendarTimeZoneID.fromString(tzid) if tzid else None)
+
result = (yield super(CalendarCollectionResource, self).readProperty(property, request))
returnValue(result)
@@ -1261,6 +1267,18 @@
yield self._newStoreObject.setTimezone(property.calendar())
returnValue(None)
+ elif property.qname() == caldavxml.CalendarTimeZoneID.qname():
+ tzid = property.toString()
+ try:
+ yield self._newStoreObject.setTimezoneID(tzid)
+ except TimezoneException:
+ raise HTTPError(ErrorResponse(
+ responsecode.FORBIDDEN,
+ (caldav_namespace, "valid-timezone"),
+ description="Invalid property"
+ ))
+ returnValue(None)
+
elif property.qname() == caldavxml.ScheduleCalendarTransp.qname():
yield self._newStoreObject.setUsedForFreeBusy(property == caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
returnValue(None)
@@ -1280,7 +1298,7 @@
result = (yield self.removeDefaultAlarmProperty(qname))
returnValue(result)
- elif qname == caldavxml.CalendarTimeZone.qname():
+ elif qname in (caldavxml.CalendarTimeZone.qname(), caldavxml.CalendarTimeZoneID.qname(),):
yield self._newStoreObject.setTimezone(None)
returnValue(None)
Modified: CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -22,7 +22,7 @@
from txweb2.iweb import IResponse
from txweb2.stream import MemoryStream
from txdav.xml import element as davxml
-from txweb2.dav.util import davXMLFromStream
+from txweb2.dav.util import davXMLFromStream, allDataFromStream
from twistedcaldav import caldavxml
from twistedcaldav import ical
@@ -36,6 +36,7 @@
from txdav.caldav.icalendarstore import ComponentUpdateState
from txdav.caldav.datastore.query.filter import TimeRange
from twext.who.idirectory import RecordType
+from twistedcaldav.timezones import readVTZ, TimezoneCache
@inlineCallbacks
@@ -174,6 +175,167 @@
return self.calendar_query(query, got_xml)
+ def test_calendar_query_timezone(self):
+ """
+ Partial retrieval of events by time range.
+ (CalDAV-access-09, section 7.6.1)
+ """
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+
+ tzid1 = "Etc/GMT+1"
+ tz1 = Component(None, pycalendar=readVTZ(tzid1))
+
+ calendar_properties = (
+ davxml.GETETag(),
+ caldavxml.CalendarData(),
+ )
+
+ query_timerange = caldavxml.TimeRange(
+ start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+ end="%04d1101T000000Z" % (DateTime.getToday().getYear(),),
+ )
+
+ query = caldavxml.CalendarQuery(
+ davxml.PropertyContainer(*calendar_properties),
+ caldavxml.Filter(
+ caldavxml.ComponentFilter(
+ caldavxml.ComponentFilter(
+ query_timerange,
+ name="VEVENT",
+ ),
+ name="VCALENDAR",
+ ),
+ ),
+ caldavxml.TimeZone.fromCalendar(tz1),
+ )
+
+ def got_xml(doc):
+ if not isinstance(doc.root_element, davxml.MultiStatus):
+ self.fail("REPORT response XML root element is not multistatus: %r" % (doc.root_element,))
+
+ return self.calendar_query(query, got_xml)
+
+
+ def test_calendar_query_timezone_id(self):
+ """
+ Partial retrieval of events by time range.
+ (CalDAV-access-09, section 7.6.1)
+ """
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+
+ tzid1 = "Etc/GMT+1"
+
+ calendar_properties = (
+ davxml.GETETag(),
+ caldavxml.CalendarData(),
+ )
+
+ query_timerange = caldavxml.TimeRange(
+ start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+ end="%04d1101T000000Z" % (DateTime.getToday().getYear(),),
+ )
+
+ query = caldavxml.CalendarQuery(
+ davxml.PropertyContainer(*calendar_properties),
+ caldavxml.Filter(
+ caldavxml.ComponentFilter(
+ caldavxml.ComponentFilter(
+ query_timerange,
+ name="VEVENT",
+ ),
+ name="VCALENDAR",
+ ),
+ ),
+ caldavxml.TimeZoneID.fromString(tzid1),
+ )
+
+ def got_xml(doc):
+ if not isinstance(doc.root_element, davxml.MultiStatus):
+ self.fail("REPORT response XML root element is not multistatus: %r" % (doc.root_element,))
+
+ return self.calendar_query(query, got_xml)
+
+
+ @inlineCallbacks
+ def test_calendar_query_bogus_timezone_id(self):
+ """
+ Partial retrieval of events by time range.
+ (CalDAV-access-09, section 7.6.1)
+ """
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+
+ calendar_properties = (
+ davxml.GETETag(),
+ caldavxml.CalendarData(),
+ )
+
+ query_timerange = caldavxml.TimeRange(
+ start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+ end="%04d1101T000000Z" % (DateTime.getToday().getYear(),),
+ )
+
+ query = caldavxml.CalendarQuery(
+ davxml.PropertyContainer(*calendar_properties),
+ caldavxml.Filter(
+ caldavxml.ComponentFilter(
+ caldavxml.ComponentFilter(
+ query_timerange,
+ name="VEVENT",
+ ),
+ name="VCALENDAR",
+ ),
+ ),
+ caldavxml.TimeZoneID.fromString("bogus"),
+ )
+
+ result = yield self.calendar_query(query, got_xml=None, expected_code=responsecode.FORBIDDEN)
+ self.assertTrue("valid-timezone" in result)
+
+
+ @inlineCallbacks
+ def test_calendar_query_wrong_timezone_elements(self):
+ """
+ Partial retrieval of events by time range.
+ (CalDAV-access-09, section 7.6.1)
+ """
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+
+ tzid1 = "Etc/GMT+1"
+ tz1 = Component(None, pycalendar=readVTZ(tzid1))
+
+ calendar_properties = (
+ davxml.GETETag(),
+ caldavxml.CalendarData(),
+ )
+
+ query_timerange = caldavxml.TimeRange(
+ start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+ end="%04d1101T000000Z" % (DateTime.getToday().getYear(),),
+ )
+
+ query = caldavxml.CalendarQuery(
+ davxml.PropertyContainer(*calendar_properties),
+ caldavxml.Filter(
+ caldavxml.ComponentFilter(
+ caldavxml.ComponentFilter(
+ query_timerange,
+ name="VEVENT",
+ ),
+ name="VCALENDAR",
+ ),
+ ),
+ caldavxml.TimeZone.fromCalendar(tz1),
+ )
+ query.children += (caldavxml.TimeZoneID.fromString(tzid1),)
+
+ result = yield self.calendar_query(query, got_xml=None, expected_code=responsecode.BAD_REQUEST)
+ self.assertTrue("Only one of" in result)
+
+
def test_calendar_query_partial_recurring(self):
"""
Partial retrieval of recurring events.
@@ -343,7 +505,7 @@
@inlineCallbacks
- def calendar_query(self, query, got_xml):
+ def calendar_query(self, query, got_xml, expected_code=responsecode.MULTI_STATUS):
principal = yield self.actualRoot.findPrincipalForAuthID("wsanchez")
request = SimpleStoreRequest(self, "REPORT", "/calendars/users/wsanchez/calendar/", authPrincipal=principal)
@@ -352,9 +514,14 @@
response = IResponse(response)
- if response.code != responsecode.MULTI_STATUS:
+ if response.code != expected_code:
self.fail("REPORT failed: %s" % (response.code,))
- returnValue(
- (yield davXMLFromStream(response.stream).addCallback(got_xml))
- )
+ if got_xml is not None:
+ returnValue(
+ (yield davXMLFromStream(response.stream).addCallback(got_xml))
+ )
+ else:
+ returnValue(
+ (yield allDataFromStream(response.stream))
+ )
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -50,7 +50,7 @@
pyCalendarToSQLTimestamp, parseSQLDateToPyCalendar
from twistedcaldav.ical import Component, InvalidICalendarDataError, Property
from twistedcaldav.instance import InvalidOverriddenInstanceError
-from twistedcaldav.timezones import TimezoneException
+from twistedcaldav.timezones import TimezoneException, readVTZ, hasTZ
from txdav.base.propertystore.base import PropertyName
from txdav.caldav.datastore.query.builder import buildExpression
@@ -1368,26 +1368,88 @@
def getTimezone(self):
"""
- Return the VTIMEZONE data.
+ Return the VTIMEZONE data. L{self._timezone} will either be a full iCalendar component
+ (BEGIN:VCALENDAR ... END:VCALENDAR) or just the timezone id.
- @return: the component (text)
+ @return: the component
@rtype: L{Component}
"""
- return Component.fromString(self._timezone) if self._timezone else None
+ if self._timezone:
+ if self._timezone.startswith("BEGIN:VCALENDAR"):
+ return Component.fromString(self._timezone)
+ else:
+ try:
+ return Component(None, pycalendar=readVTZ(self._timezone))
+ except TimezoneException:
+ return None
+ else:
+ return None
- @inlineCallbacks
+ def getTimezoneID(self):
+ """
+ Return the VTIMEZONE TZID value. L{self._timezone} will either be a full iCalendar component
+ (BEGIN:VCALENDAR ... END:VCALENDAR) or just the timezone id.
+
+ @return: the timezone id
+ @rtype: L{str}
+ """
+
+ if self._timezone:
+ if self._timezone.startswith("BEGIN:VCALENDAR"):
+ tz = Component.fromString(self._timezone)
+ return list(tz.timezones())[0]
+ else:
+ return self._timezone
+ else:
+ return None
+
+
def setTimezone(self, timezone):
"""
- Set VTIMEZONE data.
+ Set VTIMEZONE data. If the TZID is in our database, then just store the TZID value, otherwise store the
+ entire iCalendar object as text.
@param timezone: the component
@type timezone: L{Component}
"""
- self._timezone = str(timezone) if timezone else None
+ if timezone is not None:
+ try:
+ tzid = list(timezone.timezones())[0]
+ if hasTZ(tzid):
+ self._timezone = tzid
+ except TimezoneException:
+ self._timezone = str(timezone)
+ else:
+ self._timezone = None
+ return self._setTimezoneValue()
+
+ def setTimezoneID(self, tzid):
+ """
+ Set VTIMEZONE via a TZID value. Make sure the TZID is in our TZ database.
+
+ @param tzid: the component
+ @type tzid: L{Component}
+
+ @raise L{TimezoneException} if tzid is not in our database
+ """
+
+ if tzid is not None:
+ hasTZ(tzid)
+ self._timezone = tzid
+ else:
+ self._timezone = None
+ return self._setTimezoneValue()
+
+
+ @inlineCallbacks
+ def _setTimezoneValue(self):
+ """
+ Store the current L{self._timezone} value in the database.
+ """
cal = self._bindSchema
yield Update(
{
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -30,7 +30,7 @@
from twisted.python.filepath import FilePath
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue, DeferredList, \
- succeed
+ succeed, maybeDeferred
from twisted.internet.task import deferLater, Clock
from twisted.trial import unittest
@@ -40,7 +40,7 @@
from twistedcaldav.dateops import datetimeMktime
from twistedcaldav.ical import Component, normalize_iCalStr, diff_iCalStrs
from twistedcaldav.instance import InvalidOverriddenInstanceError
-from twistedcaldav.timezones import TimezoneCache
+from twistedcaldav.timezones import TimezoneCache, readVTZ, TimezoneException
from txdav.base.propertystore.base import PropertyName
from txdav.caldav.datastore.query.filter import Filter
@@ -1844,41 +1844,74 @@
Make sure a L{CalendarHomeChild}.setTimezone() works.
"""
- tz1 = Component.fromString("""BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//calendarserver.org//Zonal//EN
-BEGIN:VTIMEZONE
-TZID:Etc/GMT+1
-X-LIC-LOCATION:Etc/GMT+1
-BEGIN:STANDARD
-DTSTART:18000101T000000
-RDATE:18000101T000000
-TZNAME:GMT+1
-TZOFFSETFROM:-0100
-TZOFFSETTO:-0100
-END:STANDARD
-END:VTIMEZONE
-END:VCALENDAR
-""")
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+ tzid1 = "Etc/GMT+1"
+ tz1 = Component(None, pycalendar=readVTZ(tzid1))
+
cal = yield self.calendarUnderTest()
self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
yield cal.setTimezone(tz1)
self.assertEqual(cal.getTimezone(), tz1)
+ self.assertEqual(cal.getTimezoneID(), tzid1)
yield self.commit()
cal = yield self.calendarUnderTest()
self.assertEqual(cal.getTimezone(), tz1)
+ self.assertEqual(cal.getTimezoneID(), tzid1)
yield cal.setTimezone(None)
yield self.commit()
cal = yield self.calendarUnderTest()
self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
yield self.commit()
@inlineCallbacks
+ def test_setTimezoneID(self):
+ """
+ Make sure a L{CalendarHomeChild}.setTimezoneID() works.
+ """
+
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+
+ tzid1 = "Etc/GMT+1"
+ tz1 = Component(None, pycalendar=readVTZ(tzid1))
+
+ cal = yield self.calendarUnderTest()
+ self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
+ yield cal.setTimezoneID(tzid1)
+ self.assertEqual(cal.getTimezone(), tz1)
+ self.assertEqual(cal.getTimezoneID(), tzid1)
+ yield self.commit()
+
+ cal = yield self.calendarUnderTest()
+ self.assertEqual(cal.getTimezone(), tz1)
+ self.assertEqual(cal.getTimezoneID(), tzid1)
+ yield cal.setTimezoneID(None)
+ yield self.commit()
+
+ cal = yield self.calendarUnderTest()
+ self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
+ yield self.commit()
+
+ # Invalid TZID
+ cal = yield self.calendarUnderTest()
+ self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
+ yield self.failUnlessFailure(maybeDeferred(cal.setTimezoneID, "bogus"), TimezoneException)
+ self.assertEqual(cal.getTimezone(), None)
+ self.assertEqual(cal.getTimezoneID(), None)
+ yield self.commit()
+
+
+ @inlineCallbacks
def test_calendarRevisionChangeConcurrency(self):
"""
Test that two concurrent attempts to add resources in two separate
Modified: CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py 2015-04-09 16:55:50 UTC (rev 14668)
+++ CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py 2015-04-09 16:57:35 UTC (rev 14669)
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from twistedcaldav.timezones import readVTZ, TimezoneCache
"""
Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
@@ -40,58 +41,13 @@
@inlineCallbacks
def _calendarTimezoneUpgrade_setup(self):
- tz1 = Component.fromString("""BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//calendarserver.org//Zonal//EN
-BEGIN:VTIMEZONE
-TZID:Etc/GMT+1
-X-LIC-LOCATION:Etc/GMT+1
-BEGIN:STANDARD
-DTSTART:18000101T000000
-RDATE:18000101T000000
-TZNAME:GMT+1
-TZOFFSETFROM:-0100
-TZOFFSETTO:-0100
-END:STANDARD
-END:VTIMEZONE
-END:VCALENDAR
-""")
- tz2 = Component.fromString("""BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//calendarserver.org//Zonal//EN
-BEGIN:VTIMEZONE
-TZID:Etc/GMT+2
-X-LIC-LOCATION:Etc/GMT+2
-BEGIN:STANDARD
-DTSTART:18000101T000000
-RDATE:18000101T000000
-TZNAME:GMT+2
-TZOFFSETFROM:-0200
-TZOFFSETTO:-0200
-END:STANDARD
-END:VTIMEZONE
-END:VCALENDAR
-""")
- tz3 = Component.fromString("""BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//calendarserver.org//Zonal//EN
-BEGIN:VTIMEZONE
-TZID:Etc/GMT+3
-X-LIC-LOCATION:Etc/GMT+3
-BEGIN:STANDARD
-DTSTART:18000101T000000
-RDATE:18000101T000000
-TZNAME:GMT+3
-TZOFFSETFROM:-0300
-TZOFFSETTO:-0300
-END:STANDARD
-END:VTIMEZONE
-END:VCALENDAR
-""")
+ TimezoneCache.create()
+ self.addCleanup(TimezoneCache.clear)
+ tz1 = Component(None, pycalendar=readVTZ("Etc/GMT+1"))
+ tz2 = Component(None, pycalendar=readVTZ("Etc/GMT+2"))
+ tz3 = Component(None, pycalendar=readVTZ("Etc/GMT+3"))
+
# Share user01 calendar with user03
calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
home3 = yield self.homeUnderTest(name="user03")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20150409/2d343889/attachment-0001.html>
More information about the calendarserver-changes
mailing list