X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fadmin.py;h=94e38462d4eb60dda9283f68ecf66d4893fdef73;hb=387441f5eb4ea526c9c4144f14e12cd024ad992f;hp=ff961b77eb63c50084f049ff32a7d8835e20ba46;hpb=583c4b40dbbb17696b33e6d21ed531a32730d818;p=roundup.git diff --git a/roundup/admin.py b/roundup/admin.py index ff961b7..94e3846 100644 --- a/roundup/admin.py +++ b/roundup/admin.py @@ -16,7 +16,10 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: admin.py,v 1.32 2002-09-24 01:36:04 richard Exp $ +# $Id: admin.py,v 1.38 2003-02-25 10:19:31 richard Exp $ + +'''Administration commands for maintaining Roundup trackers. +''' import sys, os, getpass, getopt, re, UserDict, shlex, shutil try: @@ -51,7 +54,17 @@ class UsageError(ValueError): pass class AdminTool: + ''' A collection of methods used in maintaining Roundup trackers. + + Typically these methods are accessed through the roundup-admin + script. The main() method provided on this class gives the main + loop for the roundup-admin script. + Actions are defined by do_*() methods, with help for the action + given in the method docstring. + + Additional help may be supplied by help_*() methods. + ''' def __init__(self): self.commands = CommandDict() for k in AdminTool.__dict__.keys(): @@ -73,14 +86,20 @@ class AdminTool: raise UsageError, _('no such class "%(classname)s"')%locals() def props_from_args(self, args): + ''' Produce a dictionary of prop: value from the args list. + + The args list is specified as ``prop=value prop=value ...``. + ''' props = {} for arg in args: if arg.find('=') == -1: - raise UsageError, _('argument "%(arg)s" not propname=value')%locals() + raise UsageError, _('argument "%(arg)s" not propname=value' + )%locals() try: key, value = arg.split('=') except ValueError: - raise UsageError, _('argument "%(arg)s" not propname=value')%locals() + raise UsageError, _('argument "%(arg)s" not propname=value' + )%locals() if value: props[key] = value else: @@ -88,6 +107,8 @@ class AdminTool: return props def usage(self, message=''): + ''' Display a simple usage message. + ''' if message: message = _('Problem: %(message)s)\n\n')%locals() print _('''%(message)sUsage: roundup-admin [options] @@ -106,6 +127,8 @@ Help: self.help_commands() def help_commands(self): + ''' List the commands available with their precis help. + ''' print _('Commands:'), commands = [''] for command in self.commands.values(): @@ -118,11 +141,13 @@ Help: print def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')): - commands = self.commands.values() + ''' Produce an HTML command list. + ''' + commands = self.commands.values() def sortfun(a, b): return cmp(a.__name__, b.__name__) commands.sort(sortfun) - for command in commands: + for command in commands: h = command.__doc__.split('\n') name = command.__name__[3:] usage = h[0] @@ -303,12 +328,14 @@ Command help: # XXX perform a unit test based on the user's selections # install! - init.install(tracker_home, template, backend) + init.install(tracker_home, template) + init.write_select_db(tracker_home, backend) print _(''' You should now edit the tracker configuration file: %(config_file)s - ... at a minimum, you must set MAILHOST, MAIL_DOMAIN and ADMIN_EMAIL. + ... at a minimum, you must set MAILHOST, TRACKER_WEB, MAIL_DOMAIN and + ADMIN_EMAIL. If you wish to modify the default schema, you should also edit the database initialisation file: @@ -342,19 +369,31 @@ Command help: # make sure the tracker home is installed if not os.path.exists(tracker_home): raise UsageError, _('Instance home does not exist')%locals() - if not os.path.exists(os.path.join(tracker_home, 'html')): + try: + tracker = roundup.instance.open(tracker_home) + except roundup.instance.TrackerError: raise UsageError, _('Instance has not been installed')%locals() # is there already a database? - if os.path.exists(os.path.join(tracker_home, 'db')): + try: + db_exists = tracker.select_db.Database.exists(tracker.config) + except AttributeError: + # TODO: move this code to exists() static method in every backend + db_exists = os.path.exists(os.path.join(tracker_home, 'db')) + if db_exists: print _('WARNING: The database is already initialised!') print _('If you re-initialise it, you will lose all the data!') ok = raw_input(_('Erase it? Y/[N]: ')).strip() if ok.lower() != 'y': return 0 - # nuke it - shutil.rmtree(os.path.join(tracker_home, 'db')) + # Get a database backend in use by tracker + try: + # nuke it + tracker.select_db.Database.nuke(tracker.config) + except AttributeError: + # TODO: move this code to nuke() static method in every backend + shutil.rmtree(os.path.join(tracker_home, 'db')) # GO init.initialise(tracker_home, adminpw) @@ -397,7 +436,7 @@ Command help: return 0 - def do_set(self, args): + def do_set(self, args, pwre = re.compile(r'{(\w+)}(.+)')): '''Usage: set [items] property=value property=value ... Set the given properties of one or more items(s). @@ -447,7 +486,15 @@ Command help: elif isinstance(proptype, hyperdb.String): continue elif isinstance(proptype, hyperdb.Password): - props[key] = password.Password(value) + m = pwre.match(value) + if m: + # password is being given to us encrypted + p = password.Password() + p.scheme = m.group(1) + p.password = m.group(2) + props[key] = p + else: + props[key] = password.Password(value) elif isinstance(proptype, hyperdb.Date): try: props[key] = date.Date(value) @@ -463,12 +510,13 @@ Command help: elif isinstance(proptype, hyperdb.Boolean): props[key] = value.lower() in ('yes', 'true', 'on', '1') elif isinstance(proptype, hyperdb.Number): - props[key] = int(value) + props[key] = float(value) # try the set try: apply(cl.set, (itemid, ), props) except (TypeError, IndexError, ValueError), message: + import traceback; traceback.print_exc() raise UsageError, message return 0 @@ -570,7 +618,7 @@ Command help: value = cl.get(nodeid, key) print _('%(key)s: %(value)s')%locals() - def do_create(self, args): + def do_create(self, args, pwre = re.compile(r'{(\w+)}(.+)')): '''Usage: create classname property=value ... Create a new entry of a given class. @@ -633,13 +681,21 @@ Command help: except ValueError, message: raise UsageError, _('"%(value)s": %(message)s')%locals() elif isinstance(proptype, hyperdb.Password): - props[propname] = password.Password(value) + m = pwre.match(value) + if m: + # password is being given to us encrypted + p = password.Password() + p.scheme = m.group(1) + p.password = m.group(2) + props[propname] = p + else: + props[propname] = password.Password(value) elif isinstance(proptype, hyperdb.Multilink): props[propname] = value.split(',') elif isinstance(proptype, hyperdb.Boolean): props[propname] = value.lower() in ('yes', 'true', 'on', '1') elif isinstance(proptype, hyperdb.Number): - props[propname] = int(value) + props[propname] = float(value) # check for the key property propname = cl.getkey()