Code

oops
[roundup.git] / roundup / admin.py
index ef7f9217585797379646436c14bdb92d52096994..b213c14d70624d8cee19dcd3cfc038ae3694fa89 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: admin.py,v 1.8 2002-02-27 03:28:21 richard Exp $
+# $Id: admin.py,v 1.18 2002-07-18 11:17:30 gmcm Exp $
 
-import sys, os, getpass, getopt, re, UserDict, shlex
+import sys, os, getpass, getopt, re, UserDict, shlex, shutil
 try:
     import csv
 except ImportError:
     csv = None
 from roundup import date, hyperdb, roundupdb, init, password, token
+from roundup import __version__ as roundup_version
 import roundup.instance
 from roundup.i18n import _
 
@@ -249,19 +250,31 @@ Command help:
         print _('Back ends:'), ', '.join(backends)
 
 
-    def do_initialise(self, instance_home, args):
-        '''Usage: initialise [template [backend [admin password]]]
-        Initialise a new Roundup instance.
+    def do_install(self, instance_home, args):
+        '''Usage: install [template [backend [admin password]]]
+        Install 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.
 
+        The initialise command must be called after this command in order
+        to initialise the instance's database. You may edit the instance's
+        initial database contents before running that command by editing
+        the instance's dbinit.py module init() function.
+
         See also initopts help.
         '''
         if len(args) < 1:
             raise UsageError, _('Not enough arguments supplied')
+
+        # make sure the instance home can be created
+        parent = os.path.split(instance_home)[0]
+        if not os.path.exists(parent):
+            raise UsageError, _('Instance home parent directory "%(parent)s"'
+                ' does not exist')%locals()
+
         # select template
         import roundup.templates
         templates = roundup.templates.listTemplates()
@@ -273,6 +286,7 @@ Command help:
             if not template:
                 template = 'classic'
 
+        # select hyperdb backend
         import roundup.backends
         backends = roundup.backends.__all__
         backend = len(args) > 2 and args[2] or ''
@@ -282,15 +296,64 @@ Command help:
             backend = raw_input(_('Select backend [anydbm]: ')).strip()
             if not backend:
                 backend = 'anydbm'
-        if len(args) > 3:
-            adminpw = confirm = args[3]
+
+        # install!
+        init.install(instance_home, template, backend)
+
+        print _('''
+ You should now edit the instance configuration file:
+   %(instance_config_file)s
+ ... at a minimum, you must set MAILHOST, MAIL_DOMAIN and ADMIN_EMAIL.
+
+ If you wish to modify the default schema, you should also edit the database
+ initialisation file:
+   %(database_config_file)s
+ ... see the documentation on customizing for more information.
+''')%{
+    'instance_config_file': os.path.join(instance_home, 'instance_config.py'),
+    'database_config_file': os.path.join(instance_home, 'dbinit.py')
+}
+        return 0
+
+
+    def do_initialise(self, instance_home, args):
+        '''Usage: initialise [adminpw]
+        Initialise a new Roundup instance.
+
+        The administrator details will be set at this step.
+
+        Execute the instance's initialisation function dbinit.init()
+        '''
+        # password
+        if len(args) > 1:
+            adminpw = args[1]
         else:
             adminpw = ''
             confirm = 'x'
-        while adminpw != confirm:
-            adminpw = getpass.getpass(_('Admin Password: '))
-            confirm = getpass.getpass(_('       Confirm: '))
-        init.init(instance_home, template, backend, adminpw)
+            while adminpw != confirm:
+                adminpw = getpass.getpass(_('Admin Password: '))
+                confirm = getpass.getpass(_('       Confirm: '))
+
+        # make sure the instance home is installed
+        if not os.path.exists(instance_home):
+            raise UsageError, _('Instance home does not exist')%locals()
+        if not os.path.exists(os.path.join(instance_home, 'html')):
+            raise UsageError, _('Instance has not been installed')%locals()
+
+        # is there already a database?
+        if os.path.exists(os.path.join(instance_home, 'db')):
+            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(instance_home, 'db'))
+
+        # GO
+        init.initialise(instance_home, adminpw)
+
         return 0
 
 
@@ -376,6 +439,10 @@ Command help:
                     props[key] = value
                 elif isinstance(proptype, hyperdb.Multilink):
                     props[key] = value.split(',')
+                elif isinstance(proptype, hyperdb.Boolean):
+                    props[key] = value.lower() in ('yes', 'true', 'on', '1')
+                elif isinstance(proptype, hyperdb.Number):
+                    props[key] = int(value)
 
             # try the set
             try:
@@ -424,9 +491,6 @@ Command help:
                 except TypeError:
                     raise UsageError, _('%(classname)s has no key property"')%{
                         'classname': link_class.classname}
-                except KeyError:
-                    raise UsageError, _('%(classname)s has no entry "%(propname)s"')%{
-                        'classname': link_class.classname, 'propname': propname}
 
         # now do the find 
         try:
@@ -529,7 +593,7 @@ Command help:
             props = self.props_from_args(args[1:])
 
         # convert types
-        for propname in props.keys():
+        for propname, value in props.items():
             # get the property
             try:
                 proptype = properties[propname]
@@ -551,6 +615,10 @@ Command help:
                 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)
 
         # check for the key property
         propname = cl.getkey()
@@ -896,14 +964,23 @@ Date format is "YYYY-MM-DD" eg:
             raise ValueError, _('Invalid format')
         m = m.groupdict()
         if m['period']:
-            # TODO: need to fix date module.  one should be able to say
-            # pack_before = date.Date(". - %s"%value)
-            pack_before = date.Date(".") + date.Interval("- %s"%value)
+            pack_before = date.Date(". - %s"%value)
         elif m['date']:
             pack_before = date.Date(value)
         self.db.pack(pack_before)
         return 0
 
+    def do_reindex(self, args):
+        '''Usage: reindex
+        Re-generate an instance's search indexes.
+
+        This will re-generate the search indexes for an instance. This will
+        typically happen automatically.
+        '''
+        self.db.indexer.force_reindex()
+        self.db.reindex()
+        return 0
+
     def run_command(self, args):
         '''Run a single command
         '''
@@ -942,16 +1019,26 @@ Date format is "YYYY-MM-DD" eg:
         while not self.instance_home:
             self.instance_home = raw_input(_('Enter instance home: ')).strip()
 
-        # before we open the db, we may be doing an init
+        # before we open the db, we may be doing an install or init
         if command == 'initialise':
-            return self.do_initialise(self.instance_home, args)
+            try:
+                return self.do_initialise(self.instance_home, args)
+            except UsageError, message:
+                print _('Error: %(message)s')%locals()
+                return 1
+        elif command == 'install':
+            try:
+                return self.do_install(self.instance_home, args)
+            except UsageError, message:
+                print _('Error: %(message)s')%locals()
+                return 1
 
         # get the instance
         try:
             instance = roundup.instance.open(self.instance_home)
         except ValueError, message:
             self.instance_home = ''
-            print _("Couldn't open instance: %(message)s")%locals()
+            print _("Error: Couldn't open instance: %(message)s")%locals()
             return 1
 
         # only open the database once!
@@ -964,6 +1051,7 @@ Date format is "YYYY-MM-DD" eg:
             ret = function(args[1:])
         except UsageError, message:
             print _('Error: %(message)s')%locals()
+            print
             print function.__doc__
             ret = 1
         except:
@@ -975,7 +1063,7 @@ Date format is "YYYY-MM-DD" eg:
     def interactive(self):
         '''Run in an interactive mode
         '''
-        print _('Roundup {version} ready for input.')
+        print _('Roundup %s ready for input.'%roundup_version)
         print _('Type "help" for help.')
         try:
             import readline
@@ -1043,6 +1131,41 @@ if __name__ == '__main__':
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.17  2002/07/14 06:05:50  richard
+#  . fixed the date module so that Date(". - 2d") works
+#
+# Revision 1.16  2002/07/09 04:19:09  richard
+# Added reindex command to roundup-admin.
+# Fixed reindex on first access.
+# Also fixed reindexing of entries that change.
+#
+# Revision 1.15  2002/06/17 23:14:44  richard
+# . #569415 ] {version}
+#
+# Revision 1.14  2002/06/11 06:41:50  richard
+# Removed prompt for admin email in initialisation.
+#
+# Revision 1.13  2002/05/30 23:58:14  richard
+# oops
+#
+# Revision 1.12  2002/05/26 09:04:42  richard
+# out by one in the init args
+#
+# Revision 1.11  2002/05/23 01:14:20  richard
+#  . split instance initialisation into two steps, allowing config changes
+#    before the database is initialised.
+#
+# Revision 1.10  2002/04/27 10:07:23  richard
+# minor fix to error message
+#
+# Revision 1.9  2002/03/12 22:51:47  richard
+#  . #527416 ] roundup-admin uses undefined value
+#  . #527503 ] unfriendly init blowup when parent dir
+#    (also handles UsageError correctly now in init)
+#
+# Revision 1.8  2002/02/27 03:28:21  richard
+# Ran it through pychecker, made fixes
+#
 # Revision 1.7  2002/02/20 05:04:32  richard
 # Wasn't handling the cvs parser feeding properly.
 #