From: richard Date: Thu, 18 Oct 2001 02:16:42 +0000 (+0000) Subject: Oops, committed the admin script with the wierd #! line. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=b729cba95a23ab30dd8d483042466f57fca5fe43;p=roundup.git Oops, committed the admin script with the wierd #! line. Also, made the thing into a class to reduce parameter passing. Nuked the leading whitespace from the help __doc__ displays too. git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@311 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/roundup-admin b/roundup-admin index f7a0ff2..9014bc7 100755 --- a/roundup-admin +++ b/roundup-admin @@ -1,4 +1,4 @@ -#! /Users/builder/bin/python +#! /usr/bin/env python # # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/) # This module is free software, and you may redistribute it and/or modify @@ -16,7 +16,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup-admin,v 1.33 2001-10-17 23:13:19 richard Exp $ +# $Id: roundup-admin,v 1.34 2001-10-18 02:16:42 richard Exp $ import sys if int(sys.version[0]) < 2: @@ -31,9 +31,21 @@ except ImportError: from roundup import date, hyperdb, roundupdb, init, password import roundup.instance -def usage(message=''): - if message: message = 'Problem: '+message+'\n' - print '''%sUsage: roundup-admin [-i instance home] [-u login] [-c] +class AdminTool: + + def __init__(self): + self.commands = {} + for k, v in AdminTool.__dict__.items(): + if k[:3] == 'do_': + self.commands[k[3:]] = v + self.help = {} + for k, v in AdminTool.__dict__.items(): + if k[:5] == 'help_': + self.help[k[5:]] = v + + def usage(message=''): + if message: message = 'Problem: '+message+'\n' + print '''%sUsage: roundup-admin [-i instance home] [-u login] [-c] Help: roundup-admin -h @@ -44,19 +56,19 @@ Options: -i instance home -- specify the issue tracker "home directory" to administer -u -- the user[:password] to use for commands -c -- when outputting lists of data, just comma-separate them'''%message - help_commands() - -def help_commands(): - print 'Commands:', - commands = [''] - for command in figureCommands().values(): - h = command.__doc__.split('\n')[0] - commands.append(h[7:]) - commands.sort() - print '\n '.join(commands) - -def help_all(): - print ''' + self.help_commands() + + def help_commands(self): + print 'Commands:', + commands = [''] + for command in self.commands.values(): + h = command.__doc__.split('\n')[0] + commands.append(h[7:]) + commands.sort() + print '\n '.join(commands) + + def help_all(self): + print ''' All commands (except help) require an instance specifier. This is just the path to the roundup instance you're working with. A roundup instance is where roundup keeps the database and configuration file that defines an issue @@ -105,460 +117,456 @@ Date format examples: Command help: ''' - for name, command in figureCommands().items(): - print '%s:'%name - print ' ',command.__doc__ - -def do_help(args): - '''Usage: help topic - Give help about topic. - - commands -- list commands - -- help specific to a command - initopts -- init command options - all -- all available help - ''' - help = figureHelp().get(args[0], None) - if help: - help() - return - help = figureCommands().get(args[0], None) - if help: - print help.__doc__ - else: - print 'Sorry, no help for "%s"'%args[0] - -def help_initopts(): - import roundup.templates - templates = roundup.templates.listTemplates() - print 'Templates:', ', '.join(templates) - import roundup.backends - backends = roundup.backends.__all__ - print 'Back ends:', ', '.join(backends) - - -def do_init(instance_home, args, comma_sep=0): - '''Usage: init [template [backend [admin password]]] - Initialise a new Roundup instance. - - The command will prompt for the instance home directory (if not supplied - through INSTANCE_HOME or the -i option. The template, backend and admin - password may be specified on the command-line as arguments, in that order. - - See also initopts help. - ''' - # select template - import roundup.templates - templates = roundup.templates.listTemplates() - template = len(args) > 1 and args[1] or '' - if template not in templates: + for name, command in self.commands.items(): + print '%s:'%name + print ' ',command.__doc__ + + def do_help(self, args, nl_re=re.compile('[\r\n]'), + indent_re=re.compile(r'^(\s+)\S+')): + '''Usage: help topic + Give help about topic. + + commands -- list commands + -- help specific to a command + initopts -- init command options + all -- all available help + ''' + help = self.help.get(args[0], None) + if help: + help(self) + return + help = self.commands.get(args[0], None) + if help: + # display the help, removing the docsring indent + lines = nl_re.split(help.__doc__) + print lines[0] + indent = indent_re.match(lines[1]) + if indent: indent = len(indent.group(1)) + for line in lines[1:]: + if indent: + print line[indent:] + else: + print line + else: + print 'Sorry, no help for "%s"'%args[0] + + def help_initopts(self): + import roundup.templates + templates = roundup.templates.listTemplates() print 'Templates:', ', '.join(templates) - while template not in templates: - template = raw_input('Select template [extended]: ').strip() - if not template: - template = 'extended' - - import roundup.backends - backends = roundup.backends.__all__ - backend = len(args) > 2 and args[2] or '' - if backend not in backends: + import roundup.backends + backends = roundup.backends.__all__ print 'Back ends:', ', '.join(backends) - while backend not in backends: - backend = raw_input('Select backend [anydbm]: ').strip() - if not backend: - backend = 'anydbm' - if len(args) > 3: - adminpw = confirm = args[3] - else: - adminpw = '' - confirm = 'x' - while adminpw != confirm: - adminpw = getpass.getpass('Admin Password: ') - confirm = getpass.getpass(' Confirm: ') - init.init(instance_home, template, backend, adminpw) - return 0 - - -def do_get(db, args, comma_sep=0): - '''Usage: get property designator[,designator]* - Get the given property of one or more designator(s). - - Retrieves the property value of the nodes specified by the designators. - ''' - propname = args[0] - designators = string.split(args[1], ',') - l = [] - for designator in designators: - classname, nodeid = roundupdb.splitDesignator(designator) - if comma_sep: - l.append(db.getclass(classname).get(nodeid, propname)) + + + def do_init(instance_home, args): + '''Usage: init [template [backend [admin password]]] + Initialise a new Roundup instance. + + The command will prompt for the instance home directory (if not supplied + through INSTANCE_HOME or the -i option. The template, backend and admin + password may be specified on the command-line as arguments, in that + order. + + See also initopts help. + ''' + # select template + import roundup.templates + templates = roundup.templates.listTemplates() + template = len(args) > 1 and args[1] or '' + if template not in templates: + print 'Templates:', ', '.join(templates) + while template not in templates: + template = raw_input('Select template [extended]: ').strip() + if not template: + template = 'extended' + + import roundup.backends + backends = roundup.backends.__all__ + backend = len(args) > 2 and args[2] or '' + if backend not in backends: + print 'Back ends:', ', '.join(backends) + while backend not in backends: + backend = raw_input('Select backend [anydbm]: ').strip() + if not backend: + backend = 'anydbm' + if len(args) > 3: + adminpw = confirm = args[3] + else: + adminpw = '' + confirm = 'x' + while adminpw != confirm: + adminpw = getpass.getpass('Admin Password: ') + confirm = getpass.getpass(' Confirm: ') + init.init(instance_home, template, backend, adminpw) + return 0 + + + def do_get(self, args): + '''Usage: get property designator[,designator]* + Get the given property of one or more designator(s). + + Retrieves the property value of the nodes specified by the designators. + ''' + propname = args[0] + designators = string.split(args[1], ',') + l = [] + for designator in designators: + classname, nodeid = roundupdb.splitDesignator(designator) + if self.comma_sep: + l.append(self.db.getclass(classname).get(nodeid, propname)) + else: + print self.db.getclass(classname).get(nodeid, propname) + if self.comma_sep: + print ','.join(l) + return 0 + + + def do_set(self, args): + '''Usage: set designator[,designator]* propname=value ... + Set the given property of one or more designator(s). + + Sets the property to the value for all designators given. + ''' + from roundup import hyperdb + + designators = string.split(args[0], ',') + props = {} + for prop in args[1:]: + key, value = prop.split('=') + props[key] = value + for designator in designators: + classname, nodeid = roundupdb.splitDesignator(designator) + cl = self.db.getclass(classname) + properties = cl.getprops() + for key, value in props.items(): + type = properties[key] + if isinstance(type, hyperdb.String): + continue + elif isinstance(type, hyperdb.Password): + props[key] = password.Password(value) + elif isinstance(type, hyperdb.Date): + props[key] = date.Date(value) + elif isinstance(type, hyperdb.Interval): + props[key] = date.Interval(value) + elif isinstance(type, hyperdb.Link): + props[key] = value + elif isinstance(type, hyperdb.Multilink): + props[key] = value.split(',') + apply(cl.set, (nodeid, ), props) + return 0 + + def do_find(self, args): + '''Usage: find classname propname=value ... + Find the nodes of the given class with a given link property value. + + Find the nodes of the given class with a given link property value. The + value may be either the nodeid of the linked node, or its key value. + ''' + classname = args[0] + cl = self.db.getclass(classname) + + # look up the linked-to class and get the nodeid that has the value + propname, value = args[1].split('=') + num_re = re.compile('^\d+$') + if not num_re.match(value): + propcl = cl.properties[propname] + if (not isinstance(propcl, hyperdb.Link) and not + isinstance(type, hyperdb.Multilink)): + print 'You may only "find" link properties' + return 1 + propcl = self.db.getclass(propcl.classname) + value = propcl.lookup(value) + + # now do the find + if self.comma_sep: + print ','.join(cl.find(**{propname: value})) else: - print db.getclass(classname).get(nodeid, propname) - if comma_sep: - print ','.join(l) - return 0 - - -def do_set(db, args, comma_sep=0): - '''Usage: set designator[,designator]* propname=value ... - Set the given property of one or more designator(s). - - Sets the property to the value for all designators given. - ''' - from roundup import hyperdb - - designators = string.split(args[0], ',') - props = {} - for prop in args[1:]: - key, value = prop.split('=') - props[key] = value - for designator in designators: - classname, nodeid = roundupdb.splitDesignator(designator) - cl = db.getclass(classname) - properties = cl.getprops() - for key, value in props.items(): + print cl.find(**{propname: value}) + return 0 + + def do_spec(self, args): + '''Usage: spec classname + Show the properties for a classname. + + This lists the properties for a given class. + ''' + classname = args[0] + cl = self.db.getclass(classname) + keyprop = cl.getkey() + for key, value in cl.properties.items(): + if keyprop == key: + print '%s: %s (key property)'%(key, value) + else: + print '%s: %s'%(key, value) + + def do_create(self, args): + '''Usage: create classname property=value ... + Create a new entry of a given class. + + This creates a new entry of the given class using the property + name=value arguments provided on the command line after the "create" + command. + ''' + from roundup import hyperdb + + classname = args[0] + cl = self.db.getclass(classname) + props = {} + properties = cl.getprops(protected = 0) + if len(args) == 1: + # ask for the properties + for key, value in properties.items(): + if key == 'id': continue + name = value.__class__.__name__ + if isinstance(value , hyperdb.Password): + again = None + while value != again: + value = getpass.getpass('%s (Password): '%key.capitalize()) + again = getpass.getpass(' %s (Again): '%key.capitalize()) + if value != again: print 'Sorry, try again...' + if value: + props[key] = value + else: + value = raw_input('%s (%s): '%(key.capitalize(), name)) + if value: + props[key] = value + else: + # use the args + for prop in args[1:]: + key, value = prop.split('=') + props[key] = value + + # convert types + for key in props.keys(): type = properties[key] - if isinstance(type, hyperdb.String): - continue - elif isinstance(type, hyperdb.Password): - props[key] = password.Password(value) - elif isinstance(type, hyperdb.Date): + if isinstance(type, hyperdb.Date): props[key] = date.Date(value) elif isinstance(type, hyperdb.Interval): props[key] = date.Interval(value) - elif isinstance(type, hyperdb.Link): - props[key] = value + elif isinstance(type, hyperdb.Password): + props[key] = password.Password(value) elif isinstance(type, hyperdb.Multilink): props[key] = value.split(',') - apply(cl.set, (nodeid, ), props) - return 0 - -def do_find(db, args, comma_sep=0): - '''Usage: find classname propname=value ... - Find the nodes of the given class with a given link property value. - - Find the nodes of the given class with a given link property value. The - value may be either the nodeid of the linked node, or its key value. - ''' - classname = args[0] - cl = db.getclass(classname) - - # look up the linked-to class and get the nodeid that has the value - propname, value = args[1].split('=') - num_re = re.compile('^\d+$') - if not num_re.match(value): - propcl = cl.properties[propname] - if (not isinstance(propcl, hyperdb.Link) and not - isinstance(type, hyperdb.Multilink)): - print 'You may only "find" link properties' - return 1 - propcl = db.getclass(propcl.classname) - value = propcl.lookup(value) - - # now do the find - if comma_sep: - print ','.join(cl.find(**{propname: value})) - else: - print cl.find(**{propname: value}) - return 0 - -def do_spec(db, args, comma_sep=0): - '''Usage: spec classname - Show the properties for a classname. - - This lists the properties for a given class. - ''' - classname = args[0] - cl = db.getclass(classname) - keyprop = cl.getkey() - for key, value in cl.properties.items(): - if keyprop == key: - print '%s: %s (key property)'%(key, value) - else: - print '%s: %s'%(key, value) - -def do_create(db, args, comma_sep=0): - '''Usage: create classname property=value ... - Create a new entry of a given class. - - This creates a new entry of the given class using the property - name=value arguments provided on the command line after the "create" - command. - ''' - from roundup import hyperdb - - classname = args[0] - cl = db.getclass(classname) - props = {} - properties = cl.getprops(protected = 0) - if len(args) == 1: - # ask for the properties - for key, value in properties.items(): - if key == 'id': continue - name = value.__class__.__name__ - if isinstance(value , hyperdb.Password): - again = None - while value != again: - value = getpass.getpass('%s (Password): '%key.capitalize()) - again = getpass.getpass(' %s (Again): '%key.capitalize()) - if value != again: print 'Sorry, try again...' - if value: - props[key] = value - else: - value = raw_input('%s (%s): '%(key.capitalize(), name)) - if value: - props[key] = value - else: - # use the args - for prop in args[1:]: - key, value = prop.split('=') - props[key] = value - - # convert types - for key in props.keys(): - type = properties[key] - if isinstance(type, hyperdb.Date): - props[key] = date.Date(value) - elif isinstance(type, hyperdb.Interval): - props[key] = date.Interval(value) - elif isinstance(type, hyperdb.Password): - props[key] = password.Password(value) - elif isinstance(type, hyperdb.Multilink): - props[key] = value.split(',') - - if cl.getkey() and not props.has_key(cl.getkey()): - print "You must provide the '%s' property."%cl.getkey() - else: - print apply(cl.create, (), props) - - return 0 - -def do_list(db, args, comma_sep=0): - '''Usage: list classname [property] - List the instances of a class. - - Lists all instances of the given class. If the property is not - specified, the "label" property is used. The label property is tried - in order: the key, "name", "title" and then the first property, - alphabetically. - ''' - classname = args[0] - cl = db.getclass(classname) - if len(args) > 1: - key = args[1] - else: - key = cl.labelprop() - if comma_sep: - print ','.join(cl.list()) - else: - for nodeid in cl.list(): - value = cl.get(nodeid, key) - print "%4s: %s"%(nodeid, value) - return 0 - -def do_table(db, args, comma_sep=None): - '''Usage: table classname [property[,property]*] - List the instances of a class in tabular form. - - Lists all instances of the given class. If the properties are not - specified, all properties are displayed. By default, the column widths - are the width of the property names. The width may be explicitly defined - by defining the property as "name:width". For example:: - roundup> table priority id,name:10 - Id Name - 1 fatal-bug - 2 bug - 3 usability - 4 feature - ''' - classname = args[0] - cl = db.getclass(classname) - if len(args) > 1: - prop_names = args[1].split(',') - else: - prop_names = cl.getprops().keys() - props = [] - for name in prop_names: - if ':' in name: - name, width = name.split(':') - props.append((name, int(width))) + + if cl.getkey() and not props.has_key(cl.getkey()): + print "You must provide the '%s' property."%cl.getkey() else: - props.append((name, len(name))) + print apply(cl.create, (), props) - print ' '.join([string.capitalize(name) for name, width in props]) - for nodeid in cl.list(): - l = [] - for name, width in props: - if name != 'id': - value = str(cl.get(nodeid, name)) - else: - value = str(nodeid) - f = '%%-%ds'%width - l.append(f%value[:width]) - print ' '.join(l) - return 0 - -def do_history(db, args, comma_sep=0): - '''Usage: history designator - Show the history entries of a designator. - - Lists the journal entries for the node identified by the designator. - ''' - classname, nodeid = roundupdb.splitDesignator(args[0]) - # TODO: handle the -c option? - print db.getclass(classname).history(nodeid) - return 0 - -def do_retire(db, args, comma_sep=0): - '''Usage: retire designator[,designator]* - Retire the node specified by designator. - - This action indicates that a particular node is not to be retrieved by - the list or find commands, and its key value may be re-used. - ''' - designators = string.split(args[0], ',') - for designator in designators: - classname, nodeid = roundupdb.splitDesignator(designator) - db.getclass(classname).retire(nodeid) - return 0 - -def do_export(db, args, comma_sep=0): - '''Usage: export class[,class] destination_dir - Export the database to tab-separated-value files. - - This action exports the current data from the database into - tab-separated-value files that are placed in the nominated destination - directory. The journals are not exported. - ''' - if len(args) < 2: - print do_export.__doc__ - return 1 - classes = string.split(args[0], ',') - dir = args[1] + return 0 - # use the csv parser if we can - it's faster - if csv is not None: - p = csv.parser(field_sep=':') + def do_list(self, args): + '''Usage: list classname [property] + List the instances of a class. - # do all the classes specified - for classname in classes: - cl = db.getclass(classname) - f = open(os.path.join(dir, classname+'.csv'), 'w') - f.write(string.join(cl.properties.keys(), ':') + '\n') + Lists all instances of the given class. If the property is not + specified, the "label" property is used. The label property is tried + in order: the key, "name", "title" and then the first property, + alphabetically. + ''' + classname = args[0] + cl = self.db.getclass(classname) + if len(args) > 1: + key = args[1] + else: + key = cl.labelprop() + if self.comma_sep: + print ','.join(cl.list()) + else: + for nodeid in cl.list(): + value = cl.get(nodeid, key) + print "%4s: %s"%(nodeid, value) + return 0 + + def do_table(self, args): + '''Usage: table classname [property[,property]*] + List the instances of a class in tabular form. + + Lists all instances of the given class. If the properties are not + specified, all properties are displayed. By default, the column widths + are the width of the property names. The width may be explicitly defined + by defining the property as "name:width". For example:: + roundup> table priority id,name:10 + Id Name + 1 fatal-bug + 2 bug + 3 usability + 4 feature + ''' + classname = args[0] + cl = self.db.getclass(classname) + if len(args) > 1: + prop_names = args[1].split(',') + else: + prop_names = cl.getprops().keys() + props = [] + for name in prop_names: + if ':' in name: + name, width = name.split(':') + props.append((name, int(width))) + else: + props.append((name, len(name))) - # all nodes for this class - properties = cl.properties.items() + print ' '.join([string.capitalize(name) for name, width in props]) for nodeid in cl.list(): l = [] - for prop, type in properties: - value = cl.get(nodeid, prop) - # convert data where needed - if isinstance(type, hyperdb.Date): - value = value.get_tuple() - elif isinstance(type, hyperdb.Interval): - value = value.get_tuple() - elif isinstance(type, hyperdb.Password): - value = str(value) - l.append(repr(value)) + for name, width in props: + if name != 'id': + value = str(cl.get(nodeid, name)) + else: + value = str(nodeid) + f = '%%-%ds'%width + l.append(f%value[:width]) + print ' '.join(l) + return 0 + + def do_history(self, args): + '''Usage: history designator + Show the history entries of a designator. + + Lists the journal entries for the node identified by the designator. + ''' + classname, nodeid = roundupdb.splitDesignator(args[0]) + # TODO: handle the -c option? + print self.db.getclass(classname).history(nodeid) + return 0 - # now write - if csv is not None: - f.write(p.join(l) + '\n') - else: - # escape the individual entries to they're valid CSV - m = [] - for entry in l: - if '"' in entry: - entry = '""'.join(entry.split('"')) - if ':' in entry: - entry = '"%s"'%entry - m.append(entry) - f.write(':'.join(m) + '\n') - return 0 - -def do_import(db, args, comma_sep=0): - '''Usage: import class file - Import the contents of the tab-separated-value file. - - The file must define the same properties as the class (including having - a "header" line with those property names.) The new nodes are added to - the existing database - if you want to create a new database using the - imported data, then create a new database (or, tediously, retire all - the old data.) - ''' - if len(args) < 2: - print do_import.__doc__ - return 1 - if csv is None: - print 'Sorry, you need the csv module to use this function.' - print 'Get it from: http://www.object-craft.com.au/projects/csv/' - return 1 + def do_retire(self, args): + '''Usage: retire designator[,designator]* + Retire the node specified by designator. - from roundup import hyperdb - - # ensure that the properties and the CSV file headings match - cl = db.getclass(args[0]) - f = open(args[1]) - p = csv.parser(field_sep=':') - file_props = p.parse(f.readline()) - props = cl.properties.keys() - m = file_props[:] - m.sort() - props.sort() - if m != props: - print 'Import file doesn\'t define the same properties as "%s".'%args[0] - return 1 + This action indicates that a particular node is not to be retrieved by + the list or find commands, and its key value may be re-used. + ''' + designators = string.split(args[0], ',') + for designator in designators: + classname, nodeid = roundupdb.splitDesignator(designator) + self.db.getclass(classname).retire(nodeid) + return 0 + + def do_export(self, args): + '''Usage: export class[,class] destination_dir + Export the database to tab-separated-value files. + + This action exports the current data from the database into + tab-separated-value files that are placed in the nominated destination + directory. The journals are not exported. + ''' + if len(args) < 2: + print do_export.__doc__ + return 1 + classes = string.split(args[0], ',') + dir = args[1] + + # use the csv parser if we can - it's faster + if csv is not None: + p = csv.parser(field_sep=':') + + # do all the classes specified + for classname in classes: + cl = self.db.getclass(classname) + f = open(os.path.join(dir, classname+'.csv'), 'w') + f.write(string.join(cl.properties.keys(), ':') + '\n') + + # all nodes for this class + properties = cl.properties.items() + for nodeid in cl.list(): + l = [] + for prop, type in properties: + value = cl.get(nodeid, prop) + # convert data where needed + if isinstance(type, hyperdb.Date): + value = value.get_tuple() + elif isinstance(type, hyperdb.Interval): + value = value.get_tuple() + elif isinstance(type, hyperdb.Password): + value = str(value) + l.append(repr(value)) + + # now write + if csv is not None: + f.write(p.join(l) + '\n') + else: + # escape the individual entries to they're valid CSV + m = [] + for entry in l: + if '"' in entry: + entry = '""'.join(entry.split('"')) + if ':' in entry: + entry = '"%s"'%entry + m.append(entry) + f.write(':'.join(m) + '\n') + return 0 + + def do_import(self, args): + '''Usage: import class file + Import the contents of the tab-separated-value file. + + The file must define the same properties as the class (including having + a "header" line with those property names.) The new nodes are added to + the existing database - if you want to create a new database using the + imported data, then create a new database (or, tediously, retire all + the old data.) + ''' + if len(args) < 2: + print do_import.__doc__ + return 1 + if csv is None: + print 'Sorry, you need the csv module to use this function.' + print 'Get it from: http://www.object-craft.com.au/projects/csv/' + return 1 - # loop through the file and create a node for each entry - n = range(len(props)) - while 1: - line = f.readline() - if not line: break + from roundup import hyperdb - # parse lines until we get a complete entry + # ensure that the properties and the CSV file headings match + cl = self.db.getclass(args[0]) + f = open(args[1]) + p = csv.parser(field_sep=':') + file_props = p.parse(f.readline()) + props = cl.properties.keys() + m = file_props[:] + m.sort() + props.sort() + if m != props: + print 'Import file doesn\'t define the same properties as "%s".'%args[0] + return 1 + + # loop through the file and create a node for each entry + n = range(len(props)) while 1: - l = p.parse(line) - if l: break - - # make the new node's property map - d = {} - for i in n: - # Use eval to reverse the repr() used to output the CSV - value = eval(l[i]) - # Figure the property for this column - key = file_props[i] - type = cl.properties[key] - # Convert for property type - if isinstance(type, hyperdb.Date): - value = date.Date(value) - elif isinstance(type, hyperdb.Interval): - value = date.Interval(value) - elif isinstance(type, hyperdb.Password): - pwd = password.Password() - pwd.unpack(value) - value = pwd - if value is not None: - d[key] = value - - # and create the new node - apply(cl.create, (), d) - return 0 - -def figureCommands(): - d = {} - for k, v in globals().items(): - if k[:3] == 'do_': - d[k[3:]] = v - return d - -def figureHelp(): - d = {} - for k, v in globals().items(): - if k[:5] == 'help_': - d[k[5:]] = v - return d + line = f.readline() + if not line: break + + # parse lines until we get a complete entry + while 1: + l = p.parse(line) + if l: break + + # make the new node's property map + d = {} + for i in n: + # Use eval to reverse the repr() used to output the CSV + value = eval(l[i]) + # Figure the property for this column + key = file_props[i] + type = cl.properties[key] + # Convert for property type + if isinstance(type, hyperdb.Date): + value = date.Date(value) + elif isinstance(type, hyperdb.Interval): + value = date.Interval(value) + elif isinstance(type, hyperdb.Password): + pwd = password.Password() + pwd.unpack(value) + value = pwd + if value is not None: + d[key] = value + + # and create the new node + apply(cl.create, (), d) + return 0 -class AdminTool: def run_command(self, args): '''Run a single command ''' @@ -567,14 +575,14 @@ class AdminTool: # handle help now if command == 'help': if len(args)>1: - do_help(args[1:]) + self.do_help(args[1:]) return 0 - do_help(['help']) + self.do_help(['help']) return 0 if command == 'morehelp': - do_help(['help']) - help_commands() - help_all() + self.do_help(['help']) + self.help_commands() + self.help_all() return 0 # make sure we have an instance_home @@ -583,9 +591,9 @@ class AdminTool: # before we open the db, we may be doing an init if command == 'init': - return do_init(self.instance_home, args) + return self.do_init(self.instance_home, args) - function = figureCommands().get(command, None) + function = self.commands.get(command, None) # not a valid command if function is None: @@ -594,7 +602,7 @@ class AdminTool: # get the instance instance = roundup.instance.open(self.instance_home) - db = instance.open('admin') + self.db = instance.open('admin') if len(args) < 2: print function.__doc__ @@ -602,9 +610,9 @@ class AdminTool: # do the command try: - return function(db, args[1:], comma_sep=self.comma_sep) + return function(args[1:]) finally: - db.close() + self.db.close() return 1 @@ -663,6 +671,12 @@ if __name__ == '__main__': # # $Log: not supported by cvs2svn $ +# Revision 1.33 2001/10/17 23:13:19 richard +# Did a fair bit of work on the admin tool. Now has an extra command "table" +# which displays node information in a tabular format. Also fixed import and +# export so they work. Removed freshen. +# Fixed quopri usage in mailgw from bug reports. +# # Revision 1.32 2001/10/17 06:57:29 richard # Interactive startup blurb - need to figure how to get the version in there. #