[Zope3-checkins] CVS: Zope3/src/zope/fssync - command.py:1.1 main.py:1.28

Fred L. Drake, Jr. fred at zope.com
Mon Aug 11 17:55:57 EDT 2003


Update of /cvs-repository/Zope3/src/zope/fssync
In directory cvs.zope.org:/tmp/cvs-serv27084

Modified Files:
	main.py 
Added Files:
	command.py 
Log Message:
Refactor the command-line handling from the command implementation.
This facilitates implementing a new bundle management tool that uses a similar command
structure but all-different commands.


=== Added File Zope3/src/zope/fssync/command.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Table-based program command dispatcher.

This dispatcher supports a 'named command' dispatch similar to that
found in the standard CVS and Subversion client applications.

$Id: command.py,v 1.1 2003/08/11 20:55:21 fdrake Exp $
"""

import getopt
import os.path
import sys


from zope.fssync.fsutil import Error


class Usage(Error):
    """Subclass for usage error (command-line syntax).

    You should return an exit status of 2 rather than 1 when catching this.
    """


class Command:

    def __init__(self, name=None, usage=None):
        if name is None:
            name = os.path.basename(sys.argv[0])
        self.program = name
        if usage is None:
            import __main__
            usage = __main__.__doc__
        self.helptext = usage
        self.command_table = {}
        self.global_options = []
        self.local_options = []
        self.command = None

    def addCommand(self, name, function, short="", long="", aliases=""):
        names = [name] + aliases.split()
        cmdinfo = short, long.split(), function
        for n in names:
            assert n not in self.command_table
            self.command_table[n] = cmdinfo

    def realize(self, args=None):
        if args is None:
            args = sys.argv[1:]
        self.global_options, args = self.getopt("global",
                                                args, "h", ["help"],
                                                self.helptext)
        if not args:
            raise Usage("missing command argument")
        self.command = args.pop(0)
        if self.command not in self.command_table:
            raise Usage("unrecognized command")
        cmdinfo = self.command_table[self.command]
        short, long, func = cmdinfo
        short = "h" + short
        long = ["help"] + list(long)
        self.local_options, self.args = self.getopt(self.command,
                                                    args, short, long,
                                                    func.__doc__)

    def getopt(self, cmd, args, short, long, helptext):
        try:
            opts, args = getopt.getopt(args, short, long)
        except getopt.error, e:
            raise Usage("%s option error: %s", cmd, e)
        for opt, arg in opts:
            if opt in ("-h", "--help"):
                self.usage(sys.stdout, helptext)
                sys.exit()
        return opts, args

    def run(self):
        _, _, func = self.command_table[self.command]
        func(self.local_options, self.args)

    def usage(self, file, text):
        print >>file, text % {"program": self.program}


=== Zope3/src/zope/fssync/main.py 1.27 => 1.28 ===
--- Zope3/src/zope/fssync/main.py:1.27	Fri Aug  8 17:45:39 2003
+++ Zope3/src/zope/fssync/main.py	Mon Aug 11 16:55:21 2003
@@ -53,73 +53,26 @@
     srcdir = join(rootdir, "src")
     sys.path.append(srcdir)
 
+from zope.fssync.command import Command, Usage
 from zope.fssync.fsutil import Error
 from zope.fssync.fssync import FSSync
 
-class Usage(Error):
-    """Subclass for usage error (command-line syntax).
 
-    You should return an exit status of 2 rather than 1 when catching this.
-    """
-
-def main(argv=None):
+def main():
     """Main program.
 
-    You can pass it an argument list (which must include the command
-    name as argv[0]); it defaults to sys.argv.
-
     The return value is the suggested sys.exit() status code:
     0 or None for success
     2 for command line syntax errors
     1 or other for later errors
     """
-    try:
-        if argv is None:
-            argv = sys.argv
+    cmd = Command()
+    for func, aliases, short, long in command_table:
+        cmd.addCommand(func.__name__, func, short, long, aliases)
 
-        progname = os.path.basename(argv[0])
-
-        try:
-            opts, args = getopt.getopt(argv[1:], "h", ["help"])
-        except getopt.error, msg:
-            raise Usage("global option error: %s", msg)
-
-        for o, a in opts:
-            if o in ("-h", "--help"):
-                print __doc__ % {"program": progname}
-                return 0
-
-        if not args:
-            raise Usage("missing command argument")
-
-        command = args[0]
-        if command not in command_table:
-            hits = []
-            for c in command_table:
-                if c.startswith(command):
-                    hits.append(c)
-            if not hits:
-                raise Usage("unrecognized command", command)
-            if len(hits) > 1:
-                raise Usage("ambiguous command abbreviation %r (%s)",
-                            command, "|".join(hits))
-            command = hits[0]
-
-        short_opts, long_opts, handler = command_table[command]
-
-        try:
-            opts, args = getopt.getopt(args[1:],
-                                       "h"+short_opts,
-                                       ["help"] + long_opts)
-        except getopt.error, msg:
-            raise Usage("%s option error: %s", command, msg)
-
-        if ("-h", "") in opts or ("--help", "") in opts:
-            message = handler.__doc__ or "No help for %s" % handler.__name__
-            print message % {"program": progname}
-            return 0
-
-        return handler(opts, args)
+    try:
+        cmd.realize()
+        cmd.run()
 
     except Usage, msg:
         print >>sys.stderr, msg
@@ -356,22 +309,20 @@
         raise Usage(cmd + " requires at most one of -F/--file or -m/--message")
     return message, L
 
-command_table = {
-    "checkout": ("", [], checkout),
-    "co":       ("", [], checkout),
-    "update":   ("", [], update),
-    "commit":   ("F:m:r", ["file=", "message=", "raise-on-conflicts"], commit),
-    "add":      ("f:t:", ["factory=", "type="], add),
-    "remove":   ("", [], remove),
-    "rm":       ("", [], remove),
-    "r":        ("", [], remove),
-    "diff":     ("bBcC:iNuU:", ["brief", "context=", "unified="], diff),
-    "status":   ("", [], status),
-    "checkin":  ("F:m:", ["file=", "message="], checkin),
-    "ci":       ("F:m:", ["file=", "message="], checkin),
-    "revert":   ("", [], revert),
-    "mkdir":    ("", [], mkdir),
-    }
+command_table = [
+    # name is taken from the function name
+    # function, aliases,  short opts,   long opts
+    (add,      "",        "f:t:",       "factory= type="),
+    (checkin,  "",        "F:m:",       "file= message="),
+    (checkout, "co",      "",           ""),
+    (commit,   "ci",      "F:m:r",      "file= message= raise-on-conflicts"),
+    (diff,     "di",      "bBcC:iNuU:", "brief context= unified="),
+    (mkdir,    "",        "",           ""),
+    (remove,   "del delete rm", "",     ""),
+    (revert,   "",        "",           ""),
+    (status,   "stat st", "",           ""),
+    (update,   "up",      "",           ""),
+    ]
 
 if __name__ == "__main__":
-    sys.exit(main(sys.argv))
+    sys.exit(main())




More information about the Zope3-Checkins mailing list