options.py revision 13709
15470Snate@binkert.org# Copyright (c) 2005 The Regents of The University of Michigan
25470Snate@binkert.org# All rights reserved.
35470Snate@binkert.org#
45470Snate@binkert.org# Redistribution and use in source and binary forms, with or without
55470Snate@binkert.org# modification, are permitted provided that the following conditions are
65470Snate@binkert.org# met: redistributions of source code must retain the above copyright
75470Snate@binkert.org# notice, this list of conditions and the following disclaimer;
85470Snate@binkert.org# redistributions in binary form must reproduce the above copyright
95470Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
105470Snate@binkert.org# documentation and/or other materials provided with the distribution;
115470Snate@binkert.org# neither the name of the copyright holders nor the names of its
125470Snate@binkert.org# contributors may be used to endorse or promote products derived from
135470Snate@binkert.org# this software without specific prior written permission.
145470Snate@binkert.org#
155470Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
165470Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
175470Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
185470Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
195470Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205470Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
215470Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225470Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
235470Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245470Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
255470Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265470Snate@binkert.org#
275470Snate@binkert.org# Authors: Nathan Binkert
285470Snate@binkert.org
295470Snate@binkert.orgimport optparse
305470Snate@binkert.orgimport sys
315470Snate@binkert.org
325470Snate@binkert.orgfrom optparse import *
335470Snate@binkert.org
345470Snate@binkert.orgclass nodefault(object): pass
355470Snate@binkert.org
365470Snate@binkert.orgclass splitter(object):
375470Snate@binkert.org    def __init__(self, split):
385470Snate@binkert.org        self.split = split
395470Snate@binkert.org    def __call__(self, option, opt_str, value, parser):
405470Snate@binkert.org        values = value.split(self.split)
415470Snate@binkert.org        dest = getattr(parser.values, option.dest)
425470Snate@binkert.org        if dest is None:
435470Snate@binkert.org            setattr(parser.values, option.dest, values)
445470Snate@binkert.org        else:
455470Snate@binkert.org            dest.extend(values)
465470Snate@binkert.org
475586Snate@binkert.orgclass OptionParser(dict):
485470Snate@binkert.org    def __init__(self, *args, **kwargs):
495470Snate@binkert.org        kwargs.setdefault('formatter', optparse.TitledHelpFormatter())
505470Snate@binkert.org        self._optparse = optparse.OptionParser(*args, **kwargs)
515470Snate@binkert.org        self._optparse.disable_interspersed_args()
525470Snate@binkert.org
535470Snate@binkert.org        self._allopts = {}
545470Snate@binkert.org
555470Snate@binkert.org        # current option group
565470Snate@binkert.org        self._group = self._optparse
575470Snate@binkert.org
585586Snate@binkert.org    def set_defaults(self, *args, **kwargs):
595586Snate@binkert.org        return self._optparse.set_defaults(*args, **kwargs)
605586Snate@binkert.org
615470Snate@binkert.org    def set_group(self, *args, **kwargs):
625470Snate@binkert.org        '''set the current option group'''
635470Snate@binkert.org        if not args and not kwargs:
645470Snate@binkert.org            self._group = self._optparse
655470Snate@binkert.org        else:
665470Snate@binkert.org            self._group = self._optparse.add_option_group(*args, **kwargs)
675470Snate@binkert.org
685470Snate@binkert.org    def add_option(self, *args, **kwargs):
695470Snate@binkert.org        '''add an option to the current option group, or global none set'''
705470Snate@binkert.org
715470Snate@binkert.org        # if action=split, but allows the option arguments
725470Snate@binkert.org        # themselves to be lists separated by the split variable'''
735470Snate@binkert.org
745470Snate@binkert.org        if kwargs.get('action', None) == 'append' and 'split' in kwargs:
755470Snate@binkert.org            split = kwargs.pop('split')
765470Snate@binkert.org            kwargs['default'] = []
775470Snate@binkert.org            kwargs['type'] = 'string'
785470Snate@binkert.org            kwargs['action'] = 'callback'
795470Snate@binkert.org            kwargs['callback'] = splitter(split)
805470Snate@binkert.org
815470Snate@binkert.org        option = self._group.add_option(*args, **kwargs)
825470Snate@binkert.org        dest = option.dest
835470Snate@binkert.org        if dest not in self._allopts:
845470Snate@binkert.org            self._allopts[dest] = option
855470Snate@binkert.org
865470Snate@binkert.org        return option
875470Snate@binkert.org
885470Snate@binkert.org    def bool_option(self, name, default, help):
895470Snate@binkert.org        '''add a boolean option called --name and --no-name.
905470Snate@binkert.org        Display help depending on which is the default'''
915470Snate@binkert.org
925470Snate@binkert.org        tname = '--%s' % name
935470Snate@binkert.org        fname = '--no-%s' % name
945470Snate@binkert.org        dest = name.replace('-', '_')
955470Snate@binkert.org        if default:
965470Snate@binkert.org            thelp = optparse.SUPPRESS_HELP
975470Snate@binkert.org            fhelp = help
985470Snate@binkert.org        else:
995470Snate@binkert.org            thelp = help
1005470Snate@binkert.org            fhelp = optparse.SUPPRESS_HELP
1015470Snate@binkert.org
1025470Snate@binkert.org        topt = self.add_option(tname, action="store_true", default=default,
1035470Snate@binkert.org                               help=thelp)
1045470Snate@binkert.org        fopt = self.add_option(fname, action="store_false", dest=dest,
1055470Snate@binkert.org                               help=fhelp)
1065470Snate@binkert.org
1075470Snate@binkert.org        return topt,fopt
1085470Snate@binkert.org
1095470Snate@binkert.org    def __getattr__(self, attr):
1105470Snate@binkert.org        if attr.startswith('_'):
1115586Snate@binkert.org            return super(OptionParser, self).__getattribute__(attr)
1125470Snate@binkert.org
1135586Snate@binkert.org        if attr in self:
1145586Snate@binkert.org            return self[attr]
1155470Snate@binkert.org
1165586Snate@binkert.org        return super(OptionParser, self).__getattribute__(attr)
1175470Snate@binkert.org
1185470Snate@binkert.org    def __setattr__(self, attr, value):
1195470Snate@binkert.org        if attr.startswith('_'):
1205586Snate@binkert.org            super(OptionParser, self).__setattr__(attr, value)
1215586Snate@binkert.org        elif attr in self._allopts:
1225586Snate@binkert.org            defaults = { attr : value }
1235586Snate@binkert.org            self.set_defaults(**defaults)
1245586Snate@binkert.org            if attr in self:
1255586Snate@binkert.org                self[attr] = value
1265586Snate@binkert.org        else:
1275586Snate@binkert.org            super(OptionParser, self).__setattr__(attr, value)
1285470Snate@binkert.org
1295470Snate@binkert.org    def parse_args(self):
1305470Snate@binkert.org        opts,args = self._optparse.parse_args()
1315470Snate@binkert.org
13213709Sandreas.sandberg@arm.com        for key,val in opts.__dict__.items():
1335586Snate@binkert.org            if val is not None or key not in self:
1345586Snate@binkert.org                self[key] = val
1355470Snate@binkert.org
1365470Snate@binkert.org        return args
1375470Snate@binkert.org
1385470Snate@binkert.org    def usage(self, exitcode=None):
1395470Snate@binkert.org        self._optparse.print_help()
1405470Snate@binkert.org        if exitcode is not None:
1415470Snate@binkert.org            sys.exit(exitcode)
1425470Snate@binkert.org
143