[Zope-Checkins] CVS: ZODB3/zdaemon - zdoptions.py:1.3

Guido van Rossum guido@python.org
Thu, 16 Jan 2003 23:14:59 -0500


Update of /cvs-repository/ZODB3/zdaemon
In directory cvs.zope.org:/tmp/cvs-serv15288

Modified Files:
	zdoptions.py 
Log Message:
Add default and required keyword args to add().

Allow schema directory to be pre-sepcified.

Added some docstrings.

Minor other cleanup.


=== ZODB3/zdaemon/zdoptions.py 1.2 => 1.3 ===
--- ZODB3/zdaemon/zdoptions.py:1.2	Thu Jan 16 21:01:26 2003
+++ ZODB3/zdaemon/zdoptions.py	Thu Jan 16 23:14:56 2003
@@ -11,26 +11,36 @@
     doc = None
     progname = None
     configfile = None
+    schemadir = None
     schemafile = "schema.xml"
+    schema = None
+    configroot = None
 
     def __init__(self):
         self.names_list = []
         self.short_options = []
         self.long_options = []
         self.options_map = {}
+        self.default_map = {}
+        self.required_map = {}
         self.add(None, None, "h", "help", self.help)
         self.add("configfile", None, "C:", "configure=")
 
-    def help(self, value):
-        print self.doc.strip()
+    def help(self):
+        """Print a long help message (self.doc) to stdout and exit(0).
+
+        Occurrences of "%s" in self.doc are replaced by self.progname.
+        """
+        doc = self.doc
+        if doc.find("%s") > 0:
+            doc = doc.replace("%s", self.progname)
+        print doc,
         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)
+        """Print a brief error message to stderr and exit(2)."""
+        sys.stderr.write("Error: %s\n" % str(msg))
+        sys.stderr.write("For help, use %s -h\n" % self.progname)
         sys.exit(2)
 
     def add(self,
@@ -39,6 +49,8 @@
             short=None,                 # short option name
             long=None,                  # long option name
             handler=None,               # handler (defaults to string)
+            default=None,               # default value
+            required=None,              # message if not provided
             ):
         """Add information about a configuration option.
 
@@ -52,6 +64,11 @@
             Command line option calls handler
         add(name, None, short, long, handler)
             Assign handler return value to attribute 'name'
+
+        In addition, one of the following keyword arguments may be given:
+
+        default=...  -- if not None, the default value
+        required=... -- if nonempty, an error message if no value provided
        """
 
         if short and long:
@@ -78,6 +95,8 @@
             if key[-1] == "=":
                 key = key[:-1]
             key = "--" + key
+            if self.options_map.has_key(key):
+                raise ValueError, "duplicate long option key '%s'" % key
             self.options_map[key] = (name, handler)
             self.long_options.append(long)
 
@@ -85,15 +104,29 @@
             if not hasattr(self, name):
                 setattr(self, name, None)
             self.names_list.append((name, confname))
+            if default is not None:
+                self.default_map[name] = default
+            if required:
+                self.required_map[name] = required
 
     def realize(self, args=None, progname=None, doc=None):
-        """Realize a configuration."""
+        """Realize a configuration.
+
+        Optional arguments:
+
+        args     -- the command line arguments, less the program name
+                    (default is sys.argv[1:])
+
+        progname -- the program name (default is sys.argv[0])
+
+        doc      -- usage message (default is __main__.__doc__)
+        """
 
          # Provide dynamic default method arguments
         if args is None:
             args = sys.argv[1:]
         if progname is None:
-            self.progname = sys.argv[0]
+            progname = sys.argv[0]
         if doc is None:
             import __main__
             doc = __main__.__doc__
@@ -114,16 +147,18 @@
                 try:
                     arg = handler(arg)
                 except ValueError, msg:
-                    self.usage("invalid value for %s %s: %s" % (opt, arg, msg))
+                    self.usage("invalid value for %s %r: %s" % (opt, arg, msg))
             if name and arg is not None:
                 setattr(self, name, arg)
 
-        # Process config file
         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)
+            # Process config file
+            if self.schema is None:
+                # Load schema
+                if self.schemadir is None:
+                    self.schemadir = os.path.dirname(__file__)
+                self.schemafile = os.path.join(self.schemadir, self.schemafile)
+                self.schema = ZConfig.loadSchema(self.schemafile)
 
             # Load configuration
             try:
@@ -144,6 +179,16 @@
                     # Here AttributeError is not a user error!
                     obj = getattr(obj, part)
                 setattr(self, name, obj)
+
+        # Process defaults
+        for name, value in self.default_map.items():
+            if getattr(self, name) is None:
+                setattr(self, name, value)
+
+        # Process required options
+        for name, message in self.required_map.items():
+            if getattr(self, name) is None:
+                self.usage(message)
 
 
 def _test():