7 import os, weakref, copy
8 from GaudiKernel.GaudiHandles
import GaudiHandle, GaudiHandleArray
9 from GaudiKernel.DataHandle
import DataHandle
12 from AthenaCommon
import ConfigurableDb
16 __author__ =
'Wim Lavrijsen (WLavrijsen@lbl.gov), Martin Woudstra (Martin.Woudstra@cern.ch)'
18 __all__ = [
'PropertyProxy',
19 'GaudiHandlePropertyProxy',
20 'GaudiHandleArrayPropertyProxy' ]
23 from AthenaCommon.Logging
import logging
24 log = logging.getLogger(
'PropertyProxy' )
28 """A string version of isinstance().
29 <derived> is either an object instance, or a type
30 <base> is a string containing the name of the base class (or <derived> class)"""
31 if not isinstance( derived, type ):
32 derived =
type(derived)
34 if derived.__name__ == base:
37 for b
in derived.__bases__:
51 if ( tp == str
or type(value)
is str )
and not isinstance( value, tp ):
53 raise ValueError(
"received an instance of %s, but %s expected, context: %s" % (
type(value),tp, context) )
54 elif ( tp == int )
and type(value)
is float:
56 raise ValueError(
"received an instance of %s, but %s expected, context: %s" % (
type(value),tp, context) )
61 except ValueError
as verr:
62 if isinstance( value, tp ):
67 raise ValueError(
"received non-convertible type %s, but builtin type expected, reason: %s context: %s" % (
type(value),
str(verr), context) )
70 raise ValueError(
"received an instance of %s, but %s expected, reason: %s, context: %s" % (
type(value),tp,
str(verr), context) )
71 except TypeError
as terr:
72 raise TypeError(
"received an instance of %s, but %s expected, reason: %s, context: %s" % (
type(value),tp,
str(terr), context) )
77 def __init__( self, descr, docString=None, default=None ):
78 self.
history = weakref.WeakKeyDictionary()
82 if default
is not None:
91 default = property( getDefault, setDefault )
94 return (obj.getJobOptName()
or obj.getName()) +
'.' + self.
descr.__name__
100 except AttributeError:
116 if builtins.type( value )
is dict:
117 from ctypes
import pythonapi, py_object
118 from _ctypes
import PyObj_FromPtr
119 PyDictProxy_New = pythonapi.PyDictProxy_New
120 PyDictProxy_New.argtypes = (py_object,)
121 PyDictProxy_New.rettype = py_object
122 value = PyObj_FromPtr( PyDictProxy_New( value ) )
123 elif builtins.type( value )
is list:
124 value = tuple( value )
127 value = copy.copy( value )
135 'can not change property "%s" of locked configurable "%s"' %
136 (self.
descr.__name__, obj.getJobOptName()) )
140 if hasattr( self,
'default' ):
146 if proptype
and not isinstance(proptype,
type(
None)):
151 if proptype == tuple
or proptype == list:
155 tpo =
type(oldvec[0])
158 except AttributeError:
164 if not obj._isInSetDefaults()
or obj
not in self.
history:
166 if hasattr( self,
'default' )
and self.
default is None:
167 obj.__iadd__( value, self.
descr )
180 """A class with some utilities for GaudiHandles and GaudiHandleArrays"""
182 def __init__(self, descr, docString, default, handleType, allowedType ):
183 """<descr>: the real property in the object instance (from __slots__)
184 <docString>: the documentation string of this property
185 <default>: default value from C++ (via python generated by genconf)
186 <handleType>: real python handle type (e.g. PublicToolHandle, PrivateToolHandle, ...)
187 <allowedType>: allowed instance type for default
190 if not isinstance(default,allowedType):
191 raise TypeError(
"%s: %s default: %r is not a %s" % \
192 ( descr.__name__, self.__class__.__name__, default, allowedType.__name__ ) )
193 PropertyProxy.__init__( self, descr, docString, default )
202 except AttributeError:
205 default = obj.__class__.getDefaultProperty( self.
descr.__name__ )
207 if obj.isPrinting():
return default
214 default = copy.deepcopy(default)
220 elif isinstance(default,GaudiHandleArray):
224 default = copy.deepcopy(default)
234 except AttributeError
as e:
236 traceback.print_exc()
238 raise RuntimeError(
"AttributeError(%s)" % e.args)
247 'can not change property "%s" of locked configurable "%s"' %
248 (self.
descr.__name__, obj.getJobOptName()) )
252 if not obj._isInSetDefaults()
or obj
not in self.
history:
261 """Check if <value> is a handle of the correct type"""
266 """Check if <value> is a configurable of the correct type"""
271 """Return the configurable instance corresponding to the toolhandle if possible.
272 Otherwise return None"""
275 typeAndNameTuple = typeAndName.split(
'/')
276 confType = typeAndNameTuple[0]
277 confClass = ConfigurableDb.getConfigurable(confType)
280 log.error(
"%s: Configurable %s is not a %s",
284 confName = typeAndNameTuple[1]
288 return confClass(confName)
293 isString =
type(default)
is str
294 if not isString
and self.
isConfig(default):
297 elif isString
or self.
isHandle(default):
300 typeAndName = default
303 typeAndName = default.typeAndName
309 except AttributeError
as e:
311 raise RuntimeError(*e.args)
313 raise RuntimeError(
"%s: Default configurable for class %s not found in ConfigurableDb.CfgDb" % \
317 raise TypeError(
"%s: default value %r is not of type %s or %s" % \
323 if value
is None: value =
''
324 isString =
type(value)
is str
335 if not value.isInToolSvc():
336 suggestion =
'You may need to add jobOptions lines something like:' + os.linesep + \
337 'from AthenaCommon.AppMgr import ToolSvc' + os.linesep + \
339 if value.getName() == value.getType():
340 suggestion +=
'%s()' % value.__class__.__name__
342 suggestion +=
'%s(%r)' % (value.__class__.__name__,value.getName())
344 ': Public tool %s is not yet in ToolSvc. %s' %
345 (value.getJobOptName(),suggestion) )
348 elif value.hasParent( obj.getJobOptName() ):
353 return obj.copyChildAndSetParent( value, obj.getJobOptName() )
355 raise TypeError(
"Property %s value %r is not a %s nor a %s nor a string" % \
363 GaudiHandlePropertyProxyBase.__init__( self, descr, docString, default,
type(default), GaudiHandle )
368 """<descr>: the real property in the object instance (from __slots__)
369 <confTypeName>: string indicating the (base) class of allowed Configurables to be assigned.
370 <handleType>: real python handle type (e.g. PublicToolHandle, PrivateToolHandle, ...)
372 GaudiHandlePropertyProxyBase.__init__( self, descr, docString, default,
type(default).handleType, GaudiHandleArray )
377 if not isinstance( value, list )
and not isinstance( value, self.
arrayType ):
378 raise TypeError(
"%s: Value %r is not a list nor a %s" % \
386 cd = GaudiHandlePropertyProxyBase.convertDefaultToBeSet( self, obj, d )
387 if cd: newDefault.append( cd )
396 cv = GaudiHandlePropertyProxyBase.convertValueToBeSet( self, obj, v )
397 if cv: newValue.append( cv )
404 PropertyProxy.__init__(self, descr, docString, default)
409 except AttributeError:
412 default = obj.__class__.getDefaultProperty(self.
descr.__name__)
416 except AttributeError
as e:
418 raise RuntimeError(*e.args)
423 if not obj._isInSetDefaults()
or obj
not in self.
history:
434 mode = obj.__class__.getDefaultProperty(self.
descr.__name__).
mode()
435 _type = obj.__class__.getDefaultProperty(self.
descr.__name__).
type()
436 if type(value)
is str:
437 return DataHandle(value, mode, _type)
438 elif isinstance(value, DataHandle):
439 return DataHandle(value.__str__(), mode, _type)
441 raise ValueError(
"received an instance of %s, but %s expected" %
442 (
type(value),
'str or DataHandle'))
447 if isinstance(default,GaudiHandleArray):
450 if isinstance(default,GaudiHandle):
453 if isinstance(default,DataHandle):