[Zodb-checkins] CVS: ZODB3/zdaemon - zdoptions.py:1.1 zdctl.py:1.14
Guido van Rossum
guido@python.org
Wed, 15 Jan 2003 14:09:32 -0500
Update of /cvs-repository/ZODB3/zdaemon
In directory cvs.zope.org:/tmp/cvs-serv19740
Modified Files:
zdctl.py
Added Files:
zdoptions.py
Log Message:
A new, more generic approach to command line option parsing integrated
with ZConfig schema-driven config file parsing. Prototyped in zdaemon.py.
=== Added File ZODB3/zdaemon/zdoptions.py ===
"""Option processing for zdaemon and related code."""
import os
import sys
import getopt
import ZConfig
class ZDOptions:
doc = None
progname = None
configfile = None
schemafile = "schema.xml"
def __init__(self):
self.table = {}
self.short_options = {}
self.long_options = {}
self.add("help", "h", "help", handler=self.help)
self.add("configfile", "C:", "configure=")
def help(self, value):
print self.doc.strip()
sys.exit(0)
def usage(self, msg):
sys.stderr.write(str(msg) + "\n")
progname = self.progname
if progname is None:
progname = sys.argv[0]
sys.stderr.write("for more help, use %s --help\n" % progname)
sys.exit(2)
def add(self,
name, # attribute name on self
short=None, # short option name
long=None, # long option name
confname=None, # name in ZConfig (may be dotted)
handler=None, # handler (defaults to string)
required=None, # message issed if missing
):
if self.table.has_key(name):
raise ValueError, "duplicate option name: " + repr(name)
if short:
if short[0] == "-":
raise ValueError, "short option should not start with '-'"
key, rest = short[:1], short[1:]
if rest and rest != ":":
raise ValueError, "short option should be 'x' or 'x:'"
if self.short_options.has_key(key):
raise ValueError, "duplicate short option: " + repr(short)
if long:
if long[0] == "-":
raise ValueError, "long option should not start with '-'"
key = long
if key[-1] == "=":
key = key[:-1]
if self.long_options.has_key(key):
raise ValueError, "duplicate long option: " + repr(long)
if short and long:
if short.endswith(":") != long.endswith("="):
raise ValueError, "inconsistent short/long options: %r %r" % (
short, long)
self.table[name] = (short, long, confname, handler, required)
if short:
self.short_options[short[0]] = name
if long:
key = long
if key[-1] == "=":
key = key[:-1]
self.long_options[key] = name
def realize(self, args=None, progname=None, doc=None):
"""Realize a configuration."""
if args is None:
args = sys.argv[1:]
if progname is None:
self.progname = sys.argv[0]
if doc is None:
import __main__
doc = __main__.__doc__
self.progname = progname
self.doc = doc
# Construct short and long option tables for getopt
shorts = ""
longs = []
for name, (short, long, xxx, xxx, xxx) in self.table.items():
if short:
shorts += short
if long:
longs.append(long)
# Call getopt
try:
self.options, self.args = getopt.getopt(args, shorts, longs)
except getopt.error, msg:
self.usage(msg)
# Process options returned by getopt
for o, a in self.options:
if o.startswith("--"):
name = self.long_options[o[2:]]
elif o.startswith("-"):
name = self.short_options[o[1:]]
else:
self.usage("unrecognized option " + repr(o))
handler = self.table[name][3]
if handler is None:
value = a
else:
try:
value = handler(a)
except ValueError, msg:
self.usage("invalid value for %s %s: %s" % (o, a, msg))
setattr(self, name, value)
if self.configfile is not None:
# Load schema
here = os.path.dirname(__file__)
self.schemafile = os.path.join(here, self.schemafile)
self.schema = ZConfig.loadSchema(self.schemafile)
# Load configuration
try:
self.configroot, xxx = ZConfig.loadConfig(self.schema,
self.configfile)
except ZConfig.ConfigurationError, msg:
self.usage(str(msg))
# Copy config options to attributes of self. This only fills
# in options that aren't already set from the command line.
for name in self.table.keys():
if not hasattr(self, name) or getattr(self, name) is None:
confname = self.table[name][2]
parts = confname.split(".")
obj = self.configroot
for part in parts:
if obj is None:
break
# If this raises AttributeError, that's not a user error!
obj = getattr(obj, part)
setattr(self, name, obj)
def _test():
# Stupid test program
z = ZDOptions()
z.add("program", "p:", "program=", "zdctl.program")
z.realize()
names = z.table.keys()
names.sort()
for name in names:
print "%-20s = %.56r" % (name, getattr(z, name))
if __name__ == "__main__":
__file__ = sys.argv[0]
_test()
=== ZODB3/zdaemon/zdctl.py 1.13 => 1.14 ===
--- ZODB3/zdaemon/zdctl.py:1.13 Tue Jan 14 17:36:53 2003
+++ ZODB3/zdaemon/zdctl.py Wed Jan 15 14:09:29 2003
@@ -47,10 +47,14 @@
sys.path.append(dirname(dirname(normpath(abspath(sys.argv[0])))))
import ZConfig
-from ZEO.runsvr import Options
+import zdoptions
-class ZDOptions(Options):
+def string_list(arg):
+ return arg.split()
+
+
+class ZDOptions(zdoptions.ZDOptions):
# Where's python?
python = sys.executable
@@ -72,24 +76,9 @@
user = None # -u USER
zdirectory = "/" # -z DIRECTORY
- # Program (and arguments) for zdaemon
- program = None
-
- def load_schema(self):
- self.schemafile = os.path.join(self._dir, "schema.xml")
- self.schema = ZConfig.loadSchema(self.schemafile)
-
- def load_configuration(self):
- Options.load_configuration(self) # Sets self.rootconf
- if not self.rootconf:
- self.usage("a configuration file is required; use -C")
- # XXX Should allow overriding more zdaemon options here
- if self.program is None:
- program = self.rootconf.zdctl.program
- if program:
- self.program = program.split()
- if self.program is None:
- self.usage("no program specified in configuration")
+ def __init__(self):
+ zdoptions.ZDOptions.__init__(self)
+ self.add("program", "p:", "program=", "zdctl.program", string_list)
class ZDCmd(cmd.Cmd):
@@ -110,6 +99,9 @@
print "our program =", self.options.program
print "daemon's args =", args
+ def emptyline(self):
+ pass # We don't want a blank line to repeat the last command
+
def send_action(self, action):
"""Send an action to the zdaemon server and return the response.
@@ -288,7 +280,7 @@
def show_options(self):
print "schemafile: ", repr(self.options.schemafile)
- print "configuration:", repr(self.options.configuration)
+ print "configfile: ", repr(self.options.configfile)
print "zdaemon: ", repr(self.options.zdaemon)
print "program: ", repr(self.options.program)
print "backofflimit:", repr(self.options.backofflimit)
@@ -342,7 +334,8 @@
"stop the daemon manager.")
def main(args=None):
- options = ZDOptions(args)
+ options = ZDOptions()
+ options.realize(args)
c = ZDCmd(options)
if options.args:
c.onecmd(" ".join(options.args))