# simopts.py -- provide central repository/interface for importing/exposing known commandline options # across several utilities # --[no]yaycct # # Michael Thomas # Center for Computation & Technology # Louisiana State University # # import os import sys import optparse from optparse import OptionParser from optparse import OptionGroup import pyini import libutil from libutil import dprint class OptionManager: def __init__(self, optiondir): self.optionDirectory = optiondir self.parsers = dict() self.usedGroups = ["common"] self.usageString = "usage: %prog [options] arg" self.optionParser = None self.options = None self.args = None self.optionParser = None self.OptionDictionaries = dict() self.Macros = dict() self.MDBKeys = dict() self.Substitutions = list() self.Replacements = list() self.Appends = list() self.RawOptionString = " ".join(sys.argv) # find and init our option groups. self.Discovery() def PrintHelp(self): self.optionParser.print_help() def RawOptionDefined(self, option): if self.RawOptionString.count("--%s" % option) > 0: return True return False def IsNegated(self, option): if self.RawOptionString.count("--no%s" % option) > 0: return True return False def BuildOptionString(self, stripArguments=None): if self.options == None: return "" keys = self.options.__dict__.keys() ostr = str() for key in keys: if stripArguments != None and key in stripArguments: continue if key.startswith("__"): continue if key.startswith("["): continue if key in ['define', 'mdbkey', 'append', 'substitution', 'replacement']: continue sdict = self.OptionDictionaries[key] value = getattr(self.options, key) if value == None: continue if value == True: if " ".join(sys.argv).count("%s" % key) > 0: ostr = "%s --%s" % (ostr, key) elif value == False: #dprint("value is false, key is: %s" % key) if sdict['negatable'].value == 'yes': if " ".join(sys.argv).count("%s" % key) > 0: ostr = "%s --no%s" % (ostr, key) else: if " ".join(sys.argv).count("%s" % key) > 0: ostr = "%s --%s=%s" % (ostr, key, value) for key in self.Macros: ostr = "%s --define %s %s" % (ostr, key, self.Macros[key]) for key in self.MDBKeys: ostr = "%s --mdbkey %s %s" % (ostr, key, self.MDBKeys[key]) for item in self.Substitutions: ostr = "%s --substitution %s %s" % (ostr, item[0], item[1]) for item in self.Replacements: ostr = "%s --replacement=%s" % (ostr,item) for item in self.Appends: ostr = "%s --append=%s" % (ostr, item) return ostr.strip() # -- ACCESSOR METHODS -- def HasOption(self, option): o = getattr(self.options, option, None) if o == None: return False return True def GetOption(self, option): return getattr(self.options, option, None) def UpdateOption(self, option, value): setattr(self.options, option, value) # -- BUILD METHODS -- def Discovery(self): try: os.stat(self.optionDirectory) except OSError: dprint("Error while attempting to read option dir: could not open %s for reading" % self.optionDirectory) sys.exit(1) files = os.listdir(self.optionDirectory) for f in files: if f.count(".ini"): parts = os.path.splitext(f) basename = parts[0] full_path = "%s/%s" % (self.optionDirectory, f) self.parsers[basename] = pyini.IniParser(full_path) def SetUsage(self, ss): self.usageString = ss def HasGroup(self, group): return self.parsers.has_key(group) def UseGroup(self, group): if self.HasGroup(group): self.usedGroups.append(group) return dprint("Error when specifying option group %s: group %s does not exist" % (group, group)) sys.exit(1) def BuildBuiltins(self): # macro with callback self.optionParser.add_option("--define", action="callback", type="string", dest='define', nargs=2, help="set additional define", callback=self.callback) self.optionParser.add_option("--mdbkey", action="callback", type="string", dest='mdbkey', nargs=2, help="override for mdb key", callback=self.callback) self.optionParser.add_option("--substitution", action="callback", type="string", dest='substitution', nargs=2, help="perform regex substitution", callback=self.callback) self.optionParser.add_option("--replacement", action="callback", type="string", dest='replacement', nargs=1, help="perform string replacement", callback=self.callback) self.optionParser.add_option("--append", action="callback", type="string", dest='append', nargs=1, help="append onto found variable", callback=self.callback) def callback(self, option, opt, value, parser): if opt == "--define": if value[0].startswith("@"): value[0] = value[0].replace("@", "").strip() self.Macros[value[0]] = value[1] if opt == "--mdbkey": self.MDBKeys[value[0]] = value[1] if opt == "--substitution": self.Substitutions.append(value) if opt == "--replacement": self.Replacements.append(value) if opt == "--append": self.Appends.append(value) def Build(self): self.optionParser = OptionParser(usage=self.usageString) self.BuildBuiltins() for group in self.usedGroups: if group == "common": self.AddOptions(self.optionParser, group) else: og = OptionGroup(self.optionParser, "Options from %s" % group) self.AddOptions(og, group) self.optionParser.add_option_group(og) (self.options, self.args) = self.optionParser.parse_args() def AddOptions(self, op, group): if not(self.HasGroup(group)): dprint("Could not retreive ini parser for option group %s" % group) sys.exit(1) parser = self.parsers[group] options = parser.GetSections() for o in options: sdict = parser.GetSectionAsDict(o) self.OptionDictionaries[o] = sdict self.AddOption(op, o, sdict) def AddOption(self, op, option, sdict): if sdict['negatable'].value == 'yes' and sdict.has_key('short'): dprint("Error parsing option %s: cannot negate a short option" % option) sys.exit(1) if sdict.has_key("short"): optstring = '"%s", "%s"' % (sdict['short'].value, sdict['long'].value) else: optstring = '"%s"' % sdict['long'].value optstring = self.AddOptionToOptionString(optstring, 'dest', option) if sdict['arg'].value == "yes": optstring = self.AddOptionToOptionString(optstring, 'type', sdict['argtype'].value) optstring = self.AddOptionToOptionString(optstring, 'metavar', sdict['argformat'].value) if sdict.has_key('default'): optstring = self.AddOptionToOptionString(optstring, 'default', sdict['default'].value) else: optstring = self.AddOptionToOptionString(optstring, 'action', 'store_true') #dprint("storing_true for argument %s" % option) if sdict.has_key('default'): optstring = '%s,%s=%s' % (optstring, 'default', libutil.CoerseBool(sdict['default'].value)) help = sdict['desc'].value if sdict.has_key('default'): help = "%s %s" % (help, '[default: %default]') if sdict['negatable'].value == 'yes': optstring = '%s,%s=%s' % (optstring, 'help', 'optparse.SUPPRESS_HELP') else: optstring = self.AddOptionToOptionString(optstring, 'help', help) cmd = "op.add_option(%s)" % optstring #dprint(cmd) #dprint('cmd: %s' % cmd) eval(cmd) if sdict['negatable'].value == 'yes': self.AddMetaOption(op, option, sdict) self.AddNegatedOption(op, option, sdict, "no") self.AddNegatedOption(op, option, sdict, "no-") return def AddNegatedOption(self, op, option, sdict, prefix): optstring = '"--%s%s"' % (prefix, option) optstring = self.AddOptionToOptionString(optstring, 'dest', option) optstring = self.AddOptionToOptionString(optstring, 'action', 'store_false') #optstring = self.AddOptionToOptionString(optstring, 'default', False) optstring = '%s,%s=%s' % (optstring, 'help', 'optparse.SUPPRESS_HELP') cmd = "op.add_option(%s)" % optstring #dprint('cmd: %s' % cmd) eval(cmd) def AddMetaOption(self, op, option, sdict): sdict['long'].value = "--[no]%s" % option optstring = '"%s"' % sdict['long'].value if sdict.has_key('default'): optstring = '%s,%s=%s' % (optstring, 'default', libutil.CoerseBool(sdict['default'].value)) help = sdict['desc'].value if sdict.has_key('default'): help = "%s %s" % (help, '[default: %default]') optstring = self.AddOptionToOptionString(optstring, 'dest', option) optstring = self.AddOptionToOptionString(optstring, 'action', 'store_false') optstring = self.AddOptionToOptionString(optstring, 'metavar', option) optstring = self.AddOptionToOptionString(optstring, 'help', help) cmd = "op.add_option(%s)" % optstring #dprint('cmd: %s' % cmd) eval(cmd) def AddOptionToOptionString(self, os, option, value): return '%s,%s="%s"' % (os, option, value)