File indexing completed on 2025-01-18 09:14:22
0001 """Helper object to identify configuration parameters so we can easily overwrite
0002 them via command line magic or via the steering file
0003
0004 To add additional arguments create either a member variable or a property to a
0005 subclass of the ConfigHelper. To add additional arguments to the add_argument
0006 call for the parser object create an additional member::
0007
0008 self.member = [1,2]
0009 self._member_EXTRA = {'help': 'description for parameter',
0010 'nargs': '+',
0011 }
0012
0013 """
0014
0015
0016 class ConfigHelper(object):
0017 """Base class for configuration helper"""
0018
0019
0020 _setOfProperties = dict()
0021
0022 def __init__(self):
0023 pass
0024
0025 def _name(self):
0026 return self.__class__.__name__
0027
0028 def _closeProperties(self):
0029 """Store the list of properties."""
0030 self._setOfProperties[self._name()] = set(vars(self))
0031
0032 def _checkProperties(self):
0033 newProps = set(vars(self))
0034 if existingProps := self._setOfProperties.get(self._name(), set()):
0035 if unknownProps := newProps - existingProps:
0036 raise RuntimeError(f"{self._name()} error: Trying to add unknown propert(y/ies): {unknownProps}!")
0037
0038 def getOptions(self):
0039 finalVars = {}
0040
0041
0042 allVars = vars(self)
0043 for var, val in allVars.items():
0044 if not var.startswith('_'):
0045 extraArgumentsName = "_%s_EXTRA" % var
0046 options = getattr(self, extraArgumentsName) if hasattr(self, extraArgumentsName) else None
0047 finalVars[var] = {'default': val}
0048 if options:
0049 finalVars[var].update(options)
0050
0051
0052 props = [(p, getattr(type(self), p)) for p in dir(type(self)) if isinstance(getattr(type(self), p), property)]
0053 for propName, prop in props:
0054 optName = "_%s_EXTRA" % propName
0055 doc = prop.__doc__
0056 options = getattr(self, optName) if hasattr(self, optName) else None
0057 finalVars[propName] = {'default': getattr(self, propName)}
0058 if doc:
0059 finalVars[propName]['help'] = doc
0060 if options:
0061 finalVars[propName].update(options)
0062
0063 return finalVars
0064
0065 def __repr__(self):
0066 return self.printOptions()
0067
0068 def printOptions(self):
0069 """print all parameters"""
0070 options = []
0071 for opt, val in self.getOptions().items():
0072 options.append("\n\t'%s': '%s'" % (opt, val['default']))
0073 return "".join(options)
0074
0075 def setOption(self, name, val):
0076 """ set the attribute name to val """
0077 setattr(self, name, val)
0078
0079 @staticmethod
0080 def makeList(stringVal, sep=" "):
0081 """returns a list from a string separated by sep"""
0082 if not stringVal:
0083 return []
0084 if isinstance(stringVal, list):
0085 return stringVal
0086 else:
0087 return stringVal.split(sep)
0088
0089 @staticmethod
0090 def makeSet(stringVal, sep=" "):
0091 """returns a set from a string separated by sep"""
0092 if not stringVal:
0093 return set()
0094 if isinstance(stringVal, (list, set, tuple)):
0095 return set(stringVal)
0096 else:
0097 return set(stringVal.split(sep))
0098
0099 @staticmethod
0100 def makeString(container):
0101 """Return a string that can be parsed by dd4hep into a vector."""
0102 if not container:
0103 return ""
0104 if isinstance(container, set):
0105 return '{%s}' % ','.join([str(s) for s in container])
0106
0107 @staticmethod
0108 def makeTuple(val):
0109 """ returns a tuple of the string, separators are space or comma """
0110 myTuple = None
0111 if isinstance(val, tuple):
0112 myTuple = val
0113 if isinstance(val, list):
0114 myTuple = tuple(val)
0115 if isinstance(val, str):
0116 sep = ',' if ',' in val else ' '
0117 myTuple = tuple([_.strip("(), ") for _ in val.split(sep)])
0118 if myTuple is None:
0119 raise RuntimeError("Cannot parse input value %s" % val)
0120 return myTuple
0121
0122 @staticmethod
0123 def makeBool(val):
0124 """check if val is a bool or a string of true/false, otherwise raise exception"""
0125 if isinstance(val, bool):
0126 return val
0127 elif isinstance(val, str):
0128 if val.lower() == 'true':
0129 return True
0130 elif val.lower() == 'false':
0131 return False
0132 raise RuntimeError(val)
0133
0134 @staticmethod
0135 def addAllHelper(ddsim, parser):
0136 """all configHelper objects to commandline args"""
0137 for name, obj in vars(ddsim).items():
0138 if isinstance(obj, ConfigHelper):
0139 for var, optionsDict in obj.getOptions().items():
0140 optionsDict['action'] = ('store_true' if var.startswith(("enable", "force"))
0141 else optionsDict.get('action', 'store'))
0142 parser.add_argument("--%s.%s" % (name, var),
0143 dest="%s.%s" % (name, var),
0144 **optionsDict
0145 )