[CalendarServer-changes] [4220] CalendarServer/trunk/calendarserver/tools
source_changes at macosforge.org
source_changes at macosforge.org
Fri May 8 18:03:14 PDT 2009
Revision: 4220
http://trac.macosforge.org/projects/calendarserver/changeset/4220
Author: wsanchez at apple.com
Date: 2009-05-08 18:03:13 -0700 (Fri, 08 May 2009)
Log Message:
-----------
Rework the command line UI for calendarserver_manage_principals.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/export.py
CalendarServer/trunk/calendarserver/tools/migrate.py
CalendarServer/trunk/calendarserver/tools/principals.py
CalendarServer/trunk/calendarserver/tools/util.py
CalendarServer/trunk/calendarserver/tools/warmup.py
Modified: CalendarServer/trunk/calendarserver/tools/export.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/export.py 2009-05-09 00:29:42 UTC (rev 4219)
+++ CalendarServer/trunk/calendarserver/tools/export.py 2009-05-09 01:03:13 UTC (rev 4220)
@@ -36,6 +36,7 @@
from getopt import getopt, GetoptError
from os.path import dirname, abspath
+from twistedcaldav.config import ConfigurationError
from twistedcaldav.ical import Component as iComponent, Property as iProperty
from twistedcaldav.ical import iCalendarProductID
from twistedcaldav.resource import isCalendarCollectionResource
@@ -76,9 +77,9 @@
try:
(optargs, args) = getopt(
sys.argv[1:], "hf:o:c:H:r:u:", [
+ "help",
"config=",
"output=",
- "help",
"collection=", "home=", "record=", "user=",
],
)
@@ -144,12 +145,15 @@
usage("Too many arguments: %s" % (" ".join(args),))
if records:
- config = loadConfig(configFileName)
- directory = getDirectory()
+ try:
+ config = loadConfig(configFileName)
+ except ConfigurationError, e:
+ sys.stdout.write("%s\n" % (e,))
+ sys.exit(1)
for record in records:
recordType, shortName = record
- calendarHome = directory.calendarHomeForShortName(recordType, shortName)
+ calendarHome = config.directory.calendarHomeForShortName(recordType, shortName)
if not calendarHome:
sys.stderr.write("No calendar home found for record: (%s)%s\n" % (recordType, shortName))
sys.exit(1)
Modified: CalendarServer/trunk/calendarserver/tools/migrate.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/migrate.py 2009-05-09 00:29:42 UTC (rev 4219)
+++ CalendarServer/trunk/calendarserver/tools/migrate.py 2009-05-09 01:03:13 UTC (rev 4220)
@@ -29,7 +29,9 @@
import sys
from getopt import getopt, GetoptError
+from twistedcaldav.config import ConfigurationError
from twistedcaldav.upgrade import upgradeData
+
from calendarserver.tools.util import loadConfig
def usage(e=None):
@@ -75,7 +77,11 @@
if args:
usage("Too many arguments: %s" % (" ".join(args),))
- config = loadConfig(configFileName)
+ try:
+ config = loadConfig(configFileName)
+ except ConfigurationError, e:
+ sys.stdout.write("%s\n" % (e,))
+ sys.exit(1)
profiling = False
Modified: CalendarServer/trunk/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/principals.py 2009-05-09 00:29:42 UTC (rev 4219)
+++ CalendarServer/trunk/calendarserver/tools/principals.py 2009-05-09 01:03:13 UTC (rev 4220)
@@ -21,14 +21,18 @@
import itertools
import operator
from getopt import getopt, GetoptError
+from uuid import UUID
from twisted.python import log
from twisted.python.reflect import namedClass
from twisted.internet import reactor
+from twisted.internet.defer import Deferred
from twisted.internet.address import IPv4Address
from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.web2.dav import davxml
+from twext.web2.dav.davxml import sname2qname, qname2sname
+
from twistedcaldav import caldavxml
from twistedcaldav import memcachepool
from twistedcaldav.config import config, defaultConfigFile
@@ -39,7 +43,7 @@
from twistedcaldav.notify import installNotificationClient
from twistedcaldav.static import CalendarHomeProvisioningFile
-from calendarserver.tools.util import UsageError
+from calendarserver.tools.util import UsageError, booleanArgument
from calendarserver.tools.util import loadConfig, getDirectory, dummyDirectoryRecord
from calendarserver.provision.root import RootResource
@@ -49,21 +53,30 @@
print ""
name = os.path.basename(sys.argv[0])
- print "usage: %s [options]" % (name,)
+ print "usage: %s [options] actions principal [principal ...]" % (name,)
print ""
+ print " Performs the given actions against the giving principals."
+ print ""
+ print " Principals are identified by one of the following:"
+ print " Type and shortname (eg.: users:wsanchez)"
+ #print " A principal path (eg.: /principals/users/wsanchez/)"
+ print " A GUID (eg.: E415DBA7-40B5-49F5-A7CC-ACC81E4DEC79)"
+ print ""
print "options:"
print " -h --help: print this help and exit"
print " -f --config <path>: Specify caldavd.plist configuration path"
- print " --resource <prinicpal-path>: path of the resource to use"
- print " --search <search-string>: search for matching resources"
- print " --read-property: namespace-qualified DAV property to read, e.g. 'DAV:#group-member-set'"
- print " --list-read-delegates: list delegates with read-only access to the current resource"
- print " --list-write-delegates: list delegates with read-write access to the current resource"
- print " --add-read-delegate <prinicpal-path>: add argument as a read-only delegate to the current resource"
- print " --add-write-delegate <prinicpal-path>: add argument as a read-write delegate to the current resource"
- print " --remove-delegate <prinicpal-path>: strip argument of delegate status for the current resource"
- print " --set-auto-schedule [true|false] : determines whether the current resource auto-accepts invitations"
- print " --get-auto-schedule : returns the current resource's auto-schedule state"
+ print ""
+ print "actions:"
+ #print " --search <search-string>: search for matching resources"
+ print " -P, --read-property: read DAV property to read (eg.: {DAV:}group-member-set)"
+ print " --list-read-proxies: list proxies with read-only access"
+ print " --list-write-proxies: list proxies with read-write access"
+ print " --list-proxies: list all proxies"
+ print " --add-read-proxy=principal: add a read-only proxy"
+ print " --add-write-proxy=principal: add a read-write proxy"
+ print " --remove-proxy=principal: remove a proxy"
+ print " --set-auto-schedule={true|false}: set auto-accept state"
+ print " --get-auto-schedule: read auto-schedule state"
if e:
sys.exit(64)
@@ -73,17 +86,17 @@
def main():
try:
(optargs, args) = getopt(
- sys.argv[1:], "hf:r:s:", [
+ sys.argv[1:], "hf:P:", [
+ "help",
"config=",
- "help",
- "resource=",
- "search=",
+ #"search=",
"read-property=",
- "list-read-delegates",
- "list-write-delegates",
- "add-read-delegate=",
- "add-write-delegate=",
- "remove-delegate=",
+ "list-read-proxies",
+ "list-write-proxies",
+ "list-proxies",
+ "add-read-proxy=",
+ "add-write-proxy=",
+ "remove-proxy=",
"set-auto-schedule=",
"get-auto-schedule",
],
@@ -91,16 +104,14 @@
except GetoptError, e:
usage(e)
- if args:
- usage("Too many arguments: %s" % (" ".join(args),))
+ if not args:
+ usage("No principals specified.")
- logFileName = "/dev/stdout"
- observer = log.FileLogObserver(open(logFileName, "a"))
- log.addObserver(observer.emit)
-
- # First pass through the args:
-
+ #
+ # Get configuration
+ #
configFileName = None
+ actions = []
for opt, arg in optargs:
if opt in ("-h", "--help"):
@@ -109,248 +120,352 @@
elif opt in ("-f", "--config"):
configFileName = arg
- loadConfig(configFileName)
- directory, root = setup()
- root = ResourceWrapper(root)
+ elif opt in ("-P", "--read-property"):
+ try:
+ qname = sname2qname(arg)
+ except ValueError, e:
+ abort(e)
+ actions.append((action_readProperty, qname))
- reactor.callLater(0, run, directory, root, optargs)
- reactor.run()
+ elif opt in ("", "--list-read-proxies"):
+ actions.append((action_listProxies, "read"))
- at inlineCallbacks
-def run(directory, root, optargs):
+ elif opt in ("", "--list-write-proxies"):
+ actions.append((action_listProxies, "write"))
- print ""
+ elif opt in ("-L", "--list-proxies"):
+ actions.append((action_listProxies, "read", "write"))
- resource = None
+ elif opt in ("--add-read-proxy", "--add-write-proxy"):
+ if "read" in opt:
+ proxyType = "read"
+ elif "write" in opt:
+ proxyType = "write"
+ else:
+ raise AssertionError("Unknown proxy type")
- for opt, arg in optargs:
+ try:
+ principalForPrincipalID(arg, checkOnly=True)
+ except ValueError, e:
+ abort(e)
- if opt in ("-r", "--resource",):
- resource = root.lookupResource(arg)
- if resource is not None:
- print "Found resource %s at %s" % (resource.resource, arg)
- else:
- abort("Could not find resource at %s" % (arg,))
+ actions.append((action_addProxy, proxyType, arg))
- elif opt in ("-s", "--search",):
- fields = []
- for fieldName in ("fullName", "firstName", "lastName",
- "emailAddresses"):
- fields.append((fieldName, arg, True, "contains"))
+ elif opt in ("", "--remove-proxy"):
+ try:
+ principalForPrincipalID(arg, checkOnly=True)
+ except ValueError, e:
+ abort(e)
- records = list((yield directory.recordsMatchingFields(fields)))
- if records:
- records.sort(key=operator.attrgetter('fullName'))
- print "%d matches found:" % (len(records),)
- for record in records:
- print "\n%s (%s)" % (record.fullName,
- { "users" : "User",
- "groups" : "Group",
- "locations" : "Place",
- "resources" : "Resource",
- }.get(record.recordType),
- )
- print record.guid
- print " Record names: %s" % (", ".join(record.shortNames),)
- if record.authIDs:
- print " Auth IDs: %s" % (", ".join(record.authIDs),)
- if record.emailAddresses:
- print " Emails: %s" % (", ".join(record.emailAddresses),)
- else:
- print "No matches found"
+ actions.append((action_removeProxy, arg))
- elif opt in ("--read-property",):
- if resource is None: abort("No current resource.")
-
+ elif opt in ("", "--set-auto-schedule"):
try:
- namespace, name = arg.split("#")
- except Exception, e:
- abort("Can't parse --propertyToRead: %s" % (arg,))
+ autoSchedule = booleanArgument(arg)
+ except ValueError, e:
+ abort(e)
- result = (yield resource.readProperty((namespace, name)))
- print result.toxml()
+ actions.append((action_setAutoSchedule, autoSchedule))
- elif opt in ("--list-write-delegates", "--list-read-delegates"):
- if resource is None: abort("No current resource.")
+ elif opt in ("", "--get-auto-schedule"):
+ actions.append((action_getAutoSchedule,))
- permission = "write" if "write" in opt else "read"
- print "Delegates (%s) for %s:" % (permission, resource.resource)
- paths = (yield resource.getDelegates(permission))
- for path in paths:
- delegate = root.getChild(path)
- print delegate.resource
+ else:
+ raise NotImplementedError(opt)
- elif opt in ("--add-write-delegate", "--add-read-delegate"):
- if resource is None: abort("No current resource.")
+ #
+ # Get configuration
+ #
+ try:
+ loadConfig(configFileName)
+ except ConfigurationError, e:
+ abort(e)
- delegate = root.lookupResource(arg)
- if delegate is None:
- abort("No delegate found for %s" % (arg,))
+ #
+ # Do a quick sanity check that arguments look like principal
+ # identifiers.
+ #
+ for arg in args:
+ try:
+ principalForPrincipalID(arg, checkOnly=True)
+ except ValueError, e:
+ abort(e)
- permission = "write" if "write" in opt else "read"
- result = (yield resource.addDelegate(delegate, permission))
+ #
+ # Send logging output to stdout
+ #
+ setLogLevelForNamespace(None, "warn")
+ logFileName = "/dev/stdout"
+ observer = log.FileLogObserver(open(logFileName, "a"))
+ log.addObserver(observer.emit)
- elif opt == "--remove-delegate":
- if resource is None: abort("No current resource.")
+ #
+ # Start the reactor
+ #
+ reactor.callLater(0, run, args, actions)
+ reactor.run()
- delegate = root.lookupResource(arg)
- if delegate is None:
- abort("No delegate found for %s" % (arg,))
+ at inlineCallbacks
+def run(principalIDs, actions):
+ try:
+ #
+ # Connect to memcached, notifications
+ #
+ if config.Memcached.ClientEnabled:
+ memcachepool.installPool(
+ IPv4Address(
+ "TCP",
+ config.Memcached.BindAddress,
+ config.Memcached.Port,
+ ),
+ config.Memcached.MaxClients
+ )
+ if config.Notifications.Enabled:
+ installNotificationClient(
+ config.Notifications.InternalNotificationHost,
+ config.Notifications.InternalNotificationPort,
+ )
- result = (yield resource.removeDelegate(delegate, "read"))
- result = (yield resource.removeDelegate(delegate, "write"))
+ #
+ # Wire up the resource hierarchy
+ #
+ principalCollection = config.directory.getPrincipalCollection()
+ root = RootResource(
+ config.DocumentRoot,
+ principalCollections=(principalCollection,),
+ )
+ root.putChild("principals", principalCollection)
+ calendarCollection = CalendarHomeProvisioningFile(
+ os.path.join(config.DocumentRoot, "calendars"),
+ config.directory, "/calendars/",
+ )
+ root.putChild("calendars", calendarCollection)
- elif opt == "--set-auto-schedule":
- if resource is None: abort("No current resource.")
+ #
+ # Wrap root resource
+ #
+ # FIXME: not a fan -wsanchez
+ #root = ResourceWrapper(root)
- result = (yield resource.setAutoSchedule(arg.lower() in ("true", "1")))
+ for principalID in principalIDs:
+ # Resolve the given principal IDs to principals
+ try:
+ principal = principalForPrincipalID(principalID)
+ except ValueError:
+ principal = None
- elif opt == "--get-auto-schedule":
- if resource is None: abort("No current resource.")
+ if principal is None:
+ sys.stderr.write("Invalid principal ID: %s\n" % (principalID,))
+ continue
- result = (yield resource.getAutoSchedule())
- print "Auto-Schedule: %s" % ("True" if result else "False",)
+ # Performs requested actions
+ for action in actions:
+ (yield action[0](principal, *action[1:]))
+ print ""
- print ""
+ finally:
+ #
+ # Stop the reactor
+ #
+ reactor.stop()
- # reactor.callLater(0, reactor.stop)
- reactor.stop()
+def principalForPrincipalID(principalID, checkOnly=False):
+ if principalID.startswith("/"):
+ raise ValueError("Can't resolve paths yet")
-class ResourceWrapper(object):
+ if checkOnly:
+ return None
- def __init__(self, resource):
- self.resource = resource
+ if principalID.startswith("("):
+ try:
+ i = principalID.index(")")
- def readProperty(self, prop):
- return self.resource.readProperty(prop, FakeRequest())
+ if checkOnly:
+ return None
- def writeProperty(self, prop):
- return self.resource.writeProperty(prop, FakeRequest())
+ recordType = principalID[1:i]
+ shortName = principalID[i+1:]
- def lookupResource(self, specifier):
- # For now, support GUID lookup
- return self.getChild("principals/__uids__/%s" % (specifier,))
+ if not recordType or not shortName or "(" in recordType:
+ raise ValueError()
- def getChild(self, path):
- resource = self.resource
- segments = path.strip("/").split("/")
- for segment in segments:
- resource = resource.getChild(segment)
- if resource is None:
- return None
- return ResourceWrapper(resource)
+ return config.directory.principalCollection.principalForShortName(recordType, shortName)
- @inlineCallbacks
- def removeDelegate(self, delegate, permission):
- subPrincipalName = "calendar-proxy-%s" % (permission,)
- subPrincipal = self.getChild(subPrincipalName)
- if subPrincipal is None:
- abort("No proxy subprincipal found for %s" % (self.resource,))
+ except ValueError:
+ pass
- namespace, name = davxml.dav_namespace, "group-member-set"
- prop = (yield subPrincipal.readProperty((namespace, name)))
- newChildren = []
- for child in prop.children:
- if str(child) != delegate.url():
- newChildren.append(child)
+ if ":" in principalID:
+ if checkOnly:
+ return None
- if len(prop.children) == len(newChildren):
- # Nothing to do -- the delegate wasn't there
- returnValue(False)
+ recordType, shortName = principalID.split(":", 1)
- newProp = davxml.GroupMemberSet(*newChildren)
- result = (yield subPrincipal.writeProperty(newProp))
- returnValue(result)
+ return config.directory.principalCollection.principalForShortName(recordType, shortName)
- @inlineCallbacks
- def addDelegate(self, delegate, permission):
+ try:
+ guid = UUID(principalID)
- opposite = "read" if permission == "write" else "write"
- result = (yield self.removeDelegate(delegate, opposite))
+ if checkOnly:
+ return None
- subPrincipalName = "calendar-proxy-%s" % (permission,)
- subPrincipal = self.getChild(subPrincipalName)
+ return config.directory.principalCollection.principalForUID(guid)
+ except ValueError:
+ pass
+
+ raise ValueError("Invalid principal identifier: %s" % (principalID,))
+
+def proxySubprincipal(principal, proxyType):
+ return principal.getChild("calendar-proxy-" + proxyType)
+
+ at inlineCallbacks
+def action_readProperty(resource, qname):
+ property = (yield resource.readProperty(qname, None))
+ print "%r on %s:" % (qname2sname(qname), resource)
+ print ""
+ print property.toxml()
+
+ at inlineCallbacks
+def action_listProxies(principal, *proxyTypes):
+ for proxyType in proxyTypes:
+ subPrincipal = proxySubprincipal(principal, proxyType)
if subPrincipal is None:
- abort("No proxy subprincipal found for %s" % (self.resource,))
+ print "No %s proxies for %s" % (proxyType, principal)
+ continue
- namespace, name = davxml.dav_namespace, "group-member-set"
- prop = (yield subPrincipal.readProperty((namespace, name)))
- for child in prop.children:
- if str(child) == delegate.url():
- # delegate is already in the group
- break
+ membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
+
+ if membersProperty.children:
+ print "%s proxies for %s:" % (
+ {"read": "Read-only", "write": "Read/write"}[proxyType],
+ principal,
+ )
+ for member in membersProperty.children:
+ print " *", member
else:
- # delegate is not already in the group
- newChildren = list(prop.children)
- newChildren.append(davxml.HRef(delegate.url()))
- newProp = davxml.GroupMemberSet(*newChildren)
- result = (yield subPrincipal.writeProperty(newProp))
- returnValue(result)
+ print "No %s proxies for %s" % (proxyType, principal)
- @inlineCallbacks
- def getDelegates(self, permission):
+ at inlineCallbacks
+def action_addProxy(principal, proxyType, *proxyIDs):
+ for proxyID in proxyIDs:
+ proxyPrincipal = principalForPrincipalID(proxyID)
+ proxyURL = proxyPrincipal.url()
- subPrincipalName = "calendar-proxy-%s" % (permission,)
- subPrincipal = self.getChild(subPrincipalName)
+ subPrincipal = proxySubprincipal(principal, proxyType)
if subPrincipal is None:
- abort("No proxy subprincipal found for %s" % (self.resource,))
+ sys.stderr.write("Unable to edit %s proxies for %s\n" % (proxyType, principal))
+ continue
- namespace, name = davxml.dav_namespace, "group-member-set"
- prop = (yield subPrincipal.readProperty((namespace, name)))
- result = []
- for child in prop.children:
- result.append(str(child))
- returnValue(result)
+ membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
- def setAutoSchedule(self, autoSchedule):
- return self.resource.setAutoSchedule(autoSchedule)
+ for memberURL in membersProperty.children:
+ if str(memberURL) == proxyURL:
+ print "%s is already a %s proxy for %s" % (proxyPrincipal, proxyType, principal)
+ break
+ else:
+ memberURLs = list(membersProperty.children)
+ memberURLs.append(davxml.HRef(proxyURL))
+ membersProperty = davxml.GroupMemberSet(*memberURLs)
+ (yield subPrincipal.writeProperty(membersProperty, None))
+ print "Added %s as a %s proxy for %s" % (proxyPrincipal, proxyType, principal)
- def getAutoSchedule(self):
- return self.resource.getAutoSchedule()
+ proxyTypes = ["read", "write"]
+ proxyTypes.remove(proxyType)
- def url(self):
- return self.resource.url()
+ (yield action_removeProxy(principal, proxyID, proxyTypes=proxyTypes))
-class FakeRequest(object):
- pass
+ at inlineCallbacks
+def action_removeProxy(principal, *proxyIDs, **kwargs):
+ proxyTypes = kwargs.get("proxyTypes", ("read", "write"))
-def abort(msg, errno=1):
- print "ERROR:", msg
- print "Exiting"
- reactor.stop()
- sys.exit(errno)
+ for proxyID in proxyIDs:
+ for proxyType in proxyTypes:
+ proxyPrincipal = principalForPrincipalID(proxyID)
+ proxyURL = proxyPrincipal.url()
-def setup():
- setLogLevelForNamespace(None, "warn")
+ subPrincipal = proxySubprincipal(principal, proxyType)
+ if subPrincipal is None:
+ sys.stderr.write("Unable to edit %s proxies for %s\n" % (proxyType, principal))
+ continue
- directory = getDirectory()
- if config.Memcached["ClientEnabled"]:
- memcachepool.installPool(
- IPv4Address(
- 'TCP',
- config.Memcached["BindAddress"],
- config.Memcached["Port"]
- ),
- config.Memcached["MaxClients"]
- )
- if config.Notifications["Enabled"]:
- installNotificationClient(
- config.Notifications["InternalNotificationHost"],
- config.Notifications["InternalNotificationPort"],
- )
- principalCollection = directory.getPrincipalCollection()
- root = RootResource(
- config.DocumentRoot,
- principalCollections=(principalCollection,),
+ membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
+
+ memberURLs = [
+ m for m in membersProperty.children
+ if str(m) != proxyURL
+ ]
+
+ if len(memberURLs) == len(membersProperty.children):
+ # No change
+ continue
+
+ membersProperty = davxml.GroupMemberSet(*memberURLs)
+ (yield subPrincipal.writeProperty(membersProperty, None))
+ print "Removed %s as a %s proxy for %s" % (proxyPrincipal, proxyType, principal)
+
+ at inlineCallbacks
+def action_setAutoSchedule(principal, autoSchedule):
+ print "Setting auto-schedule to %s for %s" % (
+ { True: "true", False: "false" }[autoSchedule],
+ principal,
)
- root.putChild("principals", principalCollection)
- calendarCollection = CalendarHomeProvisioningFile(
- os.path.join(config.DocumentRoot, "calendars"),
- directory, "/calendars/",
+ (yield principal.setAutoSchedule(autoSchedule))
+
+ at inlineCallbacks
+def action_getAutoSchedule(principal):
+ autoSchedule = (yield principal.getAutoSchedule())
+ print "Autoschedule for %s is %s" % (
+ principal,
+ { True: "true", False: "false" }[autoSchedule],
)
- root.putChild("calendars", calendarCollection)
- return (directory, root)
+ at inlineCallbacks
+def _run(directory, root, optargs, principalIDs):
+ print ""
+
+ resource = None
+
+ for opt, arg in optargs:
+
+ if opt in ("-s", "--search",):
+ fields = []
+ for fieldName in ("fullName", "firstName", "lastName",
+ "emailAddresses"):
+ fields.append((fieldName, arg, True, "contains"))
+
+ records = list((yield config.directory.recordsMatchingFields(fields)))
+ if records:
+ records.sort(key=operator.attrgetter('fullName'))
+ print "%d matches found:" % (len(records),)
+ for record in records:
+ print "\n%s (%s)" % (record.fullName,
+ { "users" : "User",
+ "groups" : "Group",
+ "locations" : "Place",
+ "resources" : "Resource",
+ }.get(record.recordType),
+ )
+ print record.guid
+ print " Record names: %s" % (", ".join(record.shortNames),)
+ if record.authIDs:
+ print " Auth IDs: %s" % (", ".join(record.authIDs),)
+ if record.emailAddresses:
+ print " Emails: %s" % (", ".join(record.emailAddresses),)
+ else:
+ print "No matches found"
+
+ print ""
+
+ # reactor.callLater(0, reactor.stop)
+ reactor.stop()
+
+def abort(msg, status=1):
+ sys.stdout.write("%s\n" % (msg,))
+ try:
+ reactor.stop()
+ except RuntimeError:
+ pass
+ sys.exit(status)
+
if __name__ == "__main__":
main()
Modified: CalendarServer/trunk/calendarserver/tools/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/util.py 2009-05-09 00:29:42 UTC (rev 4219)
+++ CalendarServer/trunk/calendarserver/tools/util.py 2009-05-09 01:03:13 UTC (rev 4220)
@@ -19,6 +19,7 @@
"getDirectory",
"dummyDirectoryRecord",
"UsageError",
+ "booleanArgument",
]
import sys
@@ -26,7 +27,7 @@
from twisted.python.reflect import namedClass
-from twistedcaldav.config import config, defaultConfigFile
+from twistedcaldav.config import config, defaultConfigFile, ConfigurationError
from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
def loadConfig(configFileName):
@@ -34,10 +35,10 @@
configFileName = defaultConfigFile
if not os.path.isfile(configFileName):
- sys.stderr.write("No config file: %s\n" % (configFileName,))
- sys.exit(1)
+ raise ConfigurationError("No config file: %s" % (configFileName,))
config.loadConfig(configFileName)
+ config.directory = getDirectory()
return config
@@ -107,3 +108,11 @@
class UsageError (StandardError):
pass
+
+def booleanArgument(arg):
+ if arg in ("true", "yes", "yup", "uh-huh", "1", "t", "y"):
+ return True
+ elif arg in ("false", "no", "nope", "nuh-uh", "0", "f", "n"):
+ return False
+ else:
+ raise ValueError("Not a boolean: %s" % (arg,))
Modified: CalendarServer/trunk/calendarserver/tools/warmup.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/warmup.py 2009-05-09 00:29:42 UTC (rev 4219)
+++ CalendarServer/trunk/calendarserver/tools/warmup.py 2009-05-09 01:03:13 UTC (rev 4220)
@@ -32,6 +32,7 @@
from getopt import getopt, GetoptError
from os.path import dirname, abspath
+from twistedcaldav.config import ConfigurationError
from twistedcaldav.resource import isPseudoCalendarCollectionResource
from twistedcaldav.static import CalDAVFile, CalendarHomeFile
from twistedcaldav.directory.directory import DirectoryService
@@ -126,20 +127,23 @@
usage("Too many arguments: %s" % (" ".join(args),))
if records or allRecords:
- config = loadConfig(configFileName)
- directory = getDirectory()
+ try:
+ config = loadConfig(configFileName)
+ except ConfigurationError, e:
+ sys.stdout.write("%s\n" % (e,))
+ sys.exit(1)
for record in records:
recordType, shortName = record
- calendarHome = directory.calendarHomeForShortName(recordType, shortName)
+ calendarHome = config.directory.calendarHomeForShortName(recordType, shortName)
if not calendarHome:
sys.stderr.write("No calendar home found for record: (%s)%s\n" % (recordType, shortName))
sys.exit(1)
calendarHomes.add(calendarHome)
if allRecords:
- for record in directory.allRecords():
- calendarHome = directory.calendarHomeForRecord(record)
+ for record in config.directory.allRecords():
+ calendarHome = config.directory.calendarHomeForRecord(record)
if not calendarHome:
pass
else:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090508/db6567ba/attachment-0001.html>
More information about the calendarserver-changes
mailing list