3 __author__ =
"clat@hep.ph.bham.ac.uk"
6 from PyJobTransformsCore.trferr
import TransformConfigError
10 """Base class for all fixed types, implemented as descriptors. Each instance of a specific fixed type
11 (a derived class) can be set either to None (to indicate no value has been set), or to a type specified
12 by the derived class. The type is checked by the derived class by implementing the member function
15 def __init__(self,doc,default,allowedValues=None):
19 if allowedValues
is not None:
21 allowedValues.__iter__
22 except AttributeError:
23 allowedValues = [ allowedValues ]
24 varName =
"%s.allowedValues" % self.
__name
27 if default
is not None:
29 varName =
"%s default" % self.
__name
41 varName =
"%s.%s" % (instance.name(), self.
__name)
49 instance._attributeDictionary()[self.
_attributeName(instance)] = value
53 return '_%s__%s' % (instance.__class__.__name__,self.
__name)
65 """The documentation string"""
70 """The help string: type, documentation and possible values"""
71 hlp =
'(%s) %s' % (self.__class__.__name__, self.
__doc)
73 hlp +=
'. Possible values: %s' % self.
__allowed
83 """Private helper functin to check the type of <value>. May convert to another type.
84 This implementation does nothing, it just returns value.
85 This function can be overridden in derived class to do type checking.
86 It should return the value (possible with new type), or raise a TransformConfigError
87 exception in case of problems. """
92 """Private helper function to check the value of <value>. This function is
93 called after calling _checkType. <value> can therefore be considered to be
95 This implementation checks that the value is one of the allowed values (if defined).
96 This function can be overridden in derived class to do type & additional value checking.
97 It has to return the value (adapted if needed) if all is OK. It has to raise
98 a TransformConfigError exception in case of problems.
99 <variableName> is the name of the variable that is being set and is typically
100 only used for error messages."""
102 raise TransformConfigError(
'%s value %r is not in %s' %
109 """Private helper function which is called when the value of the object is set.
110 It is called after _checkType() and _checkValue(), so the value can be
111 assumed to be correct.
112 This function can be overridden in a derived class, typically to trigger additional action
113 when the value is set.
114 In case of error, raise a TransformConfigError exception, otherwise just return.
115 This implementation does nothing.
116 <variableName> is the name of the variable that is being set and is typically
117 only used for error messages."""
123 for v
in allowedValues:
124 self._checkType(variableName,v)
130 def __init__(self,doc,default='',allowedValues=None):
131 Descriptor.__init__(self,doc,default,allowedValues)
135 valType =
type(value).__name__
137 raise TransformConfigError(
'%s should be a string. Got %s instead.' % (variableName, valType) )
140 return Descriptor._checkValue(self,variableName,value)
146 Descriptor.__init__(self,doc,default,[
True,
False])
152 Descriptor.__init__(self,doc,default,allowedValues)
159 raise TransformConfigError(
'%s value %s is not a float' % (variableName, value) )
162 return Descriptor._checkValue(self,variableName,value)
168 Descriptor.__init__(self,doc,default,allowedValues)
176 raise TransformConfigError(
'%s value %s is not an int' % (variableName, value) )
178 if value !=
float(inValue):
179 raise TransformConfigError(
'%s value %s is not an int' % (variableName, value) )
182 return Descriptor._checkValue(self,variableName,value)
187 """List with a unique set of entries (duplicates are removed).
188 List of allowed values are the entries that are allowed in the list."""
189 def __init__(self,doc,default=None,allowedValues=None):
190 if default
is None: default = []
191 Descriptor.__init__(self,doc,default,allowedValues)
195 """Check that <value> is of type list of tuple, and convert to a list if it is a tuple."""
209 raise TransformConfigError(
'%s should be a list or tuple. Got %s instead.' %
210 ( variableName,
type( value ).__name__ ) )
219 raise TransformConfigError(
'%s value %r is not one of %s' %
220 (variableName, value, allowed) )
225 return list( newValue )
231 for v
in allowedValues:
232 newAllowed.add( self.
_checkType(variableName,[v])[0] )
233 return list( newAllowed )
238 """List with a unique set of strings (duplicates are removed)"""
239 def __init__(self,doc,default=None,allowedValues=None):
240 UniqueList.__init__(self,doc,default,allowedValues)
244 """Add check that all entries are strings"""
246 value = UniqueList._checkType(self,variableName,value)
249 if not isinstance( v, str ):
250 raise TransformConfigError(
"Entry %r in %s is not a string (but an %s)" %
251 ( v, variableName,
type( v ).__name__ ) )
258 """Any python (string) boolean expression where 'value' stands for the value.
259 For example, for a number range check: \"0 < value < 100\" """
289 if '__slots__' not in dict:
290 raise TransformConfigError(
'Class %s does not have member __slots__. Please add __slots__ = ()'
291 ' to the class definition' % (name,) )
296 slots = self.__slots__
297 descrName =
'__properties'
298 if descrName
not in slots:
300 slots += ( descrName, )
302 dict[
'__slots__'] = slots
304 setattr(self,descrName,[])
305 descrList = getattr(self,descrName)
307 for n,attrib
in dict.items():
308 if isinstance(attrib,Descriptor):
309 setattr(attrib,
'_Descriptor__name',n)
310 descrList.append(attrib)
312 type.__init__(self,name,bases,dict)
317 __slots__ = (
'__name',
'__attributes' )
320 """name is used in printout. The default name is derived from the filename of the python file
321 where constructor is called"""
324 filename = os.path.basename(sys._getframe(1).f_code.co_filename)
325 name = os.path.splitext(filename)[0]
335 value = getattr(self,name)
336 me.append(
"%s.%s = %r \t# %s" % (prefix,name,value,descr.help()) )
337 prefix =
' '*len(prefix)
338 return os.linesep.join(me)
342 """Return the total number of properties (this class plus all base classes)"""
347 """Provide iteration over the full list of properties (the Descriptors, not the values)"""
352 """Dictionary to store the values. Used in the class Descriptor."""
357 """Return the full list of properties (the descriptors, not the values)"""
360 for cl
in self.__class__.__bases__ + (self.__class__,):
361 descr += getattr(cl,
'__properties')
366 """Get the property (the descriptor, not the value) named <name>.
367 It raises an TransformConfigError if the class does not have proporty <name>."""
368 for d
in self.properties():
369 if d.name() == name:
return d
371 raise TransformConfigError(
'class %s does not have property %s' % (self.__class__.__name__, name))
375 """Return bool indicating if this class has property <name>"""
377 self.getProperty(name)
379 except TransformConfigError:
384 """Dictionary with the attibutes (name:value). It is a copy to make it read-only."""
385 return self.__attributes.
copy()
389 """The name of the configuration instance (mainly for printout)"""
395 """Configuration class for JobTransforms.
396 It has a number of properties shared among all jobtransforms. Those properties are
397 processed by class JobTransform."""
398 __slots__ = (
'__metadata', )
401 auxfiles =
ListOfStrings(
"List of needed auxiliary files (to be found in DATAPATH)")
403 maxeventsfactor =
Float(
"maximum number of output events = minevents * maxeventsfactor",2.0,
405 maxeventsstrategy =
String(
"what to do if number of input events is less than maxEvents",
'INPUTEVENTS',
406 [
'IGNORE',
'INPUTEVENTS',
'ABORT'])
411 """name is used in printout. The default name is derived from the filename of the python file
412 where constructor is called"""
413 JobConfig.__init__(self,name)
415 if metaData
is not None:
416 propertyNames = [ d.name()
for d
in self.
properties() ]
418 if m
not in propertyNames:
419 raise TransformConfigError(
'Requested metadata %s is not an attribute of %s' % (m,self.name()) )
424 me = JobConfig.__str__(self,prefix)
428 prefix +=
' '*len(self.name())
429 me += os.linesep + prefix +
'MetaData attributes: '
438 """A dictionary of metadata to be added to the metadata of the output files.
439 Values set to None will not be added to the list. Values will be converted to strings.
440 Python lists will be transformed to a string with comma separated entries."""
443 value = getattr(self,name)
444 if value
is not None:
446 if type(value).__name__ ==
'list': value =
','.
join([
str(v)
for v
in value])
447 meta[name] =
str(value)