[CalendarServer-changes] [5095] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Feb 12 08:12:34 PST 2010
Revision: 5095
http://trac.macosforge.org/projects/calendarserver/changeset/5095
Author: sagen at apple.com
Date: 2010-02-12 08:12:33 -0800 (Fri, 12 Feb 2010)
Log Message:
-----------
Landing branch with support for reading/writing resource "extra" data.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/gateway.py
CalendarServer/trunk/calendarserver/tools/test/test_gateway.py
CalendarServer/trunk/twistedcaldav/directory/aggregate.py
CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py
CalendarServer/trunk/twistedcaldav/directory/directory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py
CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/trunk/twistedcaldav/directory/xmlfile.py
Property Changed:
----------------
CalendarServer/trunk/
Property changes on: CalendarServer/trunk
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
+ /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
Modified: CalendarServer/trunk/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/gateway.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/calendarserver/tools/gateway.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -125,6 +125,24 @@
reactor.run()
+attrMap = {
+ 'GeneratedUID' : { 'attr' : 'guid', },
+ 'RealName' : { 'attr' : 'fullName', },
+ 'RecordName' : { 'attr' : 'shortNames', },
+ 'Comment' : { 'extras' : True, 'attr' : 'comment', },
+ 'Description' : { 'extras' : True, 'attr' : 'description', },
+ 'Type' : { 'extras' : True, 'attr' : 'type', },
+ 'Capacity' : { 'extras' : True, 'attr' : 'capacity', },
+ 'Building' : { 'extras' : True, 'attr' : 'building', },
+ 'Floor' : { 'extras' : True, 'attr' : 'floor', },
+ 'Street' : { 'extras' : True, 'attr' : 'street', },
+ 'City' : { 'extras' : True, 'attr' : 'city', },
+ 'State' : { 'extras' : True, 'attr' : 'state', },
+ 'ZIP' : { 'extras' : True, 'attr' : 'zip', },
+ 'Country' : { 'extras' : True, 'attr' : 'country', },
+ 'Phone' : { 'extras' : True, 'attr' : 'phone', },
+}
+
class Runner(object):
def __init__(self, directory, commands):
@@ -160,16 +178,48 @@
def command_createLocation(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.createRecord("locations", guid=command['GeneratedUID'],
- shortNames=command['RecordName'], fullName=command['RealName'])
+ self.dir.createRecord("locations", **kwargs)
except DirectoryError, e:
abort(str(e))
respondWithRecordsOfType(self.dir, command, "locations")
+ def command_getLocationAttributes(self, command):
+ guid = command['GeneratedUID']
+ record = self.dir.recordWithGUID(guid)
+ recordDict = recordToDict(record)
+ # principal = principalForPrincipalID(guid, directory=self.dir)
+ # recordDict['AutoSchedule'] = principal.getAutoSchedule()
+ respond(command, recordDict)
+
+ def command_setLocationAttributes(self, command):
+
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
+ try:
+ self.dir.updateRecord("locations", **kwargs)
+ except DirectoryError, e:
+ abort(str(e))
+
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # principal.setAutoSchedule(command.get('AutoSchedule', False))
+
+ respondWithRecordsOfType(self.dir, command, "locations")
+
def command_deleteLocation(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.destroyRecord("locations", guid=command['GeneratedUID'])
+ self.dir.destroyRecord("locations", **kwargs)
except DirectoryError, e:
abort(str(e))
respondWithRecordsOfType(self.dir, command, "locations")
@@ -180,16 +230,48 @@
respondWithRecordsOfType(self.dir, command, "resources")
def command_createResource(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.createRecord("resources", guid=command['GeneratedUID'],
- shortNames=command['RecordName'], fullName=command['RealName'])
+ self.dir.createRecord("resources", **kwargs)
except DirectoryError, e:
abort(str(e))
respondWithRecordsOfType(self.dir, command, "resources")
+ def command_getResourceAttributes(self, command):
+ guid = command['GeneratedUID']
+ record = self.dir.recordWithGUID(guid)
+ recordDict = recordToDict(record)
+ # principal = principalForPrincipalID(guid, directory=self.dir)
+ # recordDict['AutoSchedule'] = principal.getAutoSchedule()
+ respond(command, recordDict)
+
+ def command_setResourceAttributes(self, command):
+
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
+ try:
+ self.dir.updateRecord("resources", **kwargs)
+ except DirectoryError, e:
+ abort(str(e))
+
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # principal.setAutoSchedule(command.get('AutoSchedule', False))
+
+ respondWithRecordsOfType(self.dir, command, "resources")
+
def command_deleteResource(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.destroyRecord("resources", guid=command['GeneratedUID'])
+ self.dir.destroyRecord("resources", **kwargs)
except DirectoryError, e:
abort(str(e))
respondWithRecordsOfType(self.dir, command, "resources")
@@ -271,15 +353,24 @@
})
+def recordToDict(record):
+ recordDict = {}
+ for key, info in attrMap.iteritems():
+ try:
+ if info.get('extras', False):
+ value = record.extras[info['attr']]
+ else:
+ value = getattr(record, info['attr'])
+ recordDict[key] = value
+ except KeyError:
+ pass
+ return recordDict
+
def respondWithRecordsOfType(directory, command, recordType):
result = []
for record in directory.listRecords(recordType):
- result.append( {
- 'GeneratedUID' : record.guid,
- 'RecordName' : [n for n in record.shortNames],
- 'RealName' : record.fullName,
- 'AutoSchedule' : record.autoSchedule,
- } )
+ recordDict = recordToDict(record)
+ result.append(recordDict)
respond(command, result)
def respond(command, result):
Modified: CalendarServer/trunk/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_gateway.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/calendarserver/tools/test/test_gateway.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -185,27 +185,81 @@
self.assertEquals(len(results['result']), 10)
@inlineCallbacks
+ def test_getLocationAttributes(self):
+ results = yield self.runCommand(command_createLocation)
+ results = yield self.runCommand(command_getLocationAttributes)
+ self.assertEquals(results['result']['Building'], "Test Building")
+ self.assertEquals(results['result']['City'], "Cupertino")
+ self.assertEquals(results['result']['Capacity'], "40")
+ self.assertEquals(results['result']['Description'], "Test Description")
+ self.assertEquals(results['result']['ZIP'], "95014")
+ self.assertEquals(results['result']['Floor'], "First")
+ self.assertEquals(results['result']['RecordName'], ['createdlocation01'])
+ self.assertEquals(results['result']['State'], "CA")
+ self.assertEquals(results['result']['Street'], "1 Infinite Loop")
+ self.assertEquals(results['result']['RealName'], "Created Location 01")
+ self.assertEquals(results['result']['Comment'], "Test Comment")
+
+ @inlineCallbacks
def test_getResourceList(self):
results = yield self.runCommand(command_getResourceList)
self.assertEquals(len(results['result']), 10)
@inlineCallbacks
+ def test_getResourceAttributes(self):
+ results = yield self.runCommand(command_createResource)
+ results = yield self.runCommand(command_getResourceAttributes)
+ self.assertEquals(results['result']['Comment'], "Test Comment")
+
+ @inlineCallbacks
def test_createLocation(self):
directory = getDirectory()
- record = directory.recordWithUID("createdlocation01")
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertEquals(record, None)
yield self.runCommand(command_createLocation)
directory.flushCaches()
- record = directory.recordWithUID("createdlocation01")
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertNotEquals(record, None)
+ self.assertEquals(record.extras['comment'], "Test Comment")
+ self.assertEquals(record.extras['building'], "Test Building")
+ self.assertEquals(record.extras['floor'], "First")
+ self.assertEquals(record.extras['capacity'], "40")
+ self.assertEquals(record.extras['street'], "1 Infinite Loop")
+ self.assertEquals(record.extras['city'], "Cupertino")
+ self.assertEquals(record.extras['state'], "CA")
+ self.assertEquals(record.extras['zip'], "95014")
+ self.assertEquals(record.extras['country'], "USA")
+ self.assertEquals(record.extras['phone'], "(408) 555-1212")
+
@inlineCallbacks
- def test_destroyRecord(self):
+ def test_setLocationAttributes(self):
directory = getDirectory()
+ yield self.runCommand(command_createLocation)
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
+ yield self.runCommand(command_setLocationAttributes)
+ directory.flushCaches()
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
+
+ self.assertEquals(record.extras['comment'], "Updated Test Comment")
+ self.assertEquals(record.extras['building'], "Updated Test Building")
+ self.assertEquals(record.extras['floor'], "Second")
+ self.assertEquals(record.extras['capacity'], "41")
+ self.assertEquals(record.extras['street'], "2 Infinite Loop")
+ self.assertEquals(record.extras['city'], "Updated Cupertino")
+ self.assertEquals(record.extras['state'], "Updated CA")
+ self.assertEquals(record.extras['zip'], "95015")
+ self.assertEquals(record.extras['country'], "Updated USA")
+ self.assertEquals(record.extras['phone'], "(408) 555-1213")
+
+ @inlineCallbacks
+ def test_destroyLocation(self):
+ directory = getDirectory()
+
record = directory.recordWithUID("location01")
self.assertNotEquals(record, None)
@@ -216,6 +270,46 @@
self.assertEquals(record, None)
@inlineCallbacks
+ def test_createResource(self):
+ directory = getDirectory()
+
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record, None)
+
+ yield self.runCommand(command_createResource)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertNotEquals(record, None)
+
+ @inlineCallbacks
+ def test_setResourceAttributes(self):
+ directory = getDirectory()
+
+ yield self.runCommand(command_createResource)
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.fullName, "Laptop 1")
+
+ yield self.runCommand(command_setResourceAttributes)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.fullName, "Updated Laptop 1")
+
+ @inlineCallbacks
+ def test_destroyResource(self):
+ directory = getDirectory()
+
+ record = directory.recordWithUID("resource01")
+ self.assertNotEquals(record, None)
+
+ yield self.runCommand(command_deleteResource)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("resource01")
+ self.assertEquals(record, None)
+
+ @inlineCallbacks
def test_addWriteProxy(self):
results = yield self.runCommand(command_addWriteProxy)
self.assertEquals(len(results['result']['Proxies']), 1)
@@ -228,18 +322,6 @@
-command_deleteLocation = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>command</key>
- <string>deleteLocation</string>
- <key>GeneratedUID</key>
- <string>guidoffice3</string>
-</dict>
-</plist>
-"""
-
command_addReadProxy = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
@@ -277,17 +359,40 @@
<key>AutoSchedule</key>
<true/>
<key>GeneratedUID</key>
- <string>createdlocation01</string>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
<key>RealName</key>
<string>Created Location 01</string>
<key>RecordName</key>
<array>
<string>createdlocation01</string>
</array>
+ <key>Comment</key>
+ <string>Test Comment</string>
+ <key>Description</key>
+ <string>Test Description</string>
+ <key>Building</key>
+ <string>Test Building</string>
+ <key>Floor</key>
+ <string>First</string>
+ <key>Capacity</key>
+ <string>40</string>
+ <key>Street</key>
+ <string>1 Infinite Loop</string>
+ <key>City</key>
+ <string>Cupertino</string>
+ <key>State</key>
+ <string>CA</string>
+ <key>ZIP</key>
+ <string>95014</string>
+ <key>Country</key>
+ <string>USA</string>
+ <key>Phone</key>
+ <string>(408) 555-1212</string>
</dict>
</plist>
"""
+
command_createResource = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
@@ -297,13 +402,15 @@
<key>AutoSchedule</key>
<true/>
<key>GeneratedUID</key>
- <string>guidlaptop1</string>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
<key>RealName</key>
<string>Laptop 1</string>
<key>RecordName</key>
<array>
<string>laptop1</string>
</array>
+ <key>Comment</key>
+ <string>Test Comment</string>
</dict>
</plist>
"""
@@ -327,7 +434,7 @@
<key>command</key>
<string>deleteResource</string>
<key>GeneratedUID</key>
- <string>guidlaptop1</string>
+ <string>resource01</string>
</dict>
</plist>
"""
@@ -403,3 +510,89 @@
</dict>
</plist>
"""
+
+command_setLocationAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>setLocationAttributes</string>
+ <key>AutoSchedule</key>
+ <false/>
+ <key>GeneratedUID</key>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
+ <key>RealName</key>
+ <string>Updated Location 01</string>
+ <key>RecordName</key>
+ <array>
+ <string>createdlocation01</string>
+ </array>
+ <key>Comment</key>
+ <string>Updated Test Comment</string>
+ <key>Description</key>
+ <string>Updated Test Description</string>
+ <key>Building</key>
+ <string>Updated Test Building</string>
+ <key>Floor</key>
+ <string>Second</string>
+ <key>Capacity</key>
+ <string>41</string>
+ <key>Street</key>
+ <string>2 Infinite Loop</string>
+ <key>City</key>
+ <string>Updated Cupertino</string>
+ <key>State</key>
+ <string>Updated CA</string>
+ <key>ZIP</key>
+ <string>95015</string>
+ <key>Country</key>
+ <string>Updated USA</string>
+ <key>Phone</key>
+ <string>(408) 555-1213</string>
+</dict>
+</plist>
+"""
+
+command_getLocationAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>getLocationAttributes</string>
+ <key>GeneratedUID</key>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
+</dict>
+</plist>
+"""
+
+command_setResourceAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>setResourceAttributes</string>
+ <key>AutoSchedule</key>
+ <false/>
+ <key>GeneratedUID</key>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
+ <key>RealName</key>
+ <string>Updated Laptop 1</string>
+ <key>RecordName</key>
+ <array>
+ <string>laptop1</string>
+ </array>
+</dict>
+</plist>
+"""
+
+command_getResourceAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>getResourceAttributes</string>
+ <key>GeneratedUID</key>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
+</dict>
+</plist>
+"""
Modified: CalendarServer/trunk/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/aggregate.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/aggregate.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -192,25 +192,26 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
service = self.serviceForRecordType(recordType)
return service.createRecord(recordType, guid=guid,
shortNames=shortNames, authIDs=authIDs, fullName=fullName,
firstName=firstName, lastName=lastName,
- emailAddresses=emailAddresses, uid=uid, password=password, **kwds)
+ emailAddresses=emailAddresses, uid=uid, password=password, **kwargs)
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
service = self.serviceForRecordType(recordType)
- return service.updateRecord(recordType, guid, shortNames=shortNames,
+ return service.updateRecord(recordType, guid=guid,
+ shortNames=shortNames,
authIDs=authIDs, fullName=fullName, firstName=firstName,
lastName=lastName, emailAddresses=emailAddresses, uid=uid,
- password=password, **kwds)
+ password=password, **kwargs)
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
service = self.serviceForRecordType(recordType)
- return service.destroyRecord(recordType, guid)
+ return service.destroyRecord(recordType, guid=guid)
class DuplicateRecordTypeError(DirectoryError):
"""
Modified: CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -357,12 +357,12 @@
self, service, recordType, guid,
shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None,
+ uid=None, **kwargs
):
super(CachingDirectoryRecord, self).__init__(
- service = service,
- recordType = recordType,
- guid = guid,
+ service,
+ recordType,
+ guid,
shortNames = shortNames,
authIDs = authIDs,
fullName = fullName,
@@ -370,6 +370,7 @@
lastName = lastName,
emailAddresses = emailAddresses,
uid = uid,
+ **kwargs
)
self.cachedTime = time.time()
Modified: CalendarServer/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -299,21 +299,21 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Create/persist a directory record based on the given values
"""
raise NotImplementedError("Subclass must implement createRecord")
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Update/persist a directory record based on the given values
"""
raise NotImplementedError("Subclass must implement updateRecord")
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
"""
Remove a directory record from the directory
"""
@@ -342,6 +342,7 @@
calendarUserAddresses=set(), autoSchedule=False, enabledForCalendaring=None,
enabledForAddressBooks=None,
uid=None,
+ **kwargs
):
assert service.realmName is not None
assert recordType
@@ -356,23 +357,25 @@
if fullName is None:
fullName = ""
- self.service = service
- self.recordType = recordType
- self.guid = guid
- self.uid = uid
- self.enabled = False
- self.hostedAt = ""
- self.shortNames = shortNames
- self.authIDs = authIDs
- self.fullName = fullName
- self.firstName = firstName
- self.lastName = lastName
- self.emailAddresses = emailAddresses
- self.enabledForCalendaring = enabledForCalendaring
- self.autoSchedule = autoSchedule
+ self.service = service
+ self.recordType = recordType
+ self.guid = guid
+ self.uid = uid
+ self.enabled = False
+ self.hostedAt = ""
+ self.shortNames = shortNames
+ self.authIDs = authIDs
+ self.fullName = fullName
+ self.firstName = firstName
+ self.lastName = lastName
+ self.emailAddresses = emailAddresses
+ self.enabledForCalendaring = enabledForCalendaring
+ self.autoSchedule = autoSchedule
self.enabledForAddressBooks = enabledForAddressBooks
+ self.extras = kwargs
+
def get_calendarUserAddresses(self):
"""
Dynamically construct a calendarUserAddresses attribute which describes
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -52,13 +52,19 @@
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01",
+ shortNames=("resource01",), uid="resource01",
+ emailAddresses=("res1 at example.com", "res2 at example.com"),
+ comment="Test Comment")
record = directory.recordWithUID("resource01")
self.assertNotEquals(record, None)
- directory.createRecord("resources", "resource02", shortNames=("resource02",), uid="resource02")
+ self.assertEquals(len(record.emailAddresses), 2)
+ self.assertEquals(record.extras['comment'], "Test Comment")
+ directory.createRecord("resources", guid="resource02", shortNames=("resource02",), uid="resource02")
+
record = directory.recordWithUID("resource02")
self.assertNotEquals(record, None)
@@ -74,12 +80,12 @@
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
record = directory.recordWithUID("resource01")
self.assertNotEquals(record, None)
- directory.destroyRecord("resources", "resource01")
+ directory.destroyRecord("resources", guid="resource01")
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
@@ -91,17 +97,18 @@
def test_updateRecord(self):
directory = getDirectory()
- directory.createRecord("resources", "resource01",
+ directory.createRecord("resources", guid="resource01",
shortNames=("resource01",), uid="resource01",
fullName="Resource number 1")
record = directory.recordWithUID("resource01")
self.assertEquals(record.fullName, "Resource number 1")
- directory.updateRecord("resources", "resource01",
+ directory.updateRecord("resources", guid="resource01",
shortNames=("resource01", "r01"), uid="resource01",
fullName="Resource #1", firstName="First", lastName="Last",
- emailAddresses=("resource01 at example.com", "r01 at example.com"))
+ emailAddresses=("resource01 at example.com", "r01 at example.com"),
+ comment="Test Comment")
record = directory.recordWithUID("resource01")
self.assertEquals(record.fullName, "Resource #1")
@@ -110,6 +117,7 @@
self.assertEquals(set(record.shortNames), set(["resource01", "r01"]))
self.assertEquals(record.emailAddresses,
set(["resource01 at example.com", "r01 at example.com"]))
+ self.assertEquals(record.extras['comment'], "Test Comment")
# Make sure old records are still there:
record = directory.recordWithUID("location01")
@@ -118,5 +126,5 @@
def test_createDuplicateRecord(self):
directory = getDirectory()
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
- self.assertRaises(DirectoryError, directory.createRecord, "resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
+ self.assertRaises(DirectoryError, directory.createRecord, "resources", guid="resource01", shortNames=("resource01",), uid="resource01")
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -229,6 +229,71 @@
self.assertFalse(service.recordWithShortName(DirectoryService.recordType_groups, "disabled").enabledForCalendaring)
+ def test_readExtras(self):
+ service = self.service()
+
+ self.xmlFile().open("w").write(
+"""<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE accounts SYSTEM "accounts.dtd">
+<accounts realm="Test Realm">
+ <location>
+ <uid>my office</uid>
+ <guid>myoffice</guid>
+ <name>My Office</name>
+ <extras>
+ <comment>This is the comment</comment>
+ <capacity>40</capacity>
+ </extras>
+ </location>
+</accounts>
+"""
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "my office")
+ self.assertEquals(record.guid, "myoffice")
+ self.assertEquals(record.extras["comment"], "This is the comment")
+ self.assertEquals(record.extras["capacity"], "40")
+
+ def test_writeExtras(self):
+ service = self.service()
+
+ service.createRecord(DirectoryService.recordType_locations, "newguid",
+ shortNames=("New office",),
+ fullName="My New Office",
+ address="1 Infinite Loop, Cupertino, CA",
+ capacity="10",
+ comment="Test comment",
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record.extras["comment"], "Test comment")
+ self.assertEquals(record.extras["capacity"], "10")
+
+
+ service.updateRecord(DirectoryService.recordType_locations, "newguid",
+ shortNames=("New office",),
+ fullName="My Newer Office",
+ address="2 Infinite Loop, Cupertino, CA",
+ capacity="20",
+ comment="Test comment updated",
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record.fullName, "My Newer Office")
+ self.assertEquals(record.extras["address"], "2 Infinite Loop, Cupertino, CA")
+ self.assertEquals(record.extras["comment"], "Test comment updated")
+ self.assertEquals(record.extras["capacity"], "20")
+
+ service.destroyRecord(DirectoryService.recordType_locations, "newguid")
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record, None)
+
+
class XMLFileSubset (XMLFileBase, TestCase):
"""
Test the recordTypes subset feature of XMLFile service.
Modified: CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -48,6 +48,7 @@
ELEMENT_EMAIL_ADDRESS = "email-address"
ELEMENT_MEMBERS = "members"
ELEMENT_MEMBER = "member"
+ELEMENT_EXTRAS = "extras"
ATTRIBUTE_REALM = "realm"
ATTRIBUTE_REPEAT = "repeat"
@@ -156,6 +157,7 @@
self.emailAddresses = set()
self.members = set()
self.groups = set()
+ self.extras = {}
def repeat(self, ctr):
"""
@@ -205,6 +207,7 @@
result.lastName = lastName
result.emailAddresses = emailAddresses
result.members = self.members
+ result.extras = self.extras
return result
def parseXML(self, node):
@@ -237,6 +240,8 @@
self.emailAddresses.add(child.firstChild.data.encode("utf-8").lower())
elif child_name == ELEMENT_MEMBERS:
self._parseMembers(child, self.members)
+ elif child_name == ELEMENT_EXTRAS:
+ self._parseExtras(child, self.extras)
else:
raise RuntimeError("Unknown account attribute: %s" % (child_name,))
@@ -252,3 +257,10 @@
recordType = DirectoryService.recordType_users
if child.firstChild is not None:
addto.add((recordType, child.firstChild.data.encode("utf-8")))
+
+ def _parseExtras(self, node, addto):
+ for child in node._get_childNodes():
+ key = child._get_localName()
+ if key:
+ value = child.firstChild.data.encode("utf-8")
+ addto[key.encode("utf-8")] = value
Modified: CalendarServer/trunk/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2010-02-12 03:44:52 UTC (rev 5094)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2010-02-12 16:12:33 UTC (rev 5095)
@@ -276,6 +276,10 @@
ET.SubElement(element, "last-name").text = principal.lastName
for value in principal.emailAddresses:
ET.SubElement(element, "email-address").text = value
+ if principal.extras:
+ extrasElement = ET.SubElement(element, "extras")
+ for key, value in principal.extras.iteritems():
+ ET.SubElement(extrasElement, key).text = value
return element
@@ -311,7 +315,7 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Create and persist a record using the provided information. In this
XML-based implementation, the xml accounts are read in and converted
@@ -341,12 +345,13 @@
xmlPrincipal.firstName = firstName
xmlPrincipal.lastName = lastName
xmlPrincipal.emailAddresses = emailAddresses
+ xmlPrincipal.extras = kwargs
self._addElement(accountsElement, xmlPrincipal)
self._persistRecords(accountsElement)
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
"""
Remove the record matching guid. In this XML-based implementation,
the xml accounts are read in and those not matching the given guid are
@@ -368,9 +373,9 @@
self._persistRecords(accountsElement)
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Update the record matching guid. In this XML-based implementation,
the xml accounts are read in and converted to elementtree elements.
@@ -394,6 +399,7 @@
xmlPrincipal.firstName = firstName
xmlPrincipal.lastName = lastName
xmlPrincipal.emailAddresses = emailAddresses
+ xmlPrincipal.extras = kwargs
self._addElement(accountsElement, xmlPrincipal)
else:
self._addElement(accountsElement, xmlPrincipal)
@@ -415,6 +421,7 @@
firstName = xmlPrincipal.firstName,
lastName = xmlPrincipal.lastName,
emailAddresses = xmlPrincipal.emailAddresses,
+ **xmlPrincipal.extras
)
self.password = xmlPrincipal.password
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100212/3b1c55ec/attachment-0001.html>
More information about the calendarserver-changes
mailing list