options.py revision 13709:dd6b7ac5801f
15647Sgblack@eecs.umich.edu# Copyright (c) 2005 The Regents of The University of Michigan
25647Sgblack@eecs.umich.edu# All rights reserved.
35647Sgblack@eecs.umich.edu#
45647Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
57087Snate@binkert.org# modification, are permitted provided that the following conditions are
67087Snate@binkert.org# met: redistributions of source code must retain the above copyright
77087Snate@binkert.org# notice, this list of conditions and the following disclaimer;
87087Snate@binkert.org# redistributions in binary form must reproduce the above copyright
97087Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
107087Snate@binkert.org# documentation and/or other materials provided with the distribution;
117087Snate@binkert.org# neither the name of the copyright holders nor the names of its
127087Snate@binkert.org# contributors may be used to endorse or promote products derived from
135647Sgblack@eecs.umich.edu# this software without specific prior written permission.
147087Snate@binkert.org#
157087Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167087Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
177087Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
187087Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
197087Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
207087Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
217087Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225647Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
237087Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245647Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
255647Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265647Sgblack@eecs.umich.edu#
275647Sgblack@eecs.umich.edu# Authors: Nathan Binkert
285647Sgblack@eecs.umich.edu
295647Sgblack@eecs.umich.eduimport optparse
305647Sgblack@eecs.umich.eduimport sys
315647Sgblack@eecs.umich.edu
325647Sgblack@eecs.umich.edufrom optparse import *
335647Sgblack@eecs.umich.edu
345647Sgblack@eecs.umich.educlass nodefault(object): pass
355647Sgblack@eecs.umich.edu
365647Sgblack@eecs.umich.educlass splitter(object):
375647Sgblack@eecs.umich.edu    def __init__(self, split):
385647Sgblack@eecs.umich.edu        self.split = split
395647Sgblack@eecs.umich.edu    def __call__(self, option, opt_str, value, parser):
408229Snate@binkert.org        values = value.split(self.split)
415647Sgblack@eecs.umich.edu        dest = getattr(parser.values, option.dest)
425654Sgblack@eecs.umich.edu        if dest is None:
435647Sgblack@eecs.umich.edu            setattr(parser.values, option.dest, values)
446137Sgblack@eecs.umich.edu        else:
456137Sgblack@eecs.umich.edu            dest.extend(values)
466137Sgblack@eecs.umich.edu
475654Sgblack@eecs.umich.educlass OptionParser(dict):
486046Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
495647Sgblack@eecs.umich.edu        kwargs.setdefault('formatter', optparse.TitledHelpFormatter())
505648Sgblack@eecs.umich.edu        self._optparse = optparse.OptionParser(*args, **kwargs)
515648Sgblack@eecs.umich.edu        self._optparse.disable_interspersed_args()
525647Sgblack@eecs.umich.edu
535647Sgblack@eecs.umich.edu        self._allopts = {}
545647Sgblack@eecs.umich.edu
555647Sgblack@eecs.umich.edu        # current option group
565647Sgblack@eecs.umich.edu        self._group = self._optparse
575647Sgblack@eecs.umich.edu
585647Sgblack@eecs.umich.edu    def set_defaults(self, *args, **kwargs):
595647Sgblack@eecs.umich.edu        return self._optparse.set_defaults(*args, **kwargs)
605647Sgblack@eecs.umich.edu
615648Sgblack@eecs.umich.edu    def set_group(self, *args, **kwargs):
625647Sgblack@eecs.umich.edu        '''set the current option group'''
635648Sgblack@eecs.umich.edu        if not args and not kwargs:
645648Sgblack@eecs.umich.edu            self._group = self._optparse
655648Sgblack@eecs.umich.edu        else:
665648Sgblack@eecs.umich.edu            self._group = self._optparse.add_option_group(*args, **kwargs)
675648Sgblack@eecs.umich.edu
685648Sgblack@eecs.umich.edu    def add_option(self, *args, **kwargs):
695648Sgblack@eecs.umich.edu        '''add an option to the current option group, or global none set'''
705648Sgblack@eecs.umich.edu
715648Sgblack@eecs.umich.edu        # if action=split, but allows the option arguments
725648Sgblack@eecs.umich.edu        # themselves to be lists separated by the split variable'''
735648Sgblack@eecs.umich.edu
745648Sgblack@eecs.umich.edu        if kwargs.get('action', None) == 'append' and 'split' in kwargs:
755648Sgblack@eecs.umich.edu            split = kwargs.pop('split')
765648Sgblack@eecs.umich.edu            kwargs['default'] = []
775648Sgblack@eecs.umich.edu            kwargs['type'] = 'string'
785648Sgblack@eecs.umich.edu            kwargs['action'] = 'callback'
795648Sgblack@eecs.umich.edu            kwargs['callback'] = splitter(split)
805648Sgblack@eecs.umich.edu
815648Sgblack@eecs.umich.edu        option = self._group.add_option(*args, **kwargs)
825648Sgblack@eecs.umich.edu        dest = option.dest
835648Sgblack@eecs.umich.edu        if dest not in self._allopts:
845648Sgblack@eecs.umich.edu            self._allopts[dest] = option
855648Sgblack@eecs.umich.edu
865648Sgblack@eecs.umich.edu        return option
875648Sgblack@eecs.umich.edu
885648Sgblack@eecs.umich.edu    def bool_option(self, name, default, help):
895648Sgblack@eecs.umich.edu        '''add a boolean option called --name and --no-name.
905648Sgblack@eecs.umich.edu        Display help depending on which is the default'''
915648Sgblack@eecs.umich.edu
925648Sgblack@eecs.umich.edu        tname = '--%s' % name
935648Sgblack@eecs.umich.edu        fname = '--no-%s' % name
945648Sgblack@eecs.umich.edu        dest = name.replace('-', '_')
955648Sgblack@eecs.umich.edu        if default:
965648Sgblack@eecs.umich.edu            thelp = optparse.SUPPRESS_HELP
975648Sgblack@eecs.umich.edu            fhelp = help
985648Sgblack@eecs.umich.edu        else:
995648Sgblack@eecs.umich.edu            thelp = help
1005648Sgblack@eecs.umich.edu            fhelp = optparse.SUPPRESS_HELP
1015648Sgblack@eecs.umich.edu
1025648Sgblack@eecs.umich.edu        topt = self.add_option(tname, action="store_true", default=default,
1035648Sgblack@eecs.umich.edu                               help=thelp)
1045648Sgblack@eecs.umich.edu        fopt = self.add_option(fname, action="store_false", dest=dest,
1055648Sgblack@eecs.umich.edu                               help=fhelp)
1065648Sgblack@eecs.umich.edu
1075648Sgblack@eecs.umich.edu        return topt,fopt
1085648Sgblack@eecs.umich.edu
1095648Sgblack@eecs.umich.edu    def __getattr__(self, attr):
1105648Sgblack@eecs.umich.edu        if attr.startswith('_'):
1115648Sgblack@eecs.umich.edu            return super(OptionParser, self).__getattribute__(attr)
1125648Sgblack@eecs.umich.edu
1135648Sgblack@eecs.umich.edu        if attr in self:
1145648Sgblack@eecs.umich.edu            return self[attr]
1155648Sgblack@eecs.umich.edu
1165648Sgblack@eecs.umich.edu        return super(OptionParser, self).__getattribute__(attr)
1175648Sgblack@eecs.umich.edu
1185648Sgblack@eecs.umich.edu    def __setattr__(self, attr, value):
1195648Sgblack@eecs.umich.edu        if attr.startswith('_'):
1205648Sgblack@eecs.umich.edu            super(OptionParser, self).__setattr__(attr, value)
1215648Sgblack@eecs.umich.edu        elif attr in self._allopts:
1225648Sgblack@eecs.umich.edu            defaults = { attr : value }
1235648Sgblack@eecs.umich.edu            self.set_defaults(**defaults)
1245648Sgblack@eecs.umich.edu            if attr in self:
1255648Sgblack@eecs.umich.edu                self[attr] = value
1265648Sgblack@eecs.umich.edu        else:
1275648Sgblack@eecs.umich.edu            super(OptionParser, self).__setattr__(attr, value)
1285648Sgblack@eecs.umich.edu
1295648Sgblack@eecs.umich.edu    def parse_args(self):
1305648Sgblack@eecs.umich.edu        opts,args = self._optparse.parse_args()
1315648Sgblack@eecs.umich.edu
1325648Sgblack@eecs.umich.edu        for key,val in opts.__dict__.items():
1335648Sgblack@eecs.umich.edu            if val is not None or key not in self:
1345648Sgblack@eecs.umich.edu                self[key] = val
1355648Sgblack@eecs.umich.edu
1365648Sgblack@eecs.umich.edu        return args
1375648Sgblack@eecs.umich.edu
1385648Sgblack@eecs.umich.edu    def usage(self, exitcode=None):
1395648Sgblack@eecs.umich.edu        self._optparse.print_help()
1405648Sgblack@eecs.umich.edu        if exitcode is not None:
1415648Sgblack@eecs.umich.edu            sys.exit(exitcode)
1425648Sgblack@eecs.umich.edu
1435648Sgblack@eecs.umich.edu