python: Separate the options parsing stuff. Remove options parsing stuff from
authorNathan Binkert <nate@binkert.org>
Sun, 15 Jun 2008 04:15:58 +0000 (21:15 -0700)
committerNathan Binkert <nate@binkert.org>
Sun, 15 Jun 2008 04:15:58 +0000 (21:15 -0700)
main.py so things are a bit more obvious.

src/python/SConscript
src/python/m5/main.py
src/python/m5/options.py [new file with mode: 0644]

index 0785b43077e57f15e061f8f258927a67a08e38d1..cca9217b06479ddb99a7d9ca1ba1915ae9b3a555 100644 (file)
@@ -39,6 +39,7 @@ PySource('m5', 'm5/SimObject.py')
 PySource('m5', 'm5/convert.py')
 PySource('m5', 'm5/event.py')
 PySource('m5', 'm5/main.py')
+PySource('m5', 'm5/options.py')
 PySource('m5', 'm5/params.py')
 PySource('m5', 'm5/proxy.py')
 PySource('m5', 'm5/simulate.py')
index 5c33242240ac7f5d579b36e5e6105147edf7ef02..8011c64b8d46987c11bbc2645bfafbb5f0faa44a 100644 (file)
 
 import code
 import datetime
-import optparse
 import os
 import socket
 import sys
 
 from util import attrdict
 import defines
+from options import OptionParser
 import traceflags
 
 __all__ = [ 'options', 'arguments', 'main' ]
 
-usage="%prog [m5 options] script.py [script options]"
-version="%prog 2.0"
-brief_copyright='''
-Copyright (c) 2001-2008
-The Regents of The University of Michigan
-All Rights Reserved
-'''
-
 def print_list(items, indent=4):
     line = ' ' * indent
     for i,item in enumerate(items):
@@ -60,64 +52,19 @@ def print_list(items, indent=4):
             line += item
             print line
 
-# there's only one option parsing done, so make it global and add some
-# helper functions to make it work well.
-parser = optparse.OptionParser(usage=usage, version=version,
-                               description=brief_copyright,
-                               formatter=optparse.TitledHelpFormatter())
-parser.disable_interspersed_args()
-
-# current option group
-group = None
-
-def set_group(*args, **kwargs):
-    '''set the current option group'''
-    global group
-    if not args and not kwargs:
-        group = None
-    else:
-        group = parser.add_option_group(*args, **kwargs)
-
-class splitter(object):
-    def __init__(self, split):
-        self.split = split
-    def __call__(self, option, opt_str, value, parser):
-        getattr(parser.values, option.dest).extend(value.split(self.split))
-
-def add_option(*args, **kwargs):
-    '''add an option to the current option group, or global none set'''
-
-    # if action=split, but allows the option arguments
-    # themselves to be lists separated by the split variable'''
-
-    if kwargs.get('action', None) == 'append' and 'split' in kwargs:
-        split = kwargs.pop('split')
-        kwargs['default'] = []
-        kwargs['type'] = 'string'
-        kwargs['action'] = 'callback'
-        kwargs['callback'] = splitter(split)
-
-    if group:
-        return group.add_option(*args, **kwargs)
-
-    return parser.add_option(*args, **kwargs)
-
-def bool_option(name, default, help):
-    '''add a boolean option called --name and --no-name.
-    Display help depending on which is the default'''
-
-    tname = '--%s' % name
-    fname = '--no-%s' % name
-    dest = name.replace('-', '_')
-    if default:
-        thelp = optparse.SUPPRESS_HELP
-        fhelp = help
-    else:
-        thelp = help
-        fhelp = optparse.SUPPRESS_HELP
+usage="%prog [m5 options] script.py [script options]"
+version="%prog 2.0"
+brief_copyright='''
+Copyright (c) 2001-2008
+The Regents of The University of Michigan
+All Rights Reserved
+'''
 
-    add_option(tname, action="store_true", default=default, help=thelp)
-    add_option(fname, action="store_false", dest=dest, help=fhelp)
+options = OptionParser(usage=usage, version=version,
+                       description=brief_copyright)
+add_option = options.add_option
+set_group = options.set_group
+usage = options.usage
 
 # Help options
 add_option('-A', "--authors", action="store_true", default=False,
@@ -168,39 +115,13 @@ add_option("--trace-file", metavar="FILE", default="cout",
 add_option("--trace-ignore", metavar="EXPR", action='append', split=':',
     help="Ignore EXPR sim objects")
 
-options = attrdict()
-arguments = []
-
-def usage(exitcode=None):
-    parser.print_help()
-    if exitcode is not None:
-        sys.exit(exitcode)
-
-def parse_args():
-    _opts,args = parser.parse_args()
-    opts = attrdict(_opts.__dict__)
-
-    # setting verbose and quiet at the same time doesn't make sense
-    if opts.verbose > 0 and opts.quiet > 0:
-        usage(2)
-
-    # store the verbosity in a single variable.  0 is default,
-    # negative numbers represent quiet and positive values indicate verbose
-    opts.verbose -= opts.quiet
-
-    del opts.quiet
-
-    options.update(opts)
-    arguments.extend(args)
-    return opts,args
-
 def main():
     import defines
     import event
     import info
     import internal
 
-    parse_args()
+    arguments = options.parse_args()
 
     done = False
 
@@ -261,6 +182,11 @@ def main():
     if done:
         sys.exit(0)
 
+    # setting verbose and quiet at the same time doesn't make sense
+    if options.verbose > 0 and options.quiet > 0:
+        options.usage(2)
+
+    verbose = options.verbose - options.quiet
     if options.verbose >= 0:
         print "M5 Simulator System"
         print brief_copyright
@@ -282,7 +208,7 @@ def main():
         if arguments and not os.path.isfile(arguments[0]):
             print "Script %s not found" % arguments[0]
 
-        usage(2)
+        options.usage(2)
 
     # tell C++ about output directory
     internal.core.setOutputDir(options.outdir)
diff --git a/src/python/m5/options.py b/src/python/m5/options.py
new file mode 100644 (file)
index 0000000..50eea42
--- /dev/null
@@ -0,0 +1,145 @@
+# Copyright (c) 2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+import optparse
+import sys
+import util
+
+from optparse import *
+
+class nodefault(object): pass
+
+class splitter(object):
+    def __init__(self, split):
+        self.split = split
+    def __call__(self, option, opt_str, value, parser):
+        values = value.split(self.split)
+        dest = getattr(parser.values, option.dest)
+        if dest is None:
+            setattr(parser.values, option.dest, values)
+        else:
+            dest.extend(values)
+
+class OptionParser(object):
+    def __init__(self, *args, **kwargs):
+        kwargs.setdefault('formatter', optparse.TitledHelpFormatter())
+        self._optparse = optparse.OptionParser(*args, **kwargs)
+        self._optparse.disable_interspersed_args()
+
+        self._allopts = {}
+        self._defaults = {}
+        self._options = util.attrdict()
+
+        # current option group
+        self._group = self._optparse
+
+    def set_group(self, *args, **kwargs):
+        '''set the current option group'''
+        if not args and not kwargs:
+            self._group = self._optparse
+        else:
+            self._group = self._optparse.add_option_group(*args, **kwargs)
+
+    def add_option(self, *args, **kwargs):
+        '''add an option to the current option group, or global none set'''
+
+        # if action=split, but allows the option arguments
+        # themselves to be lists separated by the split variable'''
+
+        if kwargs.get('action', None) == 'append' and 'split' in kwargs:
+            split = kwargs.pop('split')
+            kwargs['default'] = []
+            kwargs['type'] = 'string'
+            kwargs['action'] = 'callback'
+            kwargs['callback'] = splitter(split)
+
+        default = kwargs.pop('default', nodefault)
+        option = self._group.add_option(*args, **kwargs)
+        dest = option.dest
+        if dest not in self._allopts:
+            self._allopts[dest] = option
+
+        if default != nodefault:
+            if dest not in self._options:
+                self._options[dest] = default
+
+        return option
+
+    def bool_option(self, name, default, help):
+        '''add a boolean option called --name and --no-name.
+        Display help depending on which is the default'''
+
+        tname = '--%s' % name
+        fname = '--no-%s' % name
+        dest = name.replace('-', '_')
+        if default:
+            thelp = optparse.SUPPRESS_HELP
+            fhelp = help
+        else:
+            thelp = help
+            fhelp = optparse.SUPPRESS_HELP
+
+        topt = self.add_option(tname, action="store_true", default=default,
+                               help=thelp)
+        fopt = self.add_option(fname, action="store_false", dest=dest,
+                               help=fhelp)
+
+        return topt,fopt
+
+    def __getattr__(self, attr):
+        if attr.startswith('_'):
+            return super(OptionParser, self).__getattr__(attr)
+
+        if attr in self._options:
+            return self._options[attr]
+
+        raise AttributeError, "Option %s not found" % attr
+
+    def __setattr__(self, attr, value):
+        if attr.startswith('_'):
+            return super(OptionParser, self).__setattr__(attr, value)
+
+        if attr in self._options:
+            self._options[attr] = value
+
+        return super(OptionParser, self).__setattr__(attr, value)
+
+    def parse_args(self):
+        opts,args = self._optparse.parse_args()
+
+        for key,val in opts.__dict__.iteritems():
+            if val is not None or key not in self._options:
+                self._options[key] = val
+
+        return args
+
+    def usage(self, exitcode=None):
+        self._optparse.print_help()
+        if exitcode is not None:
+            sys.exit(exitcode)
+