diff --git a/roundup/admin.py b/roundup/admin.py
index ff961b77eb63c50084f049ff32a7d8835e20ba46..94e38462d4eb60dda9283f68ecf66d4893fdef73 100644 (file)
--- a/roundup/admin.py
+++ b/roundup/admin.py
# 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:
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():
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:
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] <command> <arguments>
self.help_commands()
def help_commands(self):
+ ''' List the commands available with their precis help.
+ '''
print _('Commands:'),
commands = ['']
for command in self.commands.values():
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]
# 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:
# 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)
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).
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)
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
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.
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()