[CalendarServer-changes] [11127] CalendarServer/branches/users/cdaboo/store-scheduling
source_changes at macosforge.org
source_changes at macosforge.org
Fri May 3 11:58:13 PDT 2013
Revision: 11127
http://trac.calendarserver.org//changeset/11127
Author: cdaboo at apple.com
Date: 2013-05-03 11:58:13 -0700 (Fri, 03 May 2013)
Log Message:
-----------
Remove ResourceType from dead prop store.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/cache.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/customxml.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/aggregate.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookmultiget.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookquery.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_mkcalendar.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_props.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_resource.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_sharing.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/file.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/common.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/file.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/common.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/test_sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/file.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/cache.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/cache.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -20,8 +20,7 @@
from zope.interface import implements
-from twisted.internet.defer import succeed, maybeDeferred, inlineCallbacks, \
- returnValue
+from twisted.internet.defer import succeed, inlineCallbacks, returnValue
from twext.web2.dav.util import allDataFromStream
from twext.web2.http import Response
from twext.web2.iweb import IResource
@@ -440,21 +439,19 @@
A mixin that causes a resource's PROPFIND response to be cached. It also adds an api to change the
resource's uriToken - this must be used whenever something changes to cause the cache to be invalidated.
"""
+
+ @inlineCallbacks
def renderHTTP(self, request):
- def _cacheResponse(responseCache, response):
- return responseCache.cacheResponseForRequest(request, response)
+ response = (yield super(PropfindCacheMixin, self).renderHTTP(request))
- def _getResponseCache(response):
- d1 = request.locateResource("/")
- d1.addCallback(lambda resource: resource.responseCache)
- d1.addCallback(_cacheResponse, response)
- return d1
+ if request.method == 'PROPFIND':
+ resource = (yield request.locateResource("/"))
- d = maybeDeferred(super(PropfindCacheMixin, self).renderHTTP, request)
+ # responseCache might not be present during unit tests
+ if hasattr(resource, "responseCache"):
+ yield resource.responseCache.cacheResponseForRequest(request, response)
- if request.method == 'PROPFIND':
- d.addCallback(_getResponseCache)
- return d
+ returnValue(response)
def changeCache(self):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/customxml.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/customxml.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -468,8 +468,6 @@
-
-
PrincipalPropertySearch.allowed_children[(calendarserver_namespace, "limit")] = (0, 1)
PrincipalPropertySearch.allowed_attributes["type"] = False
Match.allowed_attributes = {
@@ -1460,6 +1458,7 @@
ResourceType.sharedownercalendar = ResourceType(Collection(), caldavxml.Calendar(), SharedOwner())
ResourceType.sharedcalendar = ResourceType(Collection(), caldavxml.Calendar(), Shared())
+ResourceType.sharedowneraddressbook = ResourceType(Collection(), carddavxml.AddressBook(), SharedOwner())
ResourceType.sharedaddressbook = ResourceType(Collection(), carddavxml.AddressBook(), Shared())
ResourceType.link = ResourceType(Link())
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/aggregate.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/aggregate.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -119,6 +119,37 @@
addressBookHomesCollection = property(_getAddressBookHomesCollection, _setAddressBookHomesCollection)
+
+ def addService(self, service):
+ """
+ Add another service to this aggregate.
+
+ @param service: the service to add
+ @type service: L{IDirectoryService}
+ """
+ service = IDirectoryService(service)
+
+ if service.realmName != self.realmName:
+ assert self.realmName is None, (
+ "Aggregated directory services must have the same realm name: %r != %r\nServices: %r"
+ % (service.realmName, self.realmName, service)
+ )
+
+ if not hasattr(service, "recordTypePrefix"):
+ service.recordTypePrefix = ""
+ prefix = service.recordTypePrefix
+
+ for recordType in (prefix + r for r in service.recordTypes()):
+ if recordType in self._recordTypes:
+ raise DuplicateRecordTypeError(
+ "%r is in multiple services: %s, %s"
+ % (recordType, self.recordTypes[recordType], service)
+ )
+ self._recordTypes[recordType] = service
+
+ service.aggregateService = self
+
+
def recordTypes(self):
return set(self._recordTypes)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -88,8 +88,7 @@
)
# See if this property is on the shared calendar
- isShared = yield self.isShared(request)
- if isShared:
+ if self.isShared():
yield self.validateInvites(request)
invitations = yield self._allInvitations()
returnValue(customxml.Invite(
@@ -117,25 +116,21 @@
returnValue(None)
+ @inlineCallbacks
def upgradeToShare(self):
"""
Set the resource-type property on this resource to indicate that this
is the owner's version of a resource which has been shared.
"""
- # Change resourcetype
- rtype = self.resourceType()
- rtype = element.ResourceType(*(rtype.children + (customxml.SharedOwner(),)))
- self.writeDeadProperty(rtype)
+ # Change status on store object
+ yield self._newStoreObject.setShared(True)
@inlineCallbacks
def downgradeFromShare(self, request):
- # Change resource type (note this might be called after deleting a resource
- # so we have to cope with that)
- rtype = self.resourceType()
- rtype = element.ResourceType(*([child for child in rtype.children if child != customxml.SharedOwner()]))
- self.writeDeadProperty(rtype)
+ # Change status on store object
+ yield self._newStoreObject.setShared(False)
# Remove all invitees
for invitation in (yield self._allInvitations()):
@@ -146,8 +141,7 @@
@inlineCallbacks
def changeUserInviteState(self, request, inviteUID, shareeUID, state, summary=None):
- shared = (yield self.isShared(request))
- if not shared:
+ if not self.isShared():
raise HTTPError(ErrorResponse(
responsecode.FORBIDDEN,
(customxml.calendarserver_namespace, "valid-request"),
@@ -241,12 +235,11 @@
returnValue(response)
- @inlineCallbacks
- def isShared(self, request):
+ def isShared(self):
"""
Return True if this is an owner shared calendar collection.
"""
- returnValue((yield self.isSpecialCollection(customxml.SharedOwner)))
+ return self._newStoreObject.isShared() if self._newStoreObject else False
def setShare(self, share):
@@ -278,26 +271,6 @@
returnValue((yield shareeHome.removeShare(request, self._share)))
- def resourceType(self):
- superObject = super(SharedCollectionMixin, self)
- try:
- superMethod = superObject.resourceType
- except AttributeError:
- rtype = element.ResourceType()
- else:
- rtype = superMethod()
-
- isShareeCollection = self.isShareeCollection()
- if isShareeCollection:
- rtype = element.ResourceType(
- *(
- tuple([child for child in rtype.children if child.qname() != customxml.SharedOwner.qname()]) +
- (customxml.Shared(),)
- )
- )
- return rtype
-
-
def sharedResourceType(self):
"""
Return the DAV:resourcetype stripped of any shared elements.
@@ -896,11 +869,11 @@
numRecords = (yield self.validateInvites(request))
# Set the sharing state on the collection
- shared = (yield self.isShared(request))
+ shared = self.isShared()
if shared and numRecords == 0:
yield self.downgradeFromShare(request)
elif not shared and numRecords != 0:
- self.upgradeToShare()
+ yield self.upgradeToShare()
# Create the multistatus response - only needed if some are bad
if badusers:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -70,7 +70,7 @@
UIDExistsElsewhereError, InvalidUIDError, InvalidResourceMove, \
InvalidComponentForStoreError
from txdav.idav import PropertyChangeNotAllowedError
-from txdav.xml import element as davxml
+from txdav.xml import element as davxml, element
from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
from urlparse import urlsplit
@@ -494,7 +494,7 @@
# Now do normal delete
# Handle sharing
- wasShared = (yield self.isShared(request))
+ wasShared = self.isShared()
if wasShared:
yield self.downgradeFromShare(request)
@@ -1085,6 +1085,15 @@
return True
+ def resourceType(self):
+ if self.isShared():
+ return customxml.ResourceType.sharedownercalendar
+ elif self.isShareeCollection():
+ return customxml.ResourceType.sharedcalendar
+ else:
+ return caldavxml.ResourceType.calendar
+
+
@inlineCallbacks
def iCalendarRolledup(self, request):
# FIXME: uncached: implement cache in the storage layer
@@ -2905,6 +2914,15 @@
"""
return True
+
+ def resourceType(self):
+ if self.isShared():
+ return customxml.ResourceType.sharedowneraddressbook
+ elif self.isShareeCollection():
+ return customxml.ResourceType.sharedaddressbook
+ else:
+ return carddavxml.ResourceType.addressbook
+
createAddressBookCollection = _CommonHomeChildCollectionMixin.createCollection
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookmultiget.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookmultiget.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookmultiget.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -15,27 +15,22 @@
##
import os
-import shutil
from twext.web2 import responsecode
from twext.web2.iweb import IResponse
from twext.web2.stream import MemoryStream
from txdav.xml import element as davxml
-from twext.web2.dav.fileop import rmdir
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.test.test_server import SimpleRequest
+from twext.web2.dav.util import davXMLFromStream, joinURL
from twistedcaldav import carddavxml
from twistedcaldav import vcard
-# FIXME: remove this, we should not be importing this module, we should be
-# testing the public API. See comments below about cheating.
-from txdav.carddav.datastore.index_file import db_basename
-
from twistedcaldav.config import config
-from twistedcaldav.test.util import AddressBookHomeTestCase
+from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
+from twisted.python.filepath import FilePath
+from twisted.internet.defer import inlineCallbacks, returnValue
-class AddressBookMultiget (AddressBookHomeTestCase):
+class AddressBookMultiget (StoreTestCase):
"""
addressbook-multiget REPORT
"""
@@ -53,6 +48,7 @@
return self.simple_vcard_multiget("/addressbook_multiget_vcards/", okuids, baduids)
+
def test_multiget_all_vcards(self):
"""
All vcards.
@@ -63,6 +59,7 @@
return self.simple_vcard_multiget("/addressbook_multiget_vcards/", okuids, baduids)
+
def test_multiget_limited_with_data(self):
"""
All vcards.
@@ -85,6 +82,7 @@
d.addCallbacks(_restoreValueOK, _restoreValueError)
return d
+
def test_multiget_limited_no_data(self):
"""
All vcards.
@@ -105,7 +103,11 @@
return self.simple_vcard_multiget("/addressbook_multiget_vcards/", okuids, baduids, withData=False)
+
def simple_vcard_multiget(self, vcard_uri, okuids, baduids, data=None, no_init=False, withData=True):
+
+ vcard_uri = joinURL("/addressbooks/users/wsanchez", vcard_uri)
+
props = (
davxml.GETETag(),
)
@@ -115,14 +117,14 @@
)
children = []
children.append(davxml.PropertyContainer(*props))
-
+
okhrefs = [vcard_uri + x + ".vcf" for x in okuids]
badhrefs = [vcard_uri + x + ".vcf" for x in baduids]
for href in okhrefs + badhrefs:
children.append(davxml.HRef.fromString(href))
-
+
query = carddavxml.AddressBookMultiGet(*children)
-
+
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,))
@@ -140,7 +142,8 @@
for property in properties:
qname = property.qname()
- if qname == (davxml.dav_namespace, "getetag"): continue
+ if qname == (davxml.dav_namespace, "getetag"):
+ continue
if qname != (carddavxml.carddav_namespace, "address-data"):
self.fail("Response included unexpected property %r" % (property,))
@@ -163,7 +166,7 @@
original_address = vcard.Component.fromStream(original_filename)
self.assertEqual(result_address, original_address)
-
+
for response in doc.root_element.childrenOfType(davxml.StatusResponse):
href = str(response.childOfType(davxml.HRef))
propstatus = response.childOfType(davxml.PropertyStatus)
@@ -181,58 +184,17 @@
continue
else:
self.fail("Got unexpected href %r" % (href,))
-
+
if withData and (len(okuids) + len(badhrefs)):
self.fail("Some components were not returned: %r, %r" % (okuids, badhrefs))
return self.addressbook_query(vcard_uri, query, got_xml, data, no_init)
+
+ @inlineCallbacks
def addressbook_query(self, addressbook_uri, query, got_xml, data, no_init):
- addressbook_path = os.path.join(self.docroot, addressbook_uri[1:])
- if not no_init and os.path.exists(addressbook_path): rmdir(addressbook_path)
-
- def do_report(response):
- if not no_init:
- response = IResponse(response)
-
- if response.code != responsecode.CREATED:
- self.fail("MKCOL failed: %s" % (response.code,))
-
- if data:
- for filename, icaldata in data.iteritems():
- path = os.path.join(addressbook_path, filename + ".vcf")
- f = open(path, "w")
- f.write(icaldata)
- f.close()
- else:
- # Add vcards to addressbook
- # We're cheating by simply copying the files in
- for filename in os.listdir(self.vcards_dir):
- if os.path.splitext(filename)[1] != ".vcf": continue
- path = os.path.join(self.vcards_dir, filename)
- shutil.copy(path, addressbook_path)
-
- # Delete the index because we cheated
- index_path = os.path.join(addressbook_path, db_basename)
- if os.path.isfile(index_path): os.remove(index_path)
-
- request = SimpleRequest(self.site, "REPORT", addressbook_uri)
- request.stream = MemoryStream(query.toxml())
-
- def do_test(response):
- response = IResponse(response)
-
- if response.code != responsecode.MULTI_STATUS:
- self.fail("REPORT failed: %s" % (response.code,))
-
- return davXMLFromStream(response.stream).addCallback(got_xml)
-
- return self.send(request, do_test)
-
- if no_init:
- return do_report(None)
- else:
+ if not no_init:
mkcol = """<?xml version="1.0" encoding="utf-8" ?>
<D:mkcol xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
<D:set>
@@ -242,6 +204,36 @@
</D:set>
</D:mkcol>
"""
- request = SimpleRequest(self.site, "MKCOL", addressbook_uri, content=mkcol)
-
- return self.send(request, do_report)
+ response = yield self.send(SimpleStoreRequest(self, "MKCOL", addressbook_uri, content=mkcol, authid="wsanchez"))
+
+ response = IResponse(response)
+
+ if response.code != responsecode.CREATED:
+ self.fail("MKCOL failed: %s" % (response.code,))
+
+ if data:
+ for filename, icaldata in data.iteritems():
+ request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, filename + ".vcf"), authid="wsanchez")
+ request.stream = MemoryStream(icaldata)
+ yield self.send(request)
+ else:
+ # Add vcards to addressbook
+ for child in FilePath(self.vcards_dir).children():
+ if os.path.splitext(child.basename())[1] != ".vcf":
+ continue
+ request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, child.basename()), authid="wsanchez")
+ request.stream = MemoryStream(child.getContent())
+ yield self.send(request)
+
+ request = SimpleStoreRequest(self, "REPORT", addressbook_uri, authid="wsanchez")
+ request.stream = MemoryStream(query.toxml())
+ response = yield self.send(request)
+
+ response = IResponse(response)
+
+ if response.code != responsecode.MULTI_STATUS:
+ self.fail("REPORT failed: %s" % (response.code,))
+
+ returnValue(
+ (yield davXMLFromStream(response.stream).addCallback(got_xml))
+ )
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookquery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookquery.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_addressbookquery.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -15,25 +15,20 @@
##
import os
-import shutil
from twext.web2 import responsecode
from twext.web2.iweb import IResponse
from twext.web2.stream import MemoryStream
from txdav.xml import element as davxml
-from twext.web2.dav.fileop import rmdir
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.test.test_server import SimpleRequest
+from twext.web2.dav.util import davXMLFromStream, joinURL
-# FIXME: remove this, we should not be importing this module, we should be
-# testing the public API. See comments below about cheating.
-from txdav.carddav.datastore.index_file import db_basename
-
from twistedcaldav import carddavxml, vcard
from twistedcaldav.config import config
-from twistedcaldav.test.util import AddressBookHomeTestCase
+from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.python.filepath import FilePath
-class AddressBookQuery (AddressBookHomeTestCase):
+class AddressBookQuery(StoreTestCase):
"""
addressbook-query REPORT
"""
@@ -55,6 +50,7 @@
[uid]
)
+
def test_addressbook_query_all_vcards(self):
"""
All vCards.
@@ -63,11 +59,12 @@
return self.simple_vcard_query("/addressbook_query_vcards/", None, uids)
+
def test_addressbook_query_limited_with_data(self):
"""
All vCards.
"""
-
+
oldValue = config.MaxQueryWithDataResults
config.MaxQueryWithDataResults = 1
def _restoreValueOK(f):
@@ -84,11 +81,12 @@
d.addCallbacks(_restoreValueOK, _restoreValueError)
return d
+
def test_addressbook_query_limited_without_data(self):
"""
All vCards.
"""
-
+
oldValue = config.MaxQueryWithDataResults
config.MaxQueryWithDataResults = 1
def _restoreValueOK(f):
@@ -105,7 +103,11 @@
d.addCallbacks(_restoreValueOK, _restoreValueError)
return d
- def simple_vcard_query(self, cal_uri, vcard_filter, uids, withData=True, limit=None):
+
+ def simple_vcard_query(self, vcard_uri, vcard_filter, uids, withData=True, limit=None):
+
+ vcard_uri = joinURL("/addressbooks/users/wsanchez", vcard_uri)
+
props = (
davxml.GETETag(),
)
@@ -142,7 +144,8 @@
for property in properties:
qname = property.qname()
- if qname == (davxml.dav_namespace, "getetag"): continue
+ if qname == (davxml.dav_namespace, "getetag"):
+ continue
if qname != (carddavxml.carddav_namespace, "address-data"):
self.fail("Response included unexpected property %r" % (property,))
@@ -165,44 +168,13 @@
if limit is not None and count != limit:
self.fail("Wrong number of limited results: %d" % (count,))
-
- return self.addressbook_query(cal_uri, query, got_xml)
- def addressbook_query(self, addressbook_uri, query, got_xml):
- addressbook_path = os.path.join(self.docroot, addressbook_uri[1:])
+ return self.addressbook_query(vcard_uri, query, got_xml)
- if os.path.exists(addressbook_path): rmdir(addressbook_path)
- def do_report(response):
- response = IResponse(response)
+ @inlineCallbacks
+ def addressbook_query(self, addressbook_uri, query, got_xml):
- if response.code != responsecode.CREATED:
- self.fail("MKCOL failed: %s" % (response.code,))
-
- # Add vCards to addressbook
- # We're cheating by simply copying the files in
- for filename in os.listdir(self.vcards_dir):
- if os.path.splitext(filename)[1] != ".vcf": continue
- path = os.path.join(self.vcards_dir, filename)
- shutil.copy(path, addressbook_path)
-
- # Delete the index because we cheated
- index_path = os.path.join(addressbook_path, db_basename)
- if os.path.isfile(index_path): os.remove(index_path)
-
- request = SimpleRequest(self.site, "REPORT", addressbook_uri)
- request.stream = MemoryStream(query.toxml())
-
- def do_test(response):
- response = IResponse(response)
-
- if response.code != responsecode.MULTI_STATUS:
- self.fail("REPORT failed: %s" % (response.code,))
-
- return davXMLFromStream(response.stream).addCallback(got_xml)
-
- return self.send(request, do_test)
-
mkcol = """<?xml version="1.0" encoding="utf-8" ?>
<D:mkcol xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
<D:set>
@@ -212,6 +184,30 @@
</D:set>
</D:mkcol>
"""
- request = SimpleRequest(self.site, "MKCOL", addressbook_uri, content=mkcol)
+ response = yield self.send(SimpleStoreRequest(self, "MKCOL", addressbook_uri, content=mkcol, authid="wsanchez"))
- return self.send(request, do_report)
+ response = IResponse(response)
+
+ if response.code != responsecode.CREATED:
+ self.fail("MKCOL failed: %s" % (response.code,))
+
+ # Add vCards to addressbook
+ for child in FilePath(self.vcards_dir).children():
+ if os.path.splitext(child.basename())[1] != ".vcf":
+ continue
+ request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, child.basename()), authid="wsanchez")
+ request.stream = MemoryStream(child.getContent())
+ yield self.send(request)
+
+ request = SimpleStoreRequest(self, "REPORT", addressbook_uri, authid="wsanchez")
+ request.stream = MemoryStream(query.toxml())
+ response = yield self.send(request)
+
+ response = IResponse(response)
+
+ if response.code != responsecode.MULTI_STATUS:
+ self.fail("REPORT failed: %s" % (response.code,))
+
+ returnValue(
+ (yield davXMLFromStream(response.stream).addCallback(got_xml))
+ )
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_mkcalendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_mkcalendar.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_mkcalendar.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -23,12 +23,11 @@
from twext.web2.stream import MemoryStream
from txdav.xml import element as davxml
from twext.web2.dav.fileop import rmdir
-from twext.web2.test.test_server import SimpleRequest
from twistedcaldav import caldavxml
-from twistedcaldav.test.util import HomeTestCase
+from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
-class MKCALENDAR (HomeTestCase):
+class MKCALENDAR (StoreTestCase):
"""
MKCALENDAR request
"""
@@ -40,13 +39,13 @@
"""
Make calendar
"""
- uri = "/calendar_make/"
+ uri = "/calendars/users/user01/calendar_make/"
path = os.path.join(self.docroot, uri[1:])
if os.path.exists(path):
rmdir(path)
- request = SimpleRequest(self.site, "MKCALENDAR", uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", uri, authid="user01")
@inlineCallbacks
def do_test(response):
@@ -65,11 +64,12 @@
return self.send(request, do_test)
+
def test_make_calendar_with_props(self):
"""
Make calendar with properties (CalDAV-access-09, section 5.3.1.2)
"""
- uri = "/calendar_prop/"
+ uri = "/calendars/users/user01/calendar_prop/"
path = os.path.join(self.docroot, uri[1:])
if os.path.exists(path):
@@ -110,7 +110,7 @@
tz = tz.calendar()
self.failUnless(tz.resourceType() == "VTIMEZONE")
self.failUnless(tuple(tz.subcomponents())[0].propertyValue("TZID") == "US-Eastern")
-
+
mk = caldavxml.MakeCalendar(
davxml.Set(
davxml.PropertyContainer(
@@ -146,7 +146,7 @@
)
)
- request = SimpleRequest(self.site, "MKCALENDAR", uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", uri, authid="user01")
request.stream = MemoryStream(mk.toxml())
return self.send(request, do_test)
@@ -155,12 +155,8 @@
"""
Make calendar on existing collection
"""
- uri = "/calendar_on_resource/"
- path = os.path.join(self.docroot, uri[1:])
+ uri = "/calendars/users/user01/calendar/"
- if not os.path.exists(path):
- os.mkdir(path)
-
def do_test(response):
response = IResponse(response)
@@ -169,18 +165,17 @@
# FIXME: Check for DAV:resource-must-be-null element
- request = SimpleRequest(self.site, "MKCALENDAR", uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", uri, authid="user01")
return self.send(request, do_test)
+
def test_make_calendar_in_calendar(self):
"""
Make calendar in calendar
"""
- first_uri = "/calendar_in_calendar/"
- first_path = os.path.join(self.docroot, first_uri[1:])
+ first_uri = "/calendars/users/user01/calendar_in_calendar/"
- if os.path.exists(first_path): rmdir(first_path)
-
+ @inlineCallbacks
def next(response):
response = IResponse(response)
@@ -193,10 +188,10 @@
if response.code != responsecode.FORBIDDEN:
self.fail("Incorrect response to nested MKCALENDAR: %s" % (response.code,))
- nested_uri = os.path.join(first_uri, "nested")
+ nested_uri = os.path.join(first_uri, "nested")
- request = SimpleRequest(self.site, "MKCALENDAR", nested_uri)
- self.send(request, do_test)
+ request = SimpleStoreRequest(self, "MKCALENDAR", nested_uri, authid="user01")
+ yield self.send(request, do_test)
- request = SimpleRequest(self.site, "MKCALENDAR", first_uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", first_uri, authid="user01")
return self.send(request, next)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_props.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_props.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_props.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -14,20 +14,17 @@
# limitations under the License.
##
+from twext.web2 import responsecode, http_headers
+from twext.web2.dav.util import davXMLFromStream
+from twext.web2.iweb import IResponse
from twext.web2.stream import MemoryStream
-import os
+from twistedcaldav import caldavxml
+from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
-from twext.web2 import responsecode, http_headers
-from twext.web2.iweb import IResponse
from txdav.xml import element as davxml
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.test.test_server import SimpleRequest
-from twistedcaldav import caldavxml
-from twistedcaldav.test.util import HomeTestCase
-
-class Properties(HomeTestCase):
+class Properties(StoreTestCase):
"""
CalDAV properties
"""
@@ -35,8 +32,7 @@
"""
Live CalDAV properties
"""
- calendar_path, calendar_uri = self.mkdtemp("live_props")
- os.rmdir(calendar_path)
+ calendar_uri = "/calendars/users/user01/test/"
def mkcalendar_cb(response):
response = IResponse(response)
@@ -116,7 +112,7 @@
cal_multiget = True
if report.childOfType(caldavxml.FreeBusyQuery) is not None:
cal_freebusy = True
-
+
if not cal_query:
self.fail("Expected CalDAV:CalendarQuery element; but got none.")
if not cal_multiget:
@@ -134,24 +130,25 @@
),
)
- request = SimpleRequest(
- self.site,
+ request = SimpleStoreRequest(
+ self,
"PROPFIND",
calendar_uri,
- headers=http_headers.Headers({"Depth":"0"}),
+ headers=http_headers.Headers({"Depth": "0"}),
+ authid="user01",
)
request.stream = MemoryStream(query.toxml())
return self.send(request, propfind_cb)
- request = SimpleRequest(self.site, "MKCALENDAR", calendar_uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", calendar_uri, authid="user01")
return self.send(request, mkcalendar_cb)
+
def test_all_props(self):
"""
Live CalDAV properties
"""
- calendar_path, calendar_uri = self.mkdtemp("all_props")
- os.rmdir(calendar_path)
+ calendar_uri = "/calendars/users/user01/test/"
def mkcalendar_cb(response):
response = IResponse(response)
@@ -205,15 +202,15 @@
davxml.AllProperties(),
)
- request = SimpleRequest(
- self.site,
+ request = SimpleStoreRequest(
+ self,
"PROPFIND",
calendar_uri,
- headers=http_headers.Headers({"Depth":"0"}),
+ headers=http_headers.Headers({"Depth": "0"}),
+ authid="user01",
)
request.stream = MemoryStream(query.toxml())
return self.send(request, propfind_cb)
- request = SimpleRequest(self.site, "MKCALENDAR", calendar_uri)
+ request = SimpleStoreRequest(self, "MKCALENDAR", calendar_uri, authid="user01")
return self.send(request, mkcalendar_cb)
-
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_resource.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_resource.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -24,7 +24,8 @@
from twistedcaldav.config import config
from twistedcaldav.resource import CalDAVResource, CommonHomeResource, \
CalendarHomeResource, AddressBookHomeResource
-from twistedcaldav.test.util import InMemoryPropertyStore
+from twistedcaldav.test.util import InMemoryPropertyStore, StoreTestCase, \
+ SimpleStoreRequest
from twistedcaldav.test.util import TestCase
from twistedcaldav.notifications import NotificationCollectionResource
@@ -182,21 +183,15 @@
-class DefaultAddressBook (TestCase):
+class DefaultAddressBook (StoreTestCase):
- def setUp(self):
- super(DefaultAddressBook, self).setUp()
- self.createStockDirectoryService()
- self.setupCalendars()
-
-
@inlineCallbacks
def test_pick_default_addressbook(self):
"""
Make calendar
"""
- request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ request = SimpleStoreRequest(self, "GET", "/addressbooks/users/wsanchez/", authid="wsanchez")
home = yield request.locateResource("/addressbooks/users/wsanchez")
# default property initially not present
@@ -216,16 +211,14 @@
else:
self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/addressbook/")
- request._newStoreTransaction.abort()
-
@inlineCallbacks
def test_pick_default_other(self):
"""
Make adbk
"""
- request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ request = SimpleStoreRequest(self, "GET", "/addressbooks/users/wsanchez/", authid="wsanchez")
home = yield request.locateResource("/addressbooks/users/wsanchez")
# default property not present
@@ -242,10 +235,9 @@
home.writeDeadProperty(carddavxml.DefaultAddressBookURL(
HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
))
- request._newStoreTransaction.commit()
# Delete the normal adbk
- request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ request = SimpleStoreRequest(self, "GET", "/addressbooks/users/wsanchez/", authid="wsanchez")
home = yield request.locateResource("/addressbooks/users/wsanchez")
adbk = yield request.locateResource("/addressbooks/users/wsanchez/addressbook")
yield adbk.storeRemove(request)
@@ -259,9 +251,10 @@
pass
else:
self.fail("carddavxml.DefaultAddressBookURL is not empty")
- request._newStoreTransaction.commit()
- request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ yield self.commit()
+
+ request = SimpleStoreRequest(self, "GET", "/addressbooks/users/wsanchez/", authid="wsanchez")
home = yield request.locateResource("/addressbooks/users/wsanchez")
yield home.pickNewDefaultAddressBook(request)
@@ -272,16 +265,14 @@
else:
self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
- request._newStoreTransaction.abort()
-
@inlineCallbacks
def test_fix_shared_default(self):
"""
Make calendar
"""
- request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ request = SimpleStoreRequest(self, "GET", "/addressbooks/users/wsanchez/", authid="wsanchez")
home = yield request.locateResource("/addressbooks/users/wsanchez")
# Create a new default adbk
@@ -306,5 +297,3 @@
self.fail("carddavxml.DefaultAddressBookURL is not present")
else:
self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/addressbook/")
-
- request._newStoreTransaction.abort()
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_sharing.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/test/test_sharing.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -14,28 +14,28 @@
# limitations under the License.
##
-from xml.etree.cElementTree import XML
-
-from txdav.xml import element as davxml
-from txdav.xml.parser import WebDAVDocument
-
from twext.web2 import responsecode
-from twext.web2.test.test_server import SimpleRequest
+from twext.web2.dav.util import allDataFromStream
+from twext.web2.http_headers import MimeType
+from twext.web2.iweb import IResponse
from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+
from twistedcaldav import customxml
+from twistedcaldav import sharing
from twistedcaldav.config import config
-from twistedcaldav.test.util import HomeTestCase, norequest
-from twistedcaldav import sharing
+from twistedcaldav.resource import CalDAVResource
from twistedcaldav.sharing import WikiDirectoryService
+from twistedcaldav.test.test_cache import StubResponseCacheResource
+from twistedcaldav.test.util import norequest, StoreTestCase, SimpleStoreRequest
-from twistedcaldav.resource import CalDAVResource
-
-from txdav.common.datastore.test.util import buildStore, StubNotifierFactory
from txdav.caldav.icalendarstore import BIND_DIRECT
-from twistedcaldav.test.test_cache import StubResponseCacheResource
+from txdav.xml import element as davxml
+from txdav.xml.parser import WebDAVDocument
+from xml.etree.cElementTree import XML
+
sharedOwnerType = davxml.ResourceType.sharedownercalendar #@UndefinedVariable
regularCalendarType = davxml.ResourceType.calendar #@UndefinedVariable
@@ -91,9 +91,8 @@
@inlineCallbacks
def calendarHome(self, request):
- a, seg = yield self._test.homeProvisioner.locateChild(request,
- ["__uids__"])
- b, seg = yield a.locateChild(request, [self._name])
+ a, _ignore_seg = yield self._test.calendarCollection.locateChild(request, ["__uids__"])
+ b, _ignore_seg = yield a.locateChild(request, [self._name])
if b is None:
# XXX all tests except test_noWikiAccess currently rely on the
# fake thing here.
@@ -114,7 +113,7 @@
-class SharingTests(HomeTestCase):
+class SharingTests(StoreTestCase):
def configure(self):
"""
@@ -127,8 +126,6 @@
@inlineCallbacks
def setUp(self):
- self.calendarStore = yield buildStore(self, StubNotifierFactory())
-
yield super(SharingTests, self).setUp()
def patched(c):
@@ -177,11 +174,9 @@
def principalForUID(resourceSelf, principalUID):
return FakePrincipal("urn:uuid:" + principalUID, self)
+ self.resource = yield self._getResource()
- def createDataStore(self):
- return self.calendarStore
-
@inlineCallbacks
def _refreshRoot(self, request=None):
if request is None:
@@ -195,11 +190,31 @@
returnValue(result)
+ @inlineCallbacks
def _doPOST(self, body, resultcode=responsecode.OK):
- return self.simpleSend("POST", "/calendar/", body,
- resultcode=resultcode)
+ request = SimpleStoreRequest(self, "POST", "/calendars/__uids__/user01/calendar/", content=body, authid="user01")
+ request.headers.setHeader("content-type", MimeType("text", "xml"))
+ response = yield self.send(request)
+ response = IResponse(response)
+ self.assertEqual(response.code, resultcode)
+ # Reload resource
+ self.resource = yield self._getResource()
+ if response.stream:
+ data = yield allDataFromStream(response.stream)
+ returnValue(data)
+ else:
+ returnValue(None)
+
+
+ @inlineCallbacks
+ def _getResource(self):
+ request = SimpleStoreRequest(self, "GET", "/calendars/__uids__/user01/calendar/")
+ resource = yield request.locateResource("/calendars/__uids__/user01/calendar/")
+ returnValue(resource)
+
+
def _clearUIDElementValue(self, xml):
for user in xml.children:
@@ -214,16 +229,16 @@
rtype = self.resource.resourceType()
self.assertEquals(rtype, regularCalendarType)
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertFalse(isShared)
isShareeCollection = self.resource.isShareeCollection()
self.assertFalse(isShareeCollection)
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
rtype = self.resource.resourceType()
self.assertEquals(rtype, sharedOwnerType)
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
isShareeCollection = self.resource.isShareeCollection()
self.assertFalse(isShareeCollection)
@@ -232,11 +247,11 @@
@inlineCallbacks
def test_downgradeFromShare(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
rtype = self.resource.resourceType()
self.assertEquals(rtype, sharedOwnerType)
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
isShareeCollection = self.resource.isShareeCollection()
self.assertFalse(isShareeCollection)
@@ -245,7 +260,7 @@
rtype = self.resource.resourceType()
self.assertEquals(rtype, regularCalendarType)
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertFalse(isShared)
isShareeCollection = self.resource.isShareeCollection()
self.assertFalse(isShareeCollection)
@@ -254,7 +269,7 @@
@inlineCallbacks
def test_POSTaddInviteeAlreadyShared(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
@@ -277,7 +292,7 @@
)
))
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
isShareeCollection = self.resource.isShareeCollection()
self.assertFalse(isShareeCollection)
@@ -307,7 +322,7 @@
)
))
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
isShareeCollection = (yield self.resource.isShareeCollection())
self.assertFalse(isShareeCollection)
@@ -316,7 +331,7 @@
@inlineCallbacks
def test_POSTupdateInvitee(self):
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertFalse(isShared)
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
@@ -329,7 +344,7 @@
</CS:share>
""")
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
@@ -342,7 +357,7 @@
</CS:share>
""")
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
propInvite = (yield self.resource.readProperty(customxml.Invite, None))
@@ -360,7 +375,7 @@
@inlineCallbacks
def test_POSTremoveInvitee(self):
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertFalse(isShared)
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
@@ -373,7 +388,7 @@
</CS:share>
""")
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertTrue(isShared)
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
@@ -384,7 +399,7 @@
</CS:share>
""")
- isShared = (yield self.resource.isShared(None))
+ isShared = self.resource.isShared()
self.assertFalse(isShared)
propInvite = (yield self.resource.readProperty(customxml.Invite, None))
@@ -394,7 +409,7 @@
@inlineCallbacks
def test_POSTaddMoreInvitees(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
@@ -449,7 +464,7 @@
@inlineCallbacks
def test_POSTaddRemoveInvitees(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
@@ -496,10 +511,11 @@
),
))
+
@inlineCallbacks
def test_POSTaddRemoveSameInvitee(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
@@ -555,7 +571,7 @@
removed the sharee.
"""
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
@@ -595,7 +611,7 @@
@inlineCallbacks
def test_POSTaddInvalidInvitee(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
data = (yield self._doPOST(
"""<?xml version="1.0" encoding="utf-8" ?>
@@ -633,12 +649,12 @@
@inlineCallbacks
def test_POSTremoveInvalidInvitee(self):
- self.resource.upgradeToShare()
+ yield self.resource.upgradeToShare()
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
<CS:set>
- <D:href>mailto:user01 at example.com</D:href>
+ <D:href>mailto:user02 at example.com</D:href>
<CS:summary>My Shared Calendar</CS:summary>
<CS:read-write/>
</CS:set>
@@ -649,8 +665,8 @@
self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
customxml.InviteUser(
customxml.UID.fromString(""),
- davxml.HRef.fromString("urn:uuid:user01"),
- customxml.CommonName.fromString("USER01"),
+ davxml.HRef.fromString("urn:uuid:user02"),
+ customxml.CommonName.fromString("USER02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
)
@@ -664,8 +680,8 @@
self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
customxml.InviteUser(
customxml.UID.fromString(""),
- davxml.HRef.fromString("urn:uuid:user01"),
- customxml.CommonName.fromString("user01"),
+ davxml.HRef.fromString("urn:uuid:user02"),
+ customxml.CommonName.fromString("user02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusInvalid(),
)
@@ -674,7 +690,7 @@
yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
<CS:remove>
- <D:href>mailto:user01 at example.com</D:href>
+ <D:href>mailto:user02 at example.com</D:href>
</CS:remove>
</CS:share>
""")
@@ -690,17 +706,19 @@
home is at /. Return the name of the newly shared calendar in the
sharee's home.
"""
- wcreate = self.calendarStore.newTransaction("create wiki")
+ wcreate = self._sqlCalendarStore.newTransaction("create wiki")
yield wcreate.calendarHomeWithUID("wiki-testing", create=True)
yield wcreate.commit()
- self.directoryFixture.addDirectoryService(WikiDirectoryService())
- txn = self.site.resource._associatedTransaction
- sharee = self.site.resource._newStoreHome
+ newService = WikiDirectoryService()
+ newService.realmName = self.directory.realmName
+ self.directory.addService(newService)
+
+ txn = self.transactionUnderTest()
+ sharee = yield self.homeUnderTest(name="user01")
sharer = yield txn.calendarHomeWithUID("wiki-testing")
cal = yield sharer.calendarWithName("calendar")
sharedName = yield cal.shareWith(sharee, BIND_DIRECT)
- yield self._refreshRoot()
returnValue(sharedName)
@@ -718,8 +736,8 @@
self.patch(sharing, "getWikiAccess", stubWikiAccessMethod)
sharedName = yield self.wikiSetup()
- request = SimpleRequest(self.site, "GET", "/404")
- collection = yield request.locateResource("/" + sharedName)
+ request = SimpleStoreRequest(self, "GET", "/calendars/__uids__/user01/")
+ collection = yield request.locateResource("/calendars/__uids__/user01/" + sharedName)
# Simulate the wiki server granting Read access
acl = (yield collection.shareeAccessControlList(request))
@@ -745,10 +763,12 @@
self.patch(sharing, "getWikiAccess", stubWikiAccessMethod)
@inlineCallbacks
def listChildrenViaPropfind():
- data = yield self.simpleSend(
- "PROPFIND", "/", resultcode=responsecode.MULTI_STATUS,
- headers=[('Depth', '1')]
- )
+ request = SimpleStoreRequest(self, "PROPFIND", "/calendars/__uids__/user01/", authid="user01")
+ request.headers.setHeader("depth", "1")
+ response = yield self.send(request)
+ response = IResponse(response)
+ data = yield allDataFromStream(response.stream)
+
tree = XML(data)
seq = [e.text for e in tree.findall("{DAV:}response/{DAV:}href")]
shortest = min(seq, key=len)
@@ -760,7 +780,3 @@
access = "no-access"
childNames = yield listChildrenViaPropfind()
self.assertNotIn(sharedName, childNames)
-
-
-
-
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/file.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/file.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -37,7 +37,7 @@
from twext.python.vcomponent import VComponent
from txdav.xml import element as davxml
-from txdav.xml.rfc2518 import ResourceType, GETContentType
+from txdav.xml.rfc2518 import GETContentType
from twext.web2.dav.resource import TwistedGETContentMD5
from twext.web2.http_headers import generateContentType, MimeType
@@ -261,10 +261,6 @@
def _calendarHome(self):
return self._home
-
- def resourceType(self):
- return ResourceType.calendar #@UndefinedVariable
-
ownerCalendarHome = CommonHomeChild.ownerHome
viewerCalendarHome = CommonHomeChild.viewerHome
calendarObjects = CommonHomeChild.objectResources
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -92,7 +92,6 @@
ObjectResourceNameNotAllowedError, TooManyObjectResourcesError, \
InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
InvalidResourceMove, InvalidComponentForStoreError
-from txdav.xml.rfc2518 import ResourceType
from pycalendar.datetime import PyCalendarDateTime
from pycalendar.duration import PyCalendarDuration
@@ -914,11 +913,6 @@
def _calendarHome(self):
return self._home
-
- # FIXME: resource type is DAV. This doesn't belong in the data store. -wsv
- def resourceType(self):
- return ResourceType.calendar # @UndefinedVariable
-
ownerCalendarHome = CommonHomeChild.ownerHome
viewerCalendarHome = CommonHomeChild.viewerHome
calendarObjects = CommonHomeChild.objectResources
@@ -1068,6 +1062,7 @@
Where=(cal.CALENDAR_HOME_RESOURCE_ID == self.viewerHome()._resourceID).And(cal.CALENDAR_RESOURCE_ID == self._resourceID)
).on(self._txn)
yield self.invalidateQueryCache()
+ yield self.notifyChanged()
def isUsedForFreeBusy(self):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/common.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/common.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -31,7 +31,7 @@
from twext.python.filepath import CachingFilePath as FilePath
from twext.enterprise.ienterprise import AlreadyFinishedError
-from txdav.xml.element import WebDAVUnknownElement, ResourceType
+from txdav.xml.element import WebDAVUnknownElement
from txdav.idav import IPropertyStore, IDataStore
from txdav.base.propertystore.base import PropertyName
from txdav.common.icommondatastore import HomeChildNameAlreadyExistsError, \
@@ -701,18 +701,8 @@
self.assertIdentical((yield home.calendarWithName(name)), None)
yield home.createCalendarWithName(name)
self.assertNotIdentical((yield home.calendarWithName(name)), None)
- @inlineCallbacks
- def checkProperties():
- calendarProperties = (
- yield home.calendarWithName(name)).properties()
- self.assertEquals(
- calendarProperties[
- PropertyName.fromString(ResourceType.sname())
- ],
- ResourceType.calendar #@UndefinedVariable
- )
- yield checkProperties()
-
+ calendarProperties = (yield home.calendarWithName(name)).properties()
+ self.assertEqual(len(calendarProperties), 0)
yield self.commit()
# Make sure notification fired after commit
@@ -722,14 +712,7 @@
home = yield self.homeUnderTest()
self.assertNotIdentical((yield home.calendarWithName(name)), None)
- # Sanity check: are the properties actually persisted? Check in
- # subsequent transaction.
- yield checkProperties()
- # FIXME: no independent testing of the property store's persistence
- # right now
-
-
@inlineCallbacks
def test_createCalendarWithName_exists(self):
"""
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -782,10 +782,10 @@
From=prop,
Where=prop.RESOURCE_ID == Parameter("resourceID"))
- # Check that two properties are present
+ # Check that one property is present
home = yield self.homeUnderTest()
rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID)
- self.assertEqual(len(tuple(rows)), 2)
+ self.assertEqual(len(tuple(rows)), 1)
yield self.commit()
# Remove calendar and check for no properties
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/file.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/file.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -29,7 +29,7 @@
from errno import ENOENT
-from txdav.xml.rfc2518 import ResourceType, GETContentType
+from txdav.xml.rfc2518 import GETContentType
from twext.web2.dav.resource import TwistedGETContentMD5
from twext.web2.http_headers import MimeType
@@ -121,10 +121,6 @@
def _addressbookHome(self):
return self._home
-
- def resourceType(self):
- return ResourceType.addressbook #@UndefinedVariable
-
ownerAddressBookHome = CommonHomeChild.ownerHome
addressbookObjects = CommonHomeChild.objectResources
listAddressbookObjects = CommonHomeChild.listObjectResources
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/sql.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/sql.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -55,7 +55,6 @@
from txdav.common.icommondatastore import InternalDataStoreError, \
InvalidUIDError, UIDExistsError, ObjectResourceTooBigError, \
InvalidObjectResourceError, InvalidComponentForStoreError
-from txdav.xml.rfc2518 import ResourceType
from zope.interface.declarations import implements
@@ -168,10 +167,6 @@
def _addressbookHome(self):
return self._home
-
- def resourceType(self):
- return ResourceType.addressbook #@UndefinedVariable
-
ownerAddressBookHome = CommonHomeChild.ownerHome
addressbookObjects = CommonHomeChild.objectResources
listAddressbookObjects = CommonHomeChild.listObjectResources
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/common.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/common.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -40,7 +40,7 @@
from twistedcaldav.vcard import Component as VComponent
from twext.python.filepath import CachingFilePath as FilePath
-from txdav.xml.element import WebDAVUnknownElement, ResourceType
+from txdav.xml.element import WebDAVUnknownElement
storePath = FilePath(__file__).parent().child("addressbook_store")
@@ -315,17 +315,8 @@
self.assertIdentical((yield home.addressbookWithName(name)), None)
yield home.createAddressBookWithName(name)
self.assertNotIdentical((yield home.addressbookWithName(name)), None)
- @inlineCallbacks
- def checkProperties():
- addressbookProperties = (yield home.addressbookWithName(name)).properties()
- addressbookType = ResourceType.addressbook #@UndefinedVariable
- self.assertEquals(
- addressbookProperties[
- PropertyName.fromString(ResourceType.sname())
- ],
- addressbookType
- )
- yield checkProperties()
+ addressbookProperties = (yield home.addressbookWithName(name)).properties()
+ self.assertEqual(len(addressbookProperties), 0)
yield self.commit()
# Make sure notification fired after commit
@@ -335,15 +326,7 @@
home = yield self.homeUnderTest()
self.assertNotIdentical((yield home.addressbookWithName(name)), None)
- # FIXME: These two lines aren't in the calendar common tests:
- # home = self.addressbookStore.newTransaction().addressbookHomeWithUID(
- # "home1")
- # Sanity check: are the properties actually persisted?
- # FIXME: no independent testing of this right now
- yield checkProperties()
-
-
@inlineCallbacks
def test_createAddressBookWithName_exists(self):
"""
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/test_sql.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/carddav/datastore/test/test_sql.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -315,7 +315,7 @@
# Check that two properties are present
home = yield self.homeUnderTest()
rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID)
- self.assertEqual(len(tuple(rows)), 2)
+ self.assertEqual(len(tuple(rows)), 1)
yield self.commit()
# Remove address book and check for no properties
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/file.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/file.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -22,7 +22,7 @@
import sys
from twext.internet.decorate import memoizedKey
from twext.python.log import LoggingMixIn
-from txdav.xml.rfc2518 import ResourceType, GETContentType, HRef
+from txdav.xml.rfc2518 import GETContentType, HRef
from txdav.xml.rfc5842 import ResourceID
from twext.web2.http_headers import generateContentType, MimeType
from twext.web2.dav.resource import TwistedGETContentMD5, \
@@ -826,8 +826,6 @@
return lambda: self._path.child(childPath.basename()).remove()
self._transaction.addOperation(do, "create child %r" % (name,))
- props = c.properties()
- props[PropertyName(*ResourceType.qname())] = c.resourceType()
self.notifyChanged()
return c
@@ -1033,10 +1031,6 @@
return self._transaction.store().directoryService()
- def resourceType(self):
- return NotImplementedError
-
-
def retrieveOldIndex(self):
"""
Retrieve the old Index object.
@@ -1522,14 +1516,8 @@
txn.addOperation(do, "create notification child %r" %
(collectionName,))
- props = c.properties()
- props[PropertyName(*ResourceType.qname())] = c.resourceType()
return c
-
- def resourceType(self):
- return ResourceType.notification #@UndefinedVariable
-
notificationObjects = CommonHomeChild.objectResources
listNotificationObjects = CommonHomeChild.listObjectResources
notificationObjectWithName = CommonHomeChild.objectResourceWithName
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -34,7 +34,6 @@
from twext.python.log import Logger, LoggingMixIn
from twisted.python.log import msg as log_msg, err as log_err
-from txdav.xml.element import ResourceType
from txdav.xml.parser import WebDAVDocument
from twext.web2.http_headers import MimeType
@@ -79,7 +78,6 @@
from twistedcaldav.config import config
-from txdav.base.propertystore.base import PropertyName
from txdav.base.propertystore.none import PropertyStore as NonePropertyStore
from txdav.base.propertystore.sql import PropertyStore
@@ -2899,6 +2897,42 @@
return self._bindMode == _BIND_MODE_OWN
+ def isShared(self):
+ """
+ For an owned collection indicate whether it is shared.
+
+ @return: C{True} if shared, C{False} otherwise
+ @rtype: C{bool}
+ """
+ return self._bindMode == _BIND_MODE_OWN and self._bindMessage == "shared"
+
+
+ @inlineCallbacks
+ def setShared(self, shared):
+ """
+ Set an owned collection to shared or unshared state. Technically this is not useful as "shared"
+ really means it has invitees, but the current sharing spec supports a notion of a shared collection
+ that has not yet had invitees added. For the time being we will support that option by using a new
+ BINS_STATUS value to indicate an owned collection that is "shared".
+
+ @param shared: whether or not the owned collection is "shared"
+ @type shared: C{bool}
+ """
+ assert self.owned()
+
+ self._bindMessage = "shared" if shared else None
+
+ bind = self._bindSchema
+ yield Update(
+ {bind.MESSAGE: self._bindMessage},
+ Where=(bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID")),
+ ).on(self._txn, resourceID=self._resourceID, homeID=self.viewerHome()._resourceID)
+
+ yield self.invalidateQueryCache()
+ yield self.notifyChanged()
+
+
def shareStatus(self):
"""
@see: L{ICalendar.shareStatus}
@@ -3370,9 +3404,6 @@
child._modified = _modified
yield child._loadPropertyStore()
- child.properties()[
- PropertyName.fromElement(ResourceType)
- ] = child.resourceType()
yield child._initSyncToken()
# Change notification for a create is on the home collection
@@ -3442,10 +3473,6 @@
return self._txn.store().directoryService()
- def resourceType(self):
- return NotImplementedError
-
-
def retrieveOldIndex(self):
return self._index
@@ -4639,10 +4666,6 @@
)
- def resourceType(self):
- return ResourceType.notification #@UndefinedVariable
-
-
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -20,7 +20,8 @@
from txdav.xml.element import HRef
from twext.enterprise.dal.syntax import Update
from txdav.common.datastore.upgrade.sql.upgrades.upgrade_from_3_to_4 import moveDefaultCalendarProperties, \
- moveCalendarTranspProperties
+ moveCalendarTranspProperties, removeResourceType
+from txdav.xml import element
"""
Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
@@ -106,3 +107,23 @@
self.assertTrue(calendar.isUsedForFreeBusy())
inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) not in inbox.properties())
+
+
+ @inlineCallbacks
+ def test_resourceTypeUpgrade(self):
+
+ # Set dead property on calendar
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ calendar.properties()[PropertyName.fromElement(element.ResourceType)] = element.ResourceType(element.Collection())
+ yield self.commit()
+
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ self.assertTrue(PropertyName.fromElement(element.ResourceType) in calendar.properties())
+ yield self.commit()
+
+ # Trigger upgrade
+ yield removeResourceType(self._sqlCalendarStore)
+
+ # Test results
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ self.assertTrue(PropertyName.fromElement(element.ResourceType) not in calendar.properties())
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py 2013-05-03 00:45:15 UTC (rev 11126)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py 2013-05-03 18:58:13 UTC (rev 11127)
@@ -26,6 +26,7 @@
from txdav.common.datastore.upgrade.sql.upgrades.util import rowsForProperty, updateDataVersion, \
updateAllCalendarHomeDataVersions, removeProperty, cleanPropertyStore
from txdav.xml.parser import WebDAVDocument
+from txdav.xml import element
"""
Data upgrade from database version 3 to 4
@@ -41,6 +42,7 @@
"""
yield moveDefaultCalendarProperties(sqlStore)
yield moveCalendarTranspProperties(sqlStore)
+ yield removeResourceType(sqlStore)
# Always bump the DB value
yield updateDataVersion(sqlStore, "CALENDAR-DATAVERSION", UPGRADE_TO_VERSION)
@@ -186,3 +188,12 @@
except RuntimeError:
yield sqlTxn.abort()
raise
+
+
+
+ at inlineCallbacks
+def removeResourceType(sqlStore):
+ sqlTxn = sqlStore.newTransaction()
+ yield removeProperty(sqlTxn, PropertyName.fromElement(element.ResourceType))
+ yield sqlTxn.commit()
+ yield cleanPropertyStore()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130503/d3e41a46/attachment-0001.html>
More information about the calendarserver-changes
mailing list