-
Andre Sailer authored3999a5b6
ConfigHelper.py 4.01 KiB
"""Helper object to identify configuration parameters so we can easily overwrite
them via command line magic or via the steering file
To add additional arguments create either a member variable or a property to a
subclass of the ConfigHelper. To add additional arguments to the add_argument
call for the parser object create an additional member::
self.member = [1,2]
self._member_EXTRA = {'help': 'description for parameter',
'nargs': '+',
}
"""
class ConfigHelper(object):
"""Base class for configuration helper"""
def __init__(self):
pass
def getOptions(self):
finalVars = {}
# get all direct members not starting with underscore
allVars = vars(self)
for var, val in allVars.items():
if not var.startswith('_'):
extraArgumentsName = "_%s_EXTRA" % var
options = getattr(self, extraArgumentsName) if hasattr(self, extraArgumentsName) else None
finalVars[var] = {'default': val}
if options:
finalVars[var].update(options)
# now get things defined with @property
props = [(p, getattr(type(self), p)) for p in dir(type(self)) if isinstance(getattr(type(self), p), property)]
for propName, prop in props:
optName = "_%s_EXTRA" % propName
doc = prop.__doc__
options = getattr(self, optName) if hasattr(self, optName) else None
finalVars[propName] = {'default': getattr(self, propName)}
if doc:
finalVars[propName]['help'] = doc
if options:
finalVars[propName].update(options)
return finalVars
def __repr__(self):
return self.printOptions()
def printOptions(self):
"""print all parameters"""
options = []
for opt, val in self.getOptions().items():
options.append("\n\t'%s': '%s'" % (opt, val['default']))
return "".join(options)
def setOption(self, name, val):
""" set the attribute name to val """
setattr(self, name, val)
@staticmethod
def makeList(stringVal, sep=" "):
"""returns a list from a string separated by sep"""
if not stringVal:
return []
if isinstance(stringVal, list):
return stringVal
else:
return stringVal.split(sep)
@staticmethod
def makeSet(stringVal, sep=" "):
"""returns a set from a string separated by sep"""
if not stringVal:
return set()
if isinstance(stringVal, (list, set, tuple)):
return set(stringVal)
else:
return set(stringVal.split(sep))
@staticmethod
def makeString(container):
"""Return a string that can be parsed by dd4hep into a vector."""
if not container:
return ""
if isinstance(container, set):
return '{%s}' % ','.join([str(s) for s in container])
@staticmethod
def makeTuple(val):
""" returns a tuple of the string, separators are space or comma """
myTuple = None
if isinstance(val, tuple):
myTuple = val
if isinstance(val, list):
myTuple = tuple(val)
if isinstance(val, str):
sep = ',' if ',' in val else ' '
myTuple = tuple([_.strip("(), ") for _ in val.split(sep)])
if myTuple is None:
raise RuntimeError("Cannot parse input value %s" % val)
return myTuple
@staticmethod
def makeBool(val):
"""check if val is a bool or a string of true/false, otherwise raise exception"""
if isinstance(val, bool):
return val
elif isinstance(val, str):
if val.lower() == 'true':
return True
elif val.lower() == 'false':
return False
raise RuntimeError(val)
@staticmethod
def addAllHelper(ddsim, parser):
"""all configHelper objects to commandline args"""
for name, obj in vars(ddsim).items():
if isinstance(obj, ConfigHelper):
for var, optionsDict in obj.getOptions().items():
optionsDict['action'] = 'store_true' if var.startswith("enable") else optionsDict.get('action', 'store')
parser.add_argument("--%s.%s" % (name, var),
dest="%s.%s" % (name, var),
**optionsDict
)