[CalendarServer-changes] [5668] CalendarServer/branches/new-store/txcaldav/calendarstore
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jun 1 15:24:05 PDT 2010
Revision: 5668
http://trac.macosforge.org/projects/calendarserver/changeset/5668
Author: glyph at apple.com
Date: 2010-06-01 15:24:00 -0700 (Tue, 01 Jun 2010)
Log Message:
-----------
simplify
Modified Paths:
--------------
CalendarServer/branches/new-store/txcaldav/calendarstore/file.py
CalendarServer/branches/new-store/txcaldav/calendarstore/scheduling.py
CalendarServer/branches/new-store/txcaldav/calendarstore/test/common.py
CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_file.py
CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_scheduling.py
Modified: CalendarServer/branches/new-store/txcaldav/calendarstore/file.py
===================================================================
--- CalendarServer/branches/new-store/txcaldav/calendarstore/file.py 2010-06-01 17:23:05 UTC (rev 5667)
+++ CalendarServer/branches/new-store/txcaldav/calendarstore/file.py 2010-06-01 22:24:00 UTC (rev 5668)
@@ -29,6 +29,8 @@
from zope.interface import implements
+from twisted.python.util import FancyEqMixin
+
from twisted.internet.defer import inlineCallbacks
from twext.python.log import LoggingMixIn
@@ -372,12 +374,14 @@
-class Calendar(LoggingMixIn):
+class Calendar(LoggingMixIn, FancyEqMixin):
"""
File-based implementation of L{ICalendar}.
"""
implements(ICalendar)
+ compareAttributes = '_path _calendarHome _transaction'.split()
+
def __init__(self, path, calendarHome):
self._path = path
self._calendarHome = calendarHome
@@ -520,15 +524,15 @@
class CalendarObject(LoggingMixIn):
"""
- @ivar path: The path of the .ics file on disk
+ @ivar _path: The path of the .ics file on disk
- @type path: L{FilePath}
+ @type _path: L{FilePath}
"""
implements(ICalendarObject)
def __init__(self, path, calendar):
self._path = path
- self.calendar = calendar
+ self._calendar = calendar
self._component = None
@@ -580,7 +584,7 @@
else:
self._path.remove()
return undo
- self.calendar._transaction.addOperation(do)
+ self._calendar._transaction.addOperation(do)
def component(self):
Modified: CalendarServer/branches/new-store/txcaldav/calendarstore/scheduling.py
===================================================================
--- CalendarServer/branches/new-store/txcaldav/calendarstore/scheduling.py 2010-06-01 17:23:05 UTC (rev 5667)
+++ CalendarServer/branches/new-store/txcaldav/calendarstore/scheduling.py 2010-06-01 22:24:00 UTC (rev 5668)
@@ -17,86 +17,80 @@
from zope.interface.declarations import implements
from txcaldav.icalendarstore import ICalendarStore, ICalendarStoreTransaction, \
ICalendarHome, ICalendar, ICalendarObject
+from twisted.python.util import FancyEqMixin
+from twisted.python.components import proxyForInterface
-class ImplicitSchedulingTransaction(object):
+class ImplicitTransaction(
+ proxyForInterface(ICalendarStoreTransaction,
+ originalAttribute="_transaction")):
"""
Wrapper around an L{ICalendarStoreTransaction}.
"""
- implements(ICalendarStoreTransaction)
def __init__(self, transaction):
"""
- Initialize an L{ImplicitSchedulingTransaction}.
+ Initialize an L{ImplicitTransaction}.
@type transaction: L{ICalendarStoreTransaction}
"""
self._transaction = transaction
- def abort(self):
- """
- Abort the underlying transaction.
- """
- return self._transaction.abort()
-
-
- def commit(self):
- """
- Commit the underlying transaction.
- """
- return self._transaction.commit()
-
-
def calendarHomeWithUID(self, uid, create=False):
# FIXME: 'create' flag
- newHome = self._transaction.calendarHomeWithUID(uid)
-# return ImplicitSchedulingCalendarHome(newHome, self)
+ newHome = super(ImplicitTransaction, self
+ ).calendarHomeWithUID(uid, create)
+# return ImplicitCalendarHome(newHome, self)
if newHome is None:
return None
else:
# FIXME: relay transaction
- return ImplicitSchedulingCalendarHome(newHome, None)
+ return ImplicitCalendarHome(newHome, None)
-class ImplicitSchedulingCalendarHome(object):
+class ImplicitCalendarHome(
+ proxyForInterface(ICalendarHome, "_calendarHome")
+ ):
+
implements(ICalendarHome)
def __init__(self, calendarHome, transaction):
"""
- L{ImplicitSchedulingCalendarHome}
+ Initialize L{ImplicitCalendarHome} with an underlying
+ calendar home and L{ImplicitTransaction}.
"""
self._calendarHome = calendarHome
self._transaction = transaction
- def uid(self):
- return self._calendarHome.uid()
+# def properties(self):
+# # FIXME: wrap?
+# return self._calendarHome.properties()
- def properties(self): ""
- # FIXME: implement
- # return self._calendarHome.properties()
+ def calendars(self):
+ for calendar in super(ImplicitCalendarHome, self).calendars():
+ yield ImplicitCalendar(self, calendar)
- def calendars(self): ""
- # FIXME: implement
def createCalendarWithName(self, name):
self._calendarHome.createCalendarWithName(name)
- def removeCalendarWithName(self, name): ""
- # FIXME: implement
+ def removeCalendarWithName(self, name):
+ self._calendarHome.removeCalendarWithName(name)
+
def calendarWithName(self, name):
calendar = self._calendarHome.calendarWithName(name)
if calendar is not None:
- return ImplicitSchedulingCalendar(self, calendar)
+ return ImplicitCalendar(self, calendar)
else:
return None
-class ImplicitSchedulingCalendarObject(object):
+class ImplicitCalendarObject(object):
implements(ICalendarObject)
def setComponent(self, component): ""
def component(self): ""
@@ -108,43 +102,41 @@
-class ImplicitSchedulingCalendar(object):
- implements(ICalendar)
+class ImplicitCalendar(FancyEqMixin,
+ proxyForInterface(ICalendar, "_subCalendar")):
+ compareAttributes = ['_subCalendar', '_parentHome']
+
def __init__(self, parentHome, subCalendar):
self._parentHome = parentHome
self._subCalendar = subCalendar
- def name(self):
- return self._subCalendar.name()
+# def ownerCalendarHome(self):
+# return self._parentHome
+# def calendarObjects(self):
+# # FIXME: wrap
+# return self._subCalendar.calendarObjects()
+# def calendarObjectWithUID(self, uid): ""
+# def createCalendarObjectWithName(self, name, component):
+# # FIXME: implement most of StoreCalendarObjectResource here!
+# self._subCalendar.createCalendarObjectWithName(name, component)
+# def removeCalendarObjectWithName(self, name):
+# # FIXME: implement deletion logic here!
+# return self._subCalendar.removeCalendarObjectWithName(name)
+# def removeCalendarObjectWithUID(self, uid): ""
+# def syncToken(self): ""
+# def calendarObjectsInTimeRange(self, start, end, timeZone): ""
+# def calendarObjectsSinceToken(self, token): ""
+# def properties(self):
+# # FIXME: probably need to wrap this as well
+# return self._subCalendar.properties()
+#
+# def calendarObjectWithName(self, name):
+# #FIXME: wrap
+# return self._subCalendar.calendarObjectWithName(name)
- def ownerCalendarHome(self):
- return self._parentHome
- def calendarObjects(self):
- # FIXME: wrap
- return self._subCalendar.calendarObjects()
- def calendarObjectWithUID(self, uid): ""
- def createCalendarObjectWithName(self, name, component):
- # FIXME: implement most of StoreCalendarObjectResource here!
- self._subCalendar.createCalendarObjectWithName(name, component)
- def removeCalendarObjectWithName(self, name):
- # FIXME: implement deletion logic here!
- return self._subCalendar.removeCalendarObjectWithName(name)
- def removeCalendarObjectWithUID(self, uid): ""
- def syncToken(self): ""
- def calendarObjectsInTimeRange(self, start, end, timeZone): ""
- def calendarObjectsSinceToken(self, token): ""
- def properties(self):
- # FIXME: probably need to wrap this as well
- return self._subCalendar.properties()
-
- def calendarObjectWithName(self, name):
- #FIXME: wrap
- return self._subCalendar.calendarObjectWithName(name)
-
-
-class ImplicitSchedulingStore(object):
+class ImplicitStore(object):
"""
This is a wrapper around an L{ICalendarStore} that implements implicit
scheduling.
@@ -154,7 +146,7 @@
def __init__(self, calendarStore):
"""
- Create an L{ImplicitSchedulingStore} wrapped around another
+ Create an L{ImplicitStore} wrapped around another
L{ICalendarStore} provider.
"""
self._calendarStore = calendarStore
@@ -164,5 +156,5 @@
"""
Wrap an underlying L{ITransaction}.
"""
- return ImplicitSchedulingTransaction(
+ return ImplicitTransaction(
self._calendarStore.newTransaction())
Modified: CalendarServer/branches/new-store/txcaldav/calendarstore/test/common.py
===================================================================
--- CalendarServer/branches/new-store/txcaldav/calendarstore/test/common.py 2010-06-01 17:23:05 UTC (rev 5667)
+++ CalendarServer/branches/new-store/txcaldav/calendarstore/test/common.py 2010-06-01 22:24:00 UTC (rev 5668)
@@ -18,12 +18,20 @@
Tests for common calendar store API functions.
"""
-from txcaldav.icalendarstore import ICalendarStore, ICalendarStoreTransaction, \
- ICalendarObject, ICalendarHome, ICalendar, InvalidCalendarComponentError
-from twext.python.filepath import CachingFilePath as FilePath
from zope.interface.verify import verifyObject
-from zope.interface.exceptions import BrokenMethodImplementation
+from zope.interface.exceptions import (
+ BrokenMethodImplementation, DoesNotImplement)
+
+from txdav.idav import IPropertyStore
from txdav.propertystore.base import PropertyName
+
+from txcaldav.icalendarstore import (
+ ICalendarStore, ICalendarStoreTransaction, ICalendarObject, ICalendarHome,
+ ICalendar, InvalidCalendarComponentError,
+ CalendarObjectNameAlreadyExistsError, CalendarAlreadyExistsError,
+ NoSuchCalendarError, NoSuchCalendarObjectError)
+
+from twext.python.filepath import CachingFilePath as FilePath
from twext.web2.dav import davxml
from twext.python.vcomponent import VComponent
@@ -34,13 +42,20 @@
cal1Root = homeRoot.child("calendar_1")
-calendar1_objectNames = (
+calendar1_objectNames = [
"1.ics",
"2.ics",
"3.ics",
-)
+]
+home1_calendarNames = [
+ "calendar_1",
+ "calendar_2",
+ "calendar_empty",
+]
+
+
event4_text = (
"BEGIN:VCALENDAR\r\n"
"VERSION:2.0\r\n"
@@ -82,6 +97,41 @@
"END:VCALENDAR\r\n"
)
+
+
+event4notCalDAV_text = (
+ "BEGIN:VCALENDAR\r\n"
+ "VERSION:2.0\r\n"
+ "PRODID:-//Apple Inc.//iCal 4.0.1//EN\r\n"
+ "CALSCALE:GREGORIAN\r\n"
+ "BEGIN:VEVENT\r\n"
+ "CREATED:20100203T013849Z\r\n"
+ "UID:4\r\n"
+ "DTEND;TZID=US/Pacific:20100207T173000\r\n" # TZID without VTIMEZONE
+ "TRANSP:OPAQUE\r\n"
+ "SUMMARY:New Event\r\n"
+ "DTSTART;TZID=US/Pacific:20100207T170000\r\n"
+ "DTSTAMP:20100203T013909Z\r\n"
+ "SEQUENCE:3\r\n"
+ "BEGIN:VALARM\r\n"
+ "X-WR-ALARMUID:1377CCC7-F85C-4610-8583-9513D4B364E1\r\n"
+ "TRIGGER:-PT20M\r\n"
+ "ATTACH;VALUE=URI:Basso\r\n"
+ "ACTION:AUDIO\r\n"
+ "END:VALARM\r\n"
+ "END:VEVENT\r\n"
+ "END:VCALENDAR\r\n"
+)
+
+
+
+event1modified_text = event4_text.replace(
+ "\r\nUID:uid4\r\n",
+ "\r\nUID:uid1\r\n"
+)
+
+
+
class CommonTests(object):
"""
Tests for common functionality of interfaces defined in
@@ -182,6 +232,9 @@
verifyObject(interface, provider)
except BrokenMethodImplementation, e:
self.fail(e)
+ except DoesNotImplement, e:
+ self.fail("%r does not provide %s.%s" %
+ (provider, interface.__module__, interface.getName()))
def test_calendarStoreProvides(self):
@@ -251,6 +304,27 @@
)
+ def test_calendarWithName_exists(self):
+ """
+ L{ICalendarHome.calendarWithName} returns an L{ICalendar} provider,
+ whose name matches the one passed in.
+ """
+ home = self.homeUnderTest()
+ for name in home1_calendarNames:
+ calendar = home.calendarWithName(name)
+ self.assertProvides(ICalendar, calendar)
+ self.assertEquals(calendar.name(), name)
+
+
+ def test_calendarWithName_absent(self):
+ """
+ L{ICalendarHome.calendarWithName} returns C{None} for calendars which
+ do not exist.
+ """
+ self.assertEquals(self.homeUnderTest().calendarWithName("xyzzy"),
+ None)
+
+
def test_createCalendarWithName_absent(self):
"""
L{ICalendarHome.createCalendarWithName} creates a new L{ICalendar} that
@@ -281,26 +355,65 @@
checkProperties()
+ def test_createCalendarWithName_exists(self):
+ """
+ L{ICalendarHome.createCalendarWithName} raises
+ L{CalendarAlreadyExistsError} when the name conflicts with an already-
+ existing
+ """
+ for name in home1_calendarNames:
+ self.assertRaises(
+ CalendarAlreadyExistsError,
+ self.homeUnderTest().createCalendarWithName, name
+ )
+
+
+ def test_removeCalendarWithName_exists(self):
+ """
+ L{ICalendarHome.removeCalendarWithName} removes a calendar that already
+ exists.
+ """
+ home = self.homeUnderTest()
+ # FIXME: test transactions
+ for name in home1_calendarNames:
+ self.assertNotIdentical(home.calendarWithName(name), None)
+ home.removeCalendarWithName(name)
+ self.assertEquals(home.calendarWithName(name), None)
+
+
+ def test_removeCalendarWithName_absent(self):
+ """
+ Attempt to remove an non-existing calendar should raise.
+ """
+ home = self.homeUnderTest()
+ self.assertRaises(NoSuchCalendarError,
+ home.removeCalendarWithName, "xyzzy")
+
+
def test_calendarObjects(self):
"""
L{ICalendar.calendarObjects} will enumerate the calendar objects present
in the filesystem, in name order, but skip those with hidden names.
"""
calendar1 = self.calendarUnderTest()
- calendarObjects = tuple(calendar1.calendarObjects())
+ calendarObjects = list(calendar1.calendarObjects())
for calendarObject in calendarObjects:
self.assertProvides(ICalendarObject, calendarObject)
+ self.assertEquals(
+ calendar1.calendarObjectWithName(calendarObject.name()),
+ calendarObject
+ )
self.assertEquals(
- tuple(o.name() for o in calendarObjects),
+ list(o.name() for o in calendarObjects),
calendar1_objectNames
)
def test_calendarObjectsWithRemovedObject(self):
"""
- L{ICalendar.calendarObjects} will skip those objects which have been
+ L{ICalendar.calendarObjects} skips those objects which have been
removed by L{Calendar.removeCalendarObjectWithName} in the same
transaction, even if it has not yet been committed.
"""
@@ -321,6 +434,19 @@
)
+ def test_calendarObjectWithName_exists(self):
+ """
+ L{ICalendar.calendarObjectWithName} returns an L{ICalendarObject}
+ provider for calendars which already exist.
+ """
+ calendar1 = self.calendarUnderTest()
+ for name in calendar1_objectNames:
+ calendarObject = calendar1.calendarObjectWithName(name)
+ self.assertProvides(ICalendarObject, calendarObject)
+ self.assertEquals(calendarObject.name(), name)
+ # FIXME: add more tests based on CommonTests.requirements
+
+
def test_calendarObjectWithName_absent(self):
"""
L{ICalendar.calendarObjectWithName} returns C{None} for calendars which
@@ -330,13 +456,115 @@
self.assertEquals(calendar1.calendarObjectWithName("xyzzy"), None)
- def test_name(self):
+ def test_removeCalendarObjectWithUID_exists(self):
"""
+ Remove an existing calendar object.
+ """
+ calendar = self.calendarUnderTest()
+ for name in calendar1_objectNames:
+ uid = (u'uid' + name.rstrip(".ics"))
+ self.assertNotIdentical(calendar.calendarObjectWithUID(uid),
+ None)
+ calendar.removeCalendarObjectWithUID(uid)
+ self.assertEquals(
+ calendar.calendarObjectWithUID(uid),
+ None
+ )
+ self.assertEquals(
+ calendar.calendarObjectWithName(name),
+ None
+ )
+
+
+ def test_removeCalendarObjectWithName_exists(self):
+ """
+ Remove an existing calendar object.
+ """
+ calendar = self.calendarUnderTest()
+ for name in calendar1_objectNames:
+ self.assertNotIdentical(
+ calendar.calendarObjectWithName(name), None
+ )
+ calendar.removeCalendarObjectWithName(name)
+ self.assertIdentical(
+ calendar.calendarObjectWithName(name), None
+ )
+
+
+ def test_removeCalendarObjectWithName_absent(self):
+ """
+ Attempt to remove an non-existing calendar object should raise.
+ """
+ calendar = self.calendarUnderTest()
+ self.assertRaises(
+ NoSuchCalendarObjectError,
+ calendar.removeCalendarObjectWithName, "xyzzy"
+ )
+
+
+ def test_calendarName(self):
+ """
L{Calendar.name} reflects the name of the calendar.
"""
self.assertEquals(self.calendarUnderTest().name(), "calendar_1")
+ def test_calendarObjectName(self):
+ """
+ L{ICalendarObject.name} reflects the name of the calendar object.
+ """
+ self.assertEquals(self.calendarObjectUnderTest().name(), "1.ics")
+
+
+ def test_component(self):
+ """
+ L{ICalendarObject.component} returns a L{VComponent} describing the
+ calendar data underlying that calendar object.
+ """
+ component = self.calendarObjectUnderTest().component()
+
+ self.failUnless(
+ isinstance(component, VComponent),
+ component
+ )
+
+ self.assertEquals(component.name(), "VCALENDAR")
+ self.assertEquals(component.mainType(), "VEVENT")
+ self.assertEquals(component.resourceUID(), "uid1")
+
+
+ def test_iCalendarText(self):
+ """
+ L{ICalendarObject.iCalendarText} returns a C{str} describing the same
+ data provided by L{ICalendarObject.component}.
+ """
+ text = self.calendarObjectUnderTest().iCalendarText()
+ self.assertIsInstance(text, str)
+ self.failUnless(text.startswith("BEGIN:VCALENDAR\r\n"))
+ self.assertIn("\r\nUID:uid1\r\n", text)
+ self.failUnless(text.endswith("\r\nEND:VCALENDAR\r\n"))
+
+
+ def test_calendarObjectUID(self):
+ """
+ L{ICalendarObject.uid} returns a C{str} describing the C{UID} property
+ of the calendar object's component.
+ """
+ self.assertEquals(self.calendarObjectUnderTest().uid(), "uid1")
+
+
+ def test_organizer(self):
+ """
+ L{ICalendarObject.organizer} returns a C{str} describing the calendar
+ user address of the C{ORGANIZER} property of the calendar object's
+ component.
+ """
+ self.assertEquals(
+ self.calendarObjectUnderTest().organizer(),
+ "mailto:wsanchez at apple.com"
+ )
+
+
def test_calendarObjectWithUID_absent(self):
"""
L{ICalendar.calendarObjectWithUID} returns C{None} for calendars which
@@ -346,9 +574,31 @@
self.assertEquals(calendar1.calendarObjectWithUID("xyzzy"), None)
+ def test_calendars(self):
+ """
+ L{ICalendarHome.calendars} returns an iterable of L{ICalendar}
+ providers, which are consistent with the results from
+ L{ICalendar.calendarWithName}.
+ """
+ # Add a dot directory to make sure we don't find it
+ # self.home1._path.child(".foo").createDirectory()
+ home = self.homeUnderTest()
+ calendars = list(home.calendars())
+
+ for calendar in calendars:
+ self.assertProvides(ICalendar, calendar)
+ self.assertEquals(calendar,
+ home.calendarWithName(calendar.name()))
+
+ self.assertEquals(
+ list(c.name() for c in calendars),
+ home1_calendarNames
+ )
+
+
def test_createCalendarObjectWithName_absent(self):
"""
- L{ICalendar.createCalendarObjectWithName} will create a new
+ L{ICalendar.createCalendarObjectWithName} creates a new
L{ICalendarObject}.
"""
calendar1 = self.calendarUnderTest()
@@ -361,6 +611,45 @@
self.assertEquals(calendarObject.component(), component)
+ def test_createCalendarObjectWithName_exists(self):
+ """
+ L{ICalendar.createCalendarObjectWithName} raises
+ L{CalendarObjectNameAlreadyExistsError} if a calendar object with the
+ given name already exists in that calendar.
+ """
+ self.assertRaises(
+ CalendarObjectNameAlreadyExistsError,
+ self.calendarUnderTest().createCalendarObjectWithName,
+ "1.ics", VComponent.fromString(event4_text)
+ )
+
+
+ def test_createCalendarObjectWithName_invalid(self):
+ """
+ L{ICalendar.createCalendarObjectWithName} raises
+ L{InvalidCalendarComponentError} if presented with invalid iCalendar
+ text.
+ """
+ self.assertRaises(
+ InvalidCalendarComponentError,
+ self.calendarUnderTest().createCalendarObjectWithName,
+ "new", VComponent.fromString(event4notCalDAV_text)
+ )
+
+
+ def test_setComponent_invalid(self):
+ """
+ L{ICalendarObject.setComponent} raises L{InvalidICalendarDataError} if
+ presented with invalid iCalendar text.
+ """
+ calendarObject = self.calendarObjectUnderTest()
+ self.assertRaises(
+ InvalidCalendarComponentError,
+ calendarObject.setComponent,
+ VComponent.fromString(event4notCalDAV_text)
+ )
+
+
def test_setComponent_uidchanged(self):
"""
L{ICalendarObject.setComponent} raises L{InvalidCalendarComponentError}
@@ -375,3 +664,72 @@
)
+ def test_calendarHomeWithUID_create(self):
+ """
+ L{ICalendarStoreTransaction.calendarHomeWithUID} with C{create=True}
+ will create a calendar home that doesn't exist yet.
+ """
+ txn = self.transactionUnderTest()
+ noHomeUID = "xyzzy"
+ calendarHome = txn.calendarHomeWithUID(
+ noHomeUID,
+ create=True
+ )
+ def readOtherTxn():
+ return self.savedStore.newTransaction().calendarHomeWithUID(
+ noHomeUID)
+ self.assertProvides(ICalendarHome, calendarHome)
+ # A concurrent transaction shouldn't be able to read it yet:
+ self.assertIdentical(readOtherTxn(), None)
+ txn.commit()
+ # But once it's committed, other transactions should see it.
+ self.assertProvides(ICalendarHome, readOtherTxn())
+
+
+ def test_setComponent(self):
+ """
+ L{CalendarObject.setComponent} changes the result of
+ L{CalendarObject.component} within the same transaction.
+ """
+ component = VComponent.fromString(event1modified_text)
+
+ calendar1 = self.calendarUnderTest()
+ calendarObject = calendar1.calendarObjectWithName("1.ics")
+ oldComponent = calendarObject.component()
+ self.assertNotEqual(component, oldComponent)
+ calendarObject.setComponent(component)
+ self.assertEquals(calendarObject.component(), component)
+
+ # Also check a new instance
+ calendarObject = calendar1.calendarObjectWithName("1.ics")
+ self.assertEquals(calendarObject.component(), component)
+
+
+ def checkPropertiesMethod(self, thunk):
+ """
+ Verify that the given object has a properties method that returns an
+ L{IPropertyStore}.
+ """
+ properties = thunk.properties()
+ self.assertProvides(IPropertyStore, properties)
+
+
+ def test_homeProperties(self):
+ """
+ L{ICalendarHome.properties} returns a property store.
+ """
+ self.checkPropertiesMethod(self.homeUnderTest())
+
+
+ def test_calendarProperties(self):
+ """
+ L{ICalendar.properties} returns a property store.
+ """
+ self.checkPropertiesMethod(self.calendarUnderTest())
+
+
+ def test_calendarObjectProperties(self):
+ """
+ L{ICalendarObject.properties} returns a proprety store.
+ """
+ self.checkPropertiesMethod(self.calendarObjectUnderTest())
Modified: CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_file.py
===================================================================
--- CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_file.py 2010-06-01 17:23:05 UTC (rev 5667)
+++ CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_file.py 2010-06-01 22:24:00 UTC (rev 5668)
@@ -23,63 +23,22 @@
from twext.python.vcomponent import VComponent
-from txdav.idav import IPropertyStore
-
from txcaldav.icalendarstore import CalendarNameNotAllowedError
from txcaldav.icalendarstore import CalendarObjectNameNotAllowedError
from txcaldav.icalendarstore import CalendarAlreadyExistsError
-from txcaldav.icalendarstore import CalendarObjectNameAlreadyExistsError
from txcaldav.icalendarstore import CalendarObjectUIDAlreadyExistsError
from txcaldav.icalendarstore import NoSuchCalendarError
from txcaldav.icalendarstore import NoSuchCalendarObjectError
-from txcaldav.icalendarstore import InvalidCalendarComponentError
from txcaldav.calendarstore.file import CalendarStore, CalendarHome
from txcaldav.calendarstore.file import Calendar, CalendarObject
from txcaldav.calendarstore.test.common import (
- CommonTests, calendar1_objectNames, event4_text)
+ CommonTests, calendar1_objectNames, event4_text, event1modified_text,
+ home1_calendarNames)
storePath = FilePath(__file__).parent().child("calendar_store")
-home1_calendarNames = (
- "calendar_1",
- "calendar_2",
- "calendar_empty",
-)
-
-
-event1modified_text = event4_text.replace(
- "\r\nUID:uid4\r\n",
- "\r\nUID:uid1\r\n"
-)
-
-event4notCalDAV_text = (
- "BEGIN:VCALENDAR\r\n"
- "VERSION:2.0\r\n"
- "PRODID:-//Apple Inc.//iCal 4.0.1//EN\r\n"
- "CALSCALE:GREGORIAN\r\n"
- "BEGIN:VEVENT\r\n"
- "CREATED:20100203T013849Z\r\n"
- "UID:4\r\n"
- "DTEND;TZID=US/Pacific:20100207T173000\r\n" # TZID without VTIMEZONE
- "TRANSP:OPAQUE\r\n"
- "SUMMARY:New Event\r\n"
- "DTSTART;TZID=US/Pacific:20100207T170000\r\n"
- "DTSTAMP:20100203T013909Z\r\n"
- "SEQUENCE:3\r\n"
- "BEGIN:VALARM\r\n"
- "X-WR-ALARMUID:1377CCC7-F85C-4610-8583-9513D4B364E1\r\n"
- "TRIGGER:-PT20M\r\n"
- "ATTACH;VALUE=URI:Basso\r\n"
- "ACTION:AUDIO\r\n"
- "END:VALARM\r\n"
- "END:VEVENT\r\n"
- "END:VCALENDAR\r\n"
-)
-
-
-
def _todo(f, why):
f.todo = why
return f
@@ -91,23 +50,11 @@
todo = lambda why: lambda f: _todo(f, why)
-class PropertiesTestMixin(object):
-
- def test_properties(self):
- properties = self.home1.properties()
-
- self.failUnless(
- IPropertyStore.providedBy(properties),
- properties
- )
-
-
-
def setUpCalendarStore(test):
test.root = FilePath(test.mktemp())
test.root.createDirectory()
- calendarPath = test.root.child("store")
+ calendarPath = test.calendarPath = test.root.child("store")
storePath.copyTo(calendarPath)
@@ -140,41 +87,6 @@
setUpCalendarStore(self)
- def test_init(self):
- """
- Ivars are correctly initialized.
- """
- self.failUnless(
- isinstance(self.calendarStore._path, FilePath),
- self.calendarStore._path
- )
-
-
- def test_calendarHomeWithUID_create(self):
- """
- Create missing calendar home.
- """
- txn = self.calendarStore.newTransaction()
- calendarHome = txn.calendarHomeWithUID(
- "xyzzy",
- create=True
- )
-
- self.failUnless(isinstance(calendarHome, CalendarHome))
- self.failIf(calendarHome._path.isdir())
- txn.commit()
- self.failUnless(calendarHome._path.isdir())
-
-
- def test_calendarHomeWithUID_create_exists(self):
- """
- Create missing calendar home.
- """
- calendarHome = self.calendarStore.newTransaction().calendarHomeWithUID("home1")
-
- self.failUnless(isinstance(calendarHome, CalendarHome))
-
-
def test_calendarHomeWithUID_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -187,7 +99,7 @@
-class CalendarHomeTest(unittest.TestCase, PropertiesTestMixin):
+class CalendarHomeTest(unittest.TestCase):
def setUp(self):
setUpHome1(self)
@@ -195,7 +107,8 @@
def test_init(self):
"""
- Ivars are correctly initialized.
+ L{CalendarHome} has C{_path} and L{_calendarStore} attributes,
+ indicating its location on disk and parent store, respectively.
"""
self.failUnless(
isinstance(self.home1._path, FilePath),
@@ -207,41 +120,6 @@
)
- def test_calendars(self):
- """
- Find all of the calendars.
- """
- # Add a dot directory to make sure we don't find it
- self.home1._path.child(".foo").createDirectory()
-
- calendars = tuple(self.home1.calendars())
-
- for calendar in calendars:
- self.failUnless(isinstance(calendar, Calendar), calendar)
-
- self.assertEquals(
- tuple(c.name() for c in calendars),
- home1_calendarNames
- )
-
-
- def test_calendarWithName_exists(self):
- """
- Find existing calendar by name.
- """
- for name in home1_calendarNames:
- calendar = self.home1.calendarWithName(name)
- self.failUnless(isinstance(calendar, Calendar), calendar)
- self.assertEquals(calendar.name(), name)
-
-
- def test_calendarWithName_absent(self):
- """
- Missing calendar.
- """
- self.assertEquals(self.home1.calendarWithName("xyzzy"), None)
-
-
def test_calendarWithName_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -252,17 +130,6 @@
self.assertEquals(self.home1.calendarWithName(name), None)
- def test_createCalendarWithName_exists(self):
- """
- Attempt to create an existing calendar should raise.
- """
- for name in home1_calendarNames:
- self.assertRaises(
- CalendarAlreadyExistsError,
- self.home1.createCalendarWithName, name
- )
-
-
def test_createCalendarWithName_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -274,27 +141,6 @@
)
- def test_removeCalendarWithName_exists(self):
- """
- Remove an existing calendar.
- """
- for name in home1_calendarNames:
- self.assertNotIdentical(self.home1.calendarWithName(name),
- None)
- self.home1.removeCalendarWithName(name)
- self.assertEquals(self.home1.calendarWithName(name), None)
-
-
- def test_removeCalendarWithName_absent(self):
- """
- Attempt to remove an non-existing calendar should raise.
- """
- self.assertRaises(
- NoSuchCalendarError,
- self.home1.removeCalendarWithName, "xyzzy"
- )
-
-
def test_removeCalendarWithName_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -309,7 +155,7 @@
-class CalendarTest(unittest.TestCase, PropertiesTestMixin):
+class CalendarTest(unittest.TestCase):
def setUp(self):
setUpCalendar1(self)
@@ -330,19 +176,6 @@
)
- def test_calendarObjectWithName_exists(self):
- """
- Find existing calendar object by name.
- """
- for name in calendar1_objectNames:
- calendarObject = self.calendar1.calendarObjectWithName(name)
- self.failUnless(
- isinstance(calendarObject, CalendarObject),
- calendarObject
- )
- self.assertEquals(calendarObject.name(), name)
-
-
def test_calendarObjectWithName_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -370,17 +203,6 @@
)
- def test_createCalendarObjectWithName_exists(self):
- """
- Attempt to create an existing calendar object should raise.
- """
- self.assertRaises(
- CalendarObjectNameAlreadyExistsError,
- self.calendar1.createCalendarObjectWithName,
- "1.ics", VComponent.fromString(event4_text)
- )
-
-
def test_createCalendarObjectWithName_dot(self):
"""
Filenames starting with "." are reserved by this
@@ -410,42 +232,6 @@
)
- def test_createCalendarObjectWithName_invalid(self):
- """
- Attempt to create a calendar object with a invalid iCalendar text
- should raise.
- """
- self.assertRaises(
- InvalidCalendarComponentError,
- self.calendar1.createCalendarObjectWithName,
- "new", VComponent.fromString(event4notCalDAV_text)
- )
-
-
- def test_removeCalendarObjectWithName_exists(self):
- """
- Remove an existing calendar object.
- """
- for name in calendar1_objectNames:
- self.assertNotIdentical(
- self.calendar1.calendarObjectWithName(name), None
- )
- self.calendar1.removeCalendarObjectWithName(name)
- self.assertIdentical(
- self.calendar1.calendarObjectWithName(name), None
- )
-
-
- def test_removeCalendarObjectWithName_absent(self):
- """
- Attempt to remove an non-existing calendar object should raise.
- """
- self.assertRaises(
- NoSuchCalendarObjectError,
- self.calendar1.removeCalendarObjectWithName, "xyzzy"
- )
-
-
def test_removeCalendarObject_delayedEffect(self):
"""
Removing a calendar object should not immediately remove the underlying
@@ -471,25 +257,6 @@
)
- def test_removeCalendarObjectWithUID_exists(self):
- """
- Remove an existing calendar object.
- """
- for name in calendar1_objectNames:
- uid = (u'uid' + name.rstrip(".ics"))
- self.assertNotIdentical(self.calendar1.calendarObjectWithUID(uid),
- None)
- self.calendar1.removeCalendarObjectWithUID(uid)
- self.assertEquals(
- self.calendar1.calendarObjectWithUID(uid),
- None
- )
- self.assertEquals(
- self.calendar1.calendarObjectWithName(name),
- None
- )
-
-
def _refresh(self):
"""
Re-read the (committed) home1 and calendar1 objects in a new
@@ -608,7 +375,7 @@
-class CalendarObjectTest(unittest.TestCase, PropertiesTestMixin):
+class CalendarObjectTest(unittest.TestCase):
def setUp(self):
setUpCalendar1(self)
self.object1 = self.calendar1.calendarObjectWithName("1.ics")
@@ -616,86 +383,20 @@
def test_init(self):
"""
- Ivars are correctly initialized.
- """
+ L{CalendarObject} has instance attributes, C{_path} and C{_calendar},
+ which refer to its position in the filesystem and the calendar in which
+ it is contained, respectively.
+ """
self.failUnless(
isinstance(self.object1._path, FilePath),
self.object1._path
)
self.failUnless(
- isinstance(self.object1.calendar, Calendar),
- self.object1.calendar
+ isinstance(self.object1._calendar, Calendar),
+ self.object1._calendar
)
- def test_name(self):
- """
- Name is correct.
- """
- self.assertEquals(self.object1.name(), "1.ics")
-
-
- def test_setComponent(self):
- """
- L{CalendarObject.setComponent} changes the result of
- L{CalendarObject.component} within the same transaction.
- """
- component = VComponent.fromString(event1modified_text)
-
- calendarObject = self.calendar1.calendarObjectWithName("1.ics")
- oldComponent = calendarObject.component()
- self.assertNotEqual(component, oldComponent)
- calendarObject.setComponent(component)
- self.assertEquals(calendarObject.component(), component)
-
- # Also check a new instance
- calendarObject = self.calendar1.calendarObjectWithName("1.ics")
- self.assertEquals(calendarObject.component(), component)
-
-
- def test_setComponent_invalid(self):
- calendarObject = self.calendar1.calendarObjectWithName("1.ics")
- self.assertRaises(
- InvalidCalendarComponentError,
- calendarObject.setComponent,
- VComponent.fromString(event4notCalDAV_text)
- )
-
-
- def test_component(self):
- """
- Component is correct.
- """
- component = self.object1.component()
-
- self.failUnless(
- isinstance(component, VComponent),
- component
- )
-
- self.assertEquals(component.name(), "VCALENDAR")
- self.assertEquals(component.mainType(), "VEVENT")
- self.assertEquals(component.resourceUID(), "uid1")
-
-
- def text_iCalendarText(self):
- """
- iCalendar text is correct.
- """
- text = self.object1.iCalendarText()
-
- self.failUnless(text.startswith("BEGIN:VCALENDAR\r\n"))
- self.failUnless("\r\nUID:uid-1\r\n" in text)
- self.failUnless(text.endswith("\r\nEND:VCALENDAR\r\n"))
-
-
- def test_uid(self):
- """
- UID is correct.
- """
- self.assertEquals(self.object1.uid(), "uid1")
-
-
def test_componentType(self):
"""
Component type is correct.
@@ -703,17 +404,7 @@
self.assertEquals(self.object1.componentType(), "VEVENT")
- def test_organizer(self):
- """
- Organizer is correct.
- """
- self.assertEquals(
- self.object1.organizer(),
- "mailto:wsanchez at apple.com"
- )
-
-
class FileStorageTests(unittest.TestCase, CommonTests):
"""
File storage tests.
@@ -727,6 +418,15 @@
return self.calendarStore
+ def test_init(self):
+ """
+ L{CalendarStore} has a C{_path} attribute which refers to its
+ constructor argument.
+ """
+ self.assertEquals(self.storeUnderTest()._path,
+ self.calendarPath)
+
+
def test_calendarObjectsWithDotFile(self):
"""
Adding a dotfile to the calendar home should not increase
Modified: CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_scheduling.py
===================================================================
--- CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_scheduling.py 2010-06-01 17:23:05 UTC (rev 5667)
+++ CalendarServer/branches/new-store/txcaldav/calendarstore/test/test_scheduling.py 2010-06-01 22:24:00 UTC (rev 5668)
@@ -21,15 +21,28 @@
from twisted.trial.unittest import TestCase
from txcaldav.calendarstore.test.common import CommonTests
from txcaldav.calendarstore.test.test_file import setUpCalendarStore
-from txcaldav.calendarstore.scheduling import ImplicitSchedulingStore
+from txcaldav.calendarstore.scheduling import ImplicitStore
+simpleEvent = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER:mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
-class ImplicitSchedulingStoreTests(TestCase, CommonTests):
+class ImplicitStoreTests(TestCase, CommonTests):
"""
Tests for L{ImplicitSchedulingStore}.
"""
def storeUnderTest(self):
setUpCalendarStore(self)
- self.implicitStore = ImplicitSchedulingStore(self.calendarStore)
+ self.implicitStore = ImplicitStore(self.calendarStore)
return self.implicitStore
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100601/c9760c3b/attachment-0001.html>
More information about the calendarserver-changes
mailing list