[Zope-Checkins] CVS: Zope/lib/python/Zope/Startup - cmdline.py:1.1.2.1 ZctlLib.py:1.1.2.5 __init__.py:1.1.2.2 handlers.py:1.1.2.3

Chris McDonough chrism@zope.com
Tue, 14 Jan 2003 22:39:09 -0500


Update of /cvs-repository/Zope/lib/python/Zope/Startup
In directory cvs.zope.org:/tmp/cvs-serv22900/lib/python/Zope/Startup

Modified Files:
      Tag: chrism-install-branch
	ZctlLib.py __init__.py handlers.py 
Added Files:
      Tag: chrism-install-branch
	cmdline.py 
Log Message:
Add command-line option override support to installer branch.


=== Added File Zope/lib/python/Zope/Startup/cmdline.py ===
import getopt

def getOptionDescriptions():
    """ Temporary implementation """

    short, long = getOptions()
    n = 0
    short_d = {}
    long_d = {}

    last = 0
    n = 0

    print short

    if short:
        while 1:
            try:
                opt = short[n]
            except IndexError:
                next = None
            try:
                next = short[n+1]
            except IndexError:
                next = None
            if next == ':':
                short_d[opt] = 1
                n = n + 2
            else:
                if next is None and short.endswith(':'):
                    short_d[opt] = 1
                else:
                    short_d[opt] = 0
                n = n + 1
            if next is None:
                break

    for opt in long:
        if opt.endswith('='):
            long_d[opt[:-1]] = 1
        else:
            long_d[opt] = 0

    opts = []

    short_l = short_d.items()
    short_l.sort()
    for k, v in short_l:
        opts.append('    -%s%s' % (k, (v and ' <value>' or '')))

    long_l = long_d.items()
    long_l.sort()
    for k, v in long_l:
        opts.append('    --%s%s' % (k, (v and ' <value>' or '')))
    return '\n'.join(opts)

def getOptions():
    short = 'Z:t:i:D:a:d:u:L:l:M:E:Xw:W:f:p:F:m:'
    long  = [
             'use-daemon-process=',
             'zserver-threads=',
             'python-check-interval=',
             'debug-mode=',
             'ip-address=',
             'dns-ip-address=',
             'effective-user=',
             'locale=',
             'access-log=',
             'trace-log=',
             'event-log=',
             'disable-servers',
             'http-server=',
             'webdav-source-server=',
# XXX need to finish these
#             'ftp-server=',
#             'pcgi-server=',
#             'fcgi-server=',
#             'monitor-server=',
#             'icp-server=',
             ]
    return short, long

class CommandLineOptions:

    def __call__(self, cfg, options):
        import Zope.Startup.datatypes
        import Zope.Startup.handlers
        import ZConfig.datatypes

        short, long = getOptions()
        opts, args = getopt.getopt(options, short, long)

        for k, v in opts:
            # set up data that servers may rely on
            if k in ('-Z', '--use-daemon-process'):
                datatype = Zope.Startup.datatypes.use_daemon_process
                handler  = Zope.Startup.handlers.use_daemon_process
                v = datatype(v)
                handler(v)
                cfg.use_daemon_process = v
            elif k in ('-t', '--zserver-threads'):
                datatype = int
                v = datatype(v)
                cfg.zserver_threads = v
            elif k in ('-i', '--python-check-interval'):
                datatype = int
                v = datatype(v)
                cfg.python_check_interval = v
            elif k in ('-D', '--debug-mode'):
                datatype = ZConfig.datatypes.asBoolean
                handler =  Zope.Startup.handlers.debug_mode
                v = datatype(v)
                handler(v)
                cfg.debug_mode = v
            elif k in ('-i', '--ip-address'):
                datatype = ZConfig.datatypes.IpaddrOrHostname()
                v = datatype(v)
                cfg.ip_address = v
            elif k in ('-d', '--dns-ip-address'):
                datatype = ZConfig.datatypes.IpaddrOrHostname()
                v = datatype(v)
                cfg.dns_ip_address = v
            elif k in ('-u', '--effective-user'):
                cfg.effective_user = v
            elif k in ('-L', '--locale'):
                datatype = ZConfig.datatypes.check_locale
                v = datatype(v)
                cfg.locale = v
            elif k in ('-l', '--access-log'):
                cfg.access = default_logger('access', v,
                                            '%(message)s',
                                            '%Y-%m-%dT%H:%M:%S')
            elif k in ('-M', '--trace-log'):
                cfg.trace = default_logger('trace', v,
                                            '%(message)s',
                                            '%Y-%m-%dT%H:%M:%S')
            elif k in ('-E', '--event-log'):
                cfg.trace = default_logger('event', v,
                                            '------\n%(asctime)s %(message)s',
                                            '%Y-%m-%dT%H:%M:%S')
            elif k in ('-X', '--disable-servers'):
                cfg.servers = []
            else:
                # continue if we've not matched, otherwise
                # fall through to the pop statement below
                continue

            opts.pop(0) # pop non-server data from opts

        factory = Zope.Startup.handlers.ServerFactoryFactory(cfg)

        for k, v in opts:
            # set up server data from what's left in opts,
            # using repopulated cfg
            if k in ('-w', '--http-server'):
                datatype = ZConfig.datatypes.inet_address
                host, port = datatype(v)
                section = dummy()
                section.ports = [(host, port)]
                section.force_connection_close = 0
                cfg.servers.append(['http_server',
                                    factory.http_server(section)[0]])
            if k in ('-W', '--webdav-source-server'):
                datatype = ZConfig.datatypes.inet_address
                host, port = datatype(v)
                section = dummy()
                section.ports = [(host, port)]
                section.force_connection_close = 0
                cfg.servers.append(['webdav_source_server',
                                    factory.webdav_source_server(section)[0]])

class dummy:
    # used as a namespace generator
    pass
            
def default_logger(name, file, format, dateformat):
    import Zope.Startup.datatypes
    logger = dummy()
    logger.level = 20
    handler = dummy()
    handler.file = file
    handler.format = format
    handler.dateformat = dateformat
    handler.level = 20
    handlers = [Zope.Startup.datatypes.file_handler(handler)]
    return Zope.Startup.datatypes.LoggerWrapper(name, 20, handlers)


=== Zope/lib/python/Zope/Startup/ZctlLib.py 1.1.2.4 => 1.1.2.5 ===
--- Zope/lib/python/Zope/Startup/ZctlLib.py:1.1.2.4	Tue Jan 14 13:00:16 2003
+++ Zope/lib/python/Zope/Startup/ZctlLib.py	Tue Jan 14 22:39:05 2003
@@ -29,7 +29,7 @@
     import readline
 except:
     readline = None
-from Zope.Startup import getSchemaKeys, configure
+from Zope.Startup import getOptions, getOptionDescriptions, configure
 from Zope.Startup.misc import TextBlockFormatter
 from Zope.Startup.misc.lock_file import lock_file
 
@@ -40,7 +40,7 @@
 zopectl:  Zope appserver controller
 
 Usage:
-    zopectl [-h | --help] [--config=filepath or url]
+    zopectl [-h | --help] [--config=filepath or url] [additional options]
 
 Options:
     -h or --help       Print this message.  Not compatible with the 'start'
@@ -55,6 +55,10 @@
                        File example: '/home/chrism/zope.conf'
                        URL example:  'http://www.zope.org/zope.conf'
 
+Additional options:
+
+%s
+
 Commands:
     help [<command>]
     start
@@ -294,12 +298,11 @@
 
     def _getRunCmd(self):
         swhome = self._getSoftwareHome()
-        overrides = self._getOverrides()
         return(
             "import os, sys; os.environ['EVENT_LOG_SEVERITY']='300'; "
             "sys.path.insert(0, '%s'); from Zope.Startup import configure; "
             "configure('%s', %s); import Zope; app=Zope.app()"
-            % ( swhome, self._getConfigLocation(), overrides)
+            % ( swhome, self._getConfigLocation(), self._getCommandLineOpts())
             )
 
     def run( self, arg ):
@@ -378,7 +381,8 @@
         self._report( normalizeDocstring( getattr( self, method_name ) ) )
 
     def _reconfigure(self):
-        self._config = configure(self._config_location, self._overrides)
+        self._config = configure(self._config_location,
+                                 self._getCommandLineOpts())
 
     def _setConfigLocation(self, config_location):
         self._config_location = config_location
@@ -395,17 +399,8 @@
     def _setCommandLineOpts( self, l ):
         self._cmdline = l
 
-    def _setOverrides(self, overrides):
-        self._overrides = overrides
-
-    def _getOverrides(self):
-        return self._overrides
-
     def _getCommandLineOpts(self):
-        l = []
-        for k,v in self._cmdline:
-            l.append('%s=%s' % (k,v))
-        return l
+        return self._cmdline
 
     def _spawnPython(self, *args, **kw):
         if not kw.has_key('wait'):
@@ -663,35 +658,42 @@
     #   Command-line processing
     #
     def usage( self ):
-        self._report( USAGE )
+        opts = getOptionDescriptions()
+        self._report( USAGE % opts)
 
     def main( self, config_location ):
-        overrides = {}
         # add relevant options to options list
-        schema_keys = getSchemaKeys()
         longopts = [ "help", "config="]
-        for name in schema_keys:
-            longopts.append('%s=' % name)
+        shortopts = "h"
+        start_shortopts, start_longopts = getOptions()
+        optcopy = sys.argv[1:]
+
         try:
-            opts, args = getopt.getopt(sys.argv[1:], "h", longopts)
+            opts, args = getopt.getopt(optcopy, start_shortopts+shortopts,
+                                       start_longopts+longopts)
         except getopt.GetoptError, v:
             print v
             self.usage()
             sys.exit(127)
+
         for k, v in opts:
             if k in ('-h', '--help'):
                 self.usage()
                 sys.exit(0)
             elif k == '--config':
                 config_location = v
-                overrides[k[2:]] = v
-            else:
-                if k.startswith('--'):
-                    k = k[2:]
-                    overrides[k] = v
+                i = 0
+                # remove --config= from optcopy
+                for item in optcopy:
+                    if item.startswith('--config='):
+                        break
+                    i = i + 1
+                optcopy.pop(i)
         self._engine._setConfigLocation(config_location)
-        self._engine._setCommandLineOpts(opts)
-        self._engine._setOverrides(overrides)
+        if not args:
+            self._engine._setCommandLineOpts(optcopy)
+        else:
+            self._engine._setCommandLineOpts(optcopy[len(args):])
         self._engine._reconfigure()
         if args:
             self.cmdqueue.append(' '.join(args))


=== Zope/lib/python/Zope/Startup/__init__.py 1.1.2.1 => 1.1.2.2 ===
--- Zope/lib/python/Zope/Startup/__init__.py:1.1.2.1	Sat Jan  4 23:01:37 2003
+++ Zope/lib/python/Zope/Startup/__init__.py	Tue Jan 14 22:39:05 2003
@@ -9,6 +9,7 @@
 from ZConfig import ConfigurationError
 from ZConfig import loadSchema, loadConfig
 from misc.lock_file import lock_file
+from cmdline import getOptions, getOptionDescriptions
 
 # global to hold config structure
 _configuration = None
@@ -26,23 +27,20 @@
     schema = loadSchema(f)
     return schema.getchildnames()
 
-def configure(config_location, overrides):
+def configure(config_location, options):
     f = getSchemaLocation()
     schema = loadSchema(f)
     import handlers
     config, handler = loadConfig(schema, config_location)
-    handlers.handleConfig(config, handler)
-##     for name, value in overrides.items():
-##         key = config.getSub(KEY_TYPE, KEY_TYPE, name)
-##         key.setValue(value)
+    handlers.handleConfig(config, handler, options)
     global _configuration
     _configuration = config
     return _configuration
     
-def start_zope(config_location, overrides):
+def start_zope(config_location, options):
     # caller must set configuration
     check_python_version()
-    cfg = configure(config_location, overrides)
+    cfg = configure(config_location, options)
 
     if cfg.zope_home not in sys.path:
         sys.path.insert(0, cfg.zope_home)


=== Zope/lib/python/Zope/Startup/handlers.py 1.1.2.2 => 1.1.2.3 ===
--- Zope/lib/python/Zope/Startup/handlers.py:1.1.2.2	Mon Jan 13 17:37:37 2003
+++ Zope/lib/python/Zope/Startup/handlers.py	Tue Jan 14 22:39:05 2003
@@ -136,39 +136,28 @@
 # server handlers
 
 class _RootHandler:
+    def __init__(self, options):
+        self.options = options
+        
     def __call__(self, config):
         """ Mutate the configuration with defaults and perform
         fixups of values that require knowledge about configuration
         values outside of their context. """
 
-        self._config = config
-
-        # alias some things for use in server handlers
-        from zLOG.AccessLogger import access_logger
-        self._logger = access_logger
-        import ZODB # :-( required to import user
-        from AccessControl.User import emergency_user
-        if hasattr(emergency_user, '__null_user__'):
-            self._pw = None
-        else:
-            self._pw = emergency_user._getPassword()
-        self._resolver = self.get_dns_resolver()
-        self._read_only = config.zserver_read_only_mode
-        self._default_ip = config.ip_address
-        self._module = 'Zope' # no longer settable
-
         # set up cgi overrides
-        self._env = {}
+        env = {}
         for pair in config.cgi_environment_variables:
             key, value = pair
             self._env[key] = value
-        config.cgi_environment_variables = self._env
+        config.cgi_environment_variables = env
 
-        # set up server factories via dispatch
+        # set up server factories
+        factory = ServerFactoryFactory(config)
         l = []
+
         for section in config.servers:
             server_type = section.__type__.name
-            for server_factory in getattr(self, server_type)(section):
+            for server_factory in getattr(factory, server_type)(section):
                 l.append((server_type, server_factory))
 
         # if no servers are defined, create default http server and ftp server
@@ -181,8 +170,8 @@
             http.force_connection_close = 0
             ftp.ports = [('', 8021)]
 
-            http = self.http_server(http)[0]
-            ftp = self.ftp_server(ftp)[0]
+            http = factory.http_server(http)[0]
+            ftp = factory.ftp_server(ftp)[0]
             l.extend([('http_server', http), ('ftp_server', ftp)])
 
         config.servers = l
@@ -218,6 +207,29 @@
             dbfactory = Factory('ZODB.DB', None, *[], **{})
             databases.append((['/'], DBWrapper(dbfactory, storagefactory)))
 
+        # do command-line overrides
+        import cmdline
+        opt_processor = cmdline.CommandLineOptions()
+        opt_processor(config, self.options)
+
+class ServerFactoryFactory:
+    def __init__(self, config):
+        self._config = config
+        # alias some things for use in server handlers
+        from zLOG.AccessLogger import access_logger
+        self._logger = access_logger
+        import ZODB # :-( required to import user
+        from AccessControl.User import emergency_user
+        if hasattr(emergency_user, '__null_user__'):
+            self._pw = None
+        else:
+            self._pw = emergency_user._getPassword()
+        self._resolver = self.get_dns_resolver()
+        self._read_only = config.zserver_read_only_mode
+        self._default_ip = config.ip_address
+        self._env = config.cgi_environment_variables
+        self._module = 'Zope' # no longer settable
+
     def get_dns_resolver(self):
         if self._config.dns_ip_address:
             from ZServer import resolver
@@ -317,13 +329,13 @@
             l.append(serverfactory)
         return l
 
-root_handler = _RootHandler()
-
-def handleConfig(config, multihandler):
+def handleConfig(config, multihandler, options):
     handlers = {}
     for name, value in globals().items():
         if not name.startswith('_'):
             handlers[name] = value
+    root_handler = _RootHandler(options)
+    handlers['root_handler'] = root_handler
     return multihandler(handlers)
     
 def make_dict(**kw):