Commits

Anonymous committed 62988e2 Merge

sync w/ atlasoff

  • Participants
  • Parent commits fbeca89, 85d9501
  • Branches waffle-repo, mob

Comments (0)

Files changed (6)

 9e344aee696367e56a95299367b5172ce423ff25 AthenaCommon-02-18-08
 41f00cb3c55aa6d37f9b26b34f19a0eca2ff8f0e AthenaCommon-02-18-09
 8b31ef1a9832fc94c7c027bc6b22f87d45004377 AthenaCommon-02-18-10
+2cbffe4193f74306f755217c44e2dbf806a1753f AthenaCommon-02-18-11
+8025802501b0a176f4ca7e1dcdc532cac2dba83d AthenaCommon-02-18-12
+b27b6fc6b1095623ae19026fe8346f3c16463545 AthenaCommon-02-18-13
+d93d4ef54c14c714aba744ce04b8eed618c788fa AthenaCommon-02-18-14
+2012-03-29  Sebastien Binet  <binet@cern.ch>
+
+	* tagging AthenaCommon-02-18-14
+	* add the ability to pass an environment to ChapPy.AthenaApp
+	* M python/ChapPy.py
+
+2012-02-16 Martin Woudstra <martin.woudstra@cern.ch>
+	* tagging AthenaCommon-02-18-13
+	* python/ConfiguredFactory.py: fix crash in printout if not running at VERBOSE output level
+	
+2012-02-15 Martin Woudstra <martin.woudstra@cern.ch>
+	* tagging AthenaCommon-02-18-12
+	* WARNING: do not use this tag (fails if not run with VERBOSE output level). Use next tag.
+	* Fix for bug #91232
+	* python/Configurable.py: add property _isPrinting for special treatment in GaudiHandlePropertyProxyBase
+	* python/PropertyProxy.py: changes in class GaudiHandlePropertyProxyBase:
+	  - do not auto-retrieve any Handles or HandleArrays when in printing mode.
+	    This changes the configurable ascii printout: it is no longer showing the full config of default instances of private AlgTools,
+	    unless they have already been retrieved by explicit request.
+	  - if object is locked, do not auto-set on __get__, but return locked copy instead
+	  - only auto-set (from inside __get__) in case of default Configurable instance, or default HandleArray
+	* python/ConfiguredFactory.py:
+	  - improved function hasPropertyBeenSet(): now also robust for auto-retrieved Private AlgTools
+	  - do not resolve already assigned Configurables
+	  - improve debug printout
+
 2011-11-16  Wim Lavrijsen <WLavrijsen@lbl.gov>
         * For Rolf, #87230 deal with TCMALLOCDIR not being defined while
 	  wanting to use the stdcmalloc and preloadlib options
             ] )
         return s
         
-    def run( self, monitor = sys.stdout ):
+    def run( self, monitor = sys.stdout, env = None ):
 
+        if env is None:
+            import os
+            env = dict(os.environ)
+            pass
+        
         sc, out = commands.getstatusoutput( "which athena.py" )
         if sc != 0:
             raise RuntimeError, "Could not fetch athena.py executable: %s" % out
 
         p = subprocess.Popen( args = ["/bin/sh"] + cmd,
                               stdout = self.logFile,
-                              stderr = self.logFile )
+                              stderr = self.logFile,
+                              env = env )
         monitor.write(" :::running [")
         monitor.flush()
         while p.poll() == None:
             return
         raise TypeError('unexpected type %s'%type(o))
     
-    def run(self, stdout=None):
+    def run(self, stdout=None, env=None):
         import os
         import subprocess as sub
+        if env is None:
+            env=dict(os.environ)
         athena_exe = sub.Popen(['which', 'athena.py'],
-                               stdout=sub.PIPE).communicate()[0].strip()
+                               stdout=sub.PIPE,
+                               env=env).communicate()[0].strip()
         
         athena_exe = os.path.expanduser(os.path.expandvars(athena_exe))
         athena_exe = os.path.realpath(athena_exe)
         cmd = [athena_exe] + self._cmdlineargs + [self._jobo.name]
         return sub.call(cmd,
                         stdout=stdout,
-                        stderr=sub.STDOUT)
+                        stderr=sub.STDOUT,
+                        env=env)
     

python/Configurable.py

       '_name',                # the (unqualified) component name
       '_inSetDefaults',       # currently setting default values
       '_isLocked',            # track configurable to be locking
+      '_isPrinting',          # inside __str__ to avoid setting of private AlgTools
       '_initok',              # used to enforce base class init
       '_setupok'              # for debugging purposes (temporary)
    )
     # set to True when locked, False otherwise
       self._isLocked = False
 
+    # set to True when inside __str__ (volatile - not stored on file)
+      self._isPrinting = False
+
     # for later, in case __init__ itself is overridden
       self._initok = True
 
       self._initok = True
       self._inSetDefaults = False
       self._isLocked = False
+      self._isPrinting = False
       for (n, v) in dct.items():
          setattr( self, n, v )
 
          else:
             return title
 
+    # avoid auto-setting private AlgTools while doing printout
+      self._isPrinting = True
+
     # print line to easily see start-of-configurable
       if indent > 0:
          headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
 
     # print line to easily see end-of-configurable. Note: No linesep!
       rep += Configurable._printFooter( indentStr, title )
+
+      self._isPrinting = False
       return rep
 
 

python/ConfiguredFactory.py

         # set value
         return getattr(configurable,property)
     except AttributeError:
-        # C++ default
         retVal = configurable.getDefaultProperty(property)
         if retVal is None: raise
         return retVal
 
+def getPropertyNoAutoRetrieve(configurable,property):
+    """Helper function to get a property of a configurable: the set value, user set default or C++ default."""
+    if hasPropertyBeenSet(configurable,property):
+        return getattr(configurable,property)
+    else:
+        retVal = configurable.getDefaultProperty(property)
+        if retVal is None: raise AttributeError("%r does not have attribute %s" % (configurable.__class__, property) )
+        return retVal
+
 
 def getPropertyType(configurable,property):
     try:
     except KeyError:
         raise AttributeError("Configurable %r does not have property %s" % (configurable.__class__.__name__,property) ) 
 
-    ## works one-way even for GaudiHandles
-    if configurable not in proxy.history:
-        return False
-
-    ## Due to the auto-retrieval of Handles (possibly triggered by Configurable.__str__ : this needs fixing!)
-    ## GaudiHandles may appear in history, even if not set
-    defValue = proxy.default
-    if not isinstance(defValue,GaudiHandle):
-        return True
-    
-    # Nasty hacked fall-back solution for GaudiHandles
-    # CAVEAT: if user sets it equal to the default, it will be considered not set
-    oldISD = configurable._inSetDefaults
-    configurable._inSetDefaults = True # avoid adding this getattr() call to the history due to auto-retrieve
-    value = getattr(configurable,property) # will auto-retrieve GaudiHandles if not yet set
-    configurable._inSetDefaults = oldISD
-
-    return defValue.getFullName() != value.getFullName()
+    return configurable in proxy.history
 
 
 #
                 except AttributeError:
                     pass
 
-        if typ is None:
-            return "%s%r  maker=%s" % (indent,name, self.getMakerType())
-        else:
-            return "%s%r  type=%s  maker=%s" % (indent,name, typ, self.getMakerType())
-    
+        mess = "%s%r  maker=%s" % (indent, name, self.getMakerType())
+        if typ is not None: mess += "  type=%s" % (typ,)
+
+        return mess
+
 
     def createInstance(self,name,argsOverride=None):
         theMaker = self._getConfigurableMaker()
 
-        parent=self
-        # turn Tool/Service names into real Tool/Service configurables
         args = dict(self.configurableArgs)
         if argsOverride: args.update(argsOverride)
         # make an instance of the class
         # One done for C++ defaults, and only if requireAllDependencies=False (otherwise exception is thrown)
         self._ignoredDependencyErrors = []
         # list of properties where the default has not been explicitly set
-        self._excludedDefaultProperties = []
+        self._excludedDefaultProperties = {}
         # list of default instances that we not created because they had only the type
         self._excludedOnlyTypes = []
 
 
     def _isExcludedDefaultProperty(self,propName):
         if propName in self._propertiesToExcludeDefaults:
-            addToListIfNotIn( self._excludedDefaultProperties, propName )
+            n = self._excludedDefaultProperties.setdefault(propName,0)
+            n += 1
+            self._excludedDefaultProperties[propName] = n
             return True
 
         return False
         isPropertyArray = issubclass(propertyType,GaudiHandleArray)
         isValueArray = type(propertyValue) in (list,tuple) or isinstance(propertyValue,GaudiHandleArray)
 
-        resolvingString = ""
+        resolvingString = indent+"%s "
         # for debug printout
         if self.logger().isEnabledFor(logging.VERBOSE):
-            resolvingString = indent+"Resolving "
             if ( isPropDefault ):
                 resolvingString += "default "
             else:
 
         try:
             if isValueArray:
-                self.logger().verbose(resolvingString)
+                self.logger().verbose(resolvingString, "Resolving")
                 newPropertyValue = [] # propertyType()
                 for v in propertyValue:
                     conf = self._resolveConfigurable(parent,propertyName,v,getterFunc,checkType,indent,propStack)
-                    if conf: newPropertyValue.append( conf )
+                    if conf:
+                        newPropertyValue.append( conf )
+                    else: # keep existing one
+                        newPropertyValue.append( v )
 
             else: # not an array
-                if isPropDefault and self._isExcludedDefaultValue(propertyValue): return propertyValue
-                if not isPropertyArray: self.logger().verbose(resolvingString)
+                if isPropDefault and self._isExcludedDefaultValue(propertyValue):
+                    self.logger().verbose(resolvingString, "Keeping existing")
+                    return propertyValue
+                if not isPropertyArray: self.logger().verbose(resolvingString, "Resolving")
 
                 if isinstance(propertyValue,Configurable):
-                    doCheck=True
-                    tryDefault=False
+                    # do not change already assigned configurables
+                    self.logger().verbose(resolvingString, "Keeping existing")
+                    return propertyValue
                 elif isinstance(propertyValue,GaudiHandle) or type(propertyValue) == str:
                     doCheck=checkType
                     # tryDefaultConfigurable None instead of False to always retrieve it for the sake of dependencies
                     raise TypeError("%r is not a Configurable, Handle, HandleArray, string or list" % propertyValue)
 
                 nextIndent=indent+" "
-                newPropertyValue = getterFunc(propertyValue, tryDefaultConfigurable=tryDefault, checkType=doCheck,
+                newPropertyValue = getterFunc(propertyValue, tryDefaultConfigurable=tryDefault, checkType=doCheck, allowNone=True,
                                               indent=nextIndent,propStack=propStack)
 
                 # for printout at the end
 
     ## @arg @c parent : the parent (@c ConfiguredPlaceHolder) of the property
     def _resolveProperty(self,parent,propertyName,propertyValue,checkType=False,indent="",propStack=None):
-        """For Tool/ServiceHandles: turn name of tool/service into configurable instances.a
-        For any other, just return value."""
+        """For Tool/ServiceHandles: turn name of tool/service into configurable instances.
+        For any other, return None so it does not get re-assigned"""
         if propertyValue is None: return None # valid also for Handles. Nothing special to do.
         cls = parent.__class__
         try:
             confGetter = self.getPrivateTool
         elif isinstance(cxxdefault,(ServiceHandle,ServiceHandleArray)):
             confGetter = self.getService
-        else: # any other type of property
+        else: # any other type of property left untouched
             return propertyValue
 
         return self._resolveConfigurable(parent,propertyName,propertyValue,confGetter,checkType,indent,propStack)
         confName = conf.getName()
         defaultProps = conf.getDefaultProperties()
         for name,value in defaultProps.items():
-            # use set value if available
-            try:
-                value = getattr(conf,name)
-            except AttributeError:
-                # value not set, so we stick with the default value
-                pass
-
             # skip non-configurables, since they don't need to be resolved
             propertyType = getPropertyType(conf,name)
             if not issubclass(propertyType,(GaudiHandle,GaudiHandleArray,Configurable)):
                 if not self._configSetDependencies: continue
             else:
                 if not self._configDefaultDependencies: continue
+                if self._isExcludedDefaultProperty( name ): continue
 
-            # skip some defaults
-            if not isPropSet and self._isExcludedDefaultProperty( name ):
+            # to avoid auto-retrieve of private AlgTools, only call getattr() if already set elsewhere
+            if isPropSet:
+                value = getattr(conf,name)
+            else:
+                value = defaultProps[name]
+
+            resolvedValue = self._resolveProperty(conf,name,value,checkType=isPropSet,indent=indent,propStack=propStack)
+            if resolvedValue is None or resolvedValue == value:
+                self.logger().verbose("%sProperty %s.%s=%r left unchanged", indent, conf.getFullName(),name, value)
                 continue
 
-
-            resolvedValue = self._resolveProperty(conf,name,value,checkType=isPropSet,indent=indent,propStack=propStack)
-            if resolvedValue is None: continue
             try:
                 setattr(conf,name,resolvedValue)
             except Exception,err:
-                raise ConfigurationError("ERROR in setting %s(%r).%s = %r\n  Error message: %s" %
+                raise ConfigurationError("ERROR in setting %s(%r).%s = %r\n  Exception raised: %s" %
                                          (conf.getType(),conf.getName(),name,value,err) )
 
         
         newValue = None
         for n,v in propsToCheck.items():
             try:
-                oldProp = getProperty(configInstance,n)
+                oldProp = getPropertyNoAutoRetrieve(configInstance,n)
             except AttributeError:
                 continue
             
         # first look in available instances
         confType,confName = getTypeAndName(instanceName)
         if not confName: return None
-        self.logger().verbose("%sGoing to instantiate %s(%r)",indent,confType,confName)
+        self.logger().verbose("%sTrying to instantiate %s(%r)",indent,confType,confName)
         nextIndent=indent+" "
         if propStack is None: propStack = PropertyStack()
         conf = None
         maker = self._availableConfigurables.get(confName)
         if maker is not None:
             conf = maker.getInstance()
-            if conf is None:
+            if conf is not None:
+                self.logger().debug("%sUsing already configured %s(%r)",indent,conf.getType(),conf.getName())            
+            else: # create it
                 conf = maker.createInstance(confName)
+                self.logger().verbose("%sInstantiated %s(%r). Starting to resolve dependencies",indent,conf.getType(),conf.getName())
+                self._resolveAllProperties(conf,nextIndent,propStack)
+                if checkType and confType != confName:
+                    # explicit type given, check that existing type is as requested
+                    self.checkConfigurableType(conf,confType)
 
-            self._resolveAllProperties(conf,nextIndent,propStack)
-            if checkType and confType != confName:
-                # explicit type given, check that existing type is as requested
-                self.checkConfigurableType(conf,confType)
-
-            self.logger().debug("%sInstantiated configured %s(%r)",indent,conf.getType(),conf.getName())
+                self.logger().debug("%sInstantiated configured %s(%r)",indent,conf.getType(),conf.getName())
 
         else:
             # look in default configurables (if requested)
             if tryDefaultConfigurable or tryDefaultConfigurable is None:
                 # do not make defaults if only the type is given
-                if self._excludeIfOnlyType(instanceName): return None
+                if self._excludeIfOnlyType(instanceName):
+                    self.logger().verbose("%sNot instantiated because %r is only a type",indent,instanceName)
+                    return None
                 # skip explicitly excludes ones
                 if self._skipIfNotAvailable(instanceName):
+                    self.logger().verbose("%sNot instantiated because %r is not in database",indent,instanceName)
                     return None
 
                 configurableClass = ConfigurableDb.getConfigurable(confType)
                     if tryDefaultConfigurable:
                         raise ConfigurableClassNotFoundError("Could not find configurable class for %s" % instanceName)
                     elif tryDefaultConfigurable is None:
+                        self.logger().verbose("%sNot instantiated because configurable class %r does not exist",indent,confType)
                         return None
 
                 else:
                     
 
         if conf is None:
+            self.logger().verbose("%sCould not find configurable instance %r", indent, instanceName)
             raise ConfigurableInstanceNotFoundError("Could not find configurable instance %r" % (instanceName) )
 
-
         return conf
 
 
         if not self._hasReadDB: self.read()
         # check if original is available (to catch mistakes like swapping cloneName and originalName)
         if type(originalOrName) == str and originalOrName not in self._availableConfigurables:
-            raise ConfigurationError("Can not make clone %r of non-existing configurable %r" % (cloneName,originalOrName))
-
+            raise ConfigurationError("Can not make clone %r of non-existing configurable %r" % (cloneName,originalOrName) )
 
         conf = None
         # first see if cloneName is already present in list of available configurables
             if conf is None:
                 conf = maker.createInstance(cloneName)
                 self._resolveAllProperties(conf)
+                self.logger().info("Instantiated configurable %s(%r), requested as clone of %r", conf.__class__.__name__, conf.name(), originalOrName)
+            else:
+                self.logger().debug("Using existing configurable %s(%r), requested as clone of %r", conf.__class__.__name__, conf.name(), originalOrName)
                 
             problem = self.checkProperties(conf,kwargs)
             if problem:
                 raise ConfigurationError("Existing clone requested with incompatible properties: "+problem)
 
-            return conf
 
-        # if we get here, clone needs to me made
-        if type(originalOrName) == str:
-            originalName = originalOrName # for printout later
-            self._addConfiguredClone(originalName,cloneName,**kwargs)
-            conf = self.getConfigured(cloneName,tryDefaultConfigurable=False,checkType=True)
+        if conf is None:
+            # if we get here, clone needs to me made
+            if type(originalOrName) == str:
+                originalName = originalOrName # for printout later
+                self._addConfiguredClone(originalName,cloneName,**kwargs)
+                conf = self.getConfigured(cloneName,tryDefaultConfigurable=False,checkType=True)
+                self.logger().info("Instantiated configurable %s(%r) as clone of %r", conf.__class__.__name__, conf.name(), originalName)
 
-        elif isinstance(originalOrName,Configurable):
-            originalName = originalOrName.name() # for printout later
-            conf = originalOrName.clone(cloneName)
-            for n,v in kwargs.items():
-                setattr(conf,n,v)
-            self._resolveAllProperties(conf)
-            
+            elif isinstance(originalOrName,Configurable):
+                originalName = originalOrName.name() # for printout later
+                conf = originalOrName.clone(cloneName)
+                for n,v in kwargs.items():
+                    setattr(conf,n,v)
+                self._resolveAllProperties(conf)
+                # add to list for later retrieval
+                self._availableConfigurables[cloneName] = ConfiguredPlaceHolder(conf)
+                self.logger().info("Instantiated direct resolved clone %s(%r) from original %r", conf.__class__.__name__, conf.name(), originalName)
+
 
         if conf is None:
             # complete failure
             raise RuntimeError("Could not find configurable %r as source for clone %r" % (originalOrName,cloneName) )
 
-        self.logger().info("Instantiating configurable %s(%r) as clone of %r", conf.__class__.__name__, conf.name(), originalName)
-        # also store clones for later usage
         return conf
         
 
         return tool
 
 
-    def getPublicTool(self, name, tryDefaultConfigurable=None, checkType=False, indent="", propStack=None):
+    def getPublicTool(self, name, tryDefaultConfigurable=None, checkType=False, allowNone=False, indent="", propStack=None):
         """Get public tool"""
-        if not name: return None
+        if not name:
+            if allowNone: return None
+            else: raise ConfigurationError("Requested Public Tool with empty name")
+
         global ToolSvc
         confType,confName = getTypeAndName(name)
         if not confName: return None
         except AttributeError:
             # make it and add to ToolSvc
             theTool = self._getTool(name, tryDefaultConfigurable, checkType, indent, propStack)
-            if theTool is None: return None
+            if theTool is None:
+                if allowNone: return None
+                else: raise ConfigurationError("Public Tool %r not found" % (name,) )
+                    
             # some configurable makers already add the tool to ToolSvc
             if not hasattr(ToolSvc,theTool.getName()):
                 ToolSvc += theTool
             return theTool
 
 
-    def getPrivateTool(self, name, tryDefaultConfigurable = None, checkType = True, indent = "", propStack=None, **toolProps):
+    def getPrivateTool(self, name, tryDefaultConfigurable = None, checkType = True, allowNone=False, indent = "", propStack=None, **toolProps):
         """Get private tool. Returns a (deep) copy of the tool, so really private"""
-        if not name: return None
+        if not name:
+            if allowNone: return None
+            else: raise ConfigurationError("Requested Private Tool with empty name")
+            
         tool = self._getTool(name, tryDefaultConfigurable, checkType, indent, propStack)
-        if tool is None: return None
+        if tool is None:
+            if allowNone: return None
+            else: raise ConfigurationError("Private Tool %r not found" % (name,) )
+
         # start with a copy
         tool = copy.deepcopy( tool )
         # overwrite with user properties
         """Add a clone of a possible service to the list of possible services."""
         self._addConfiguredClone(originalName, cloneName, **kwargs)
 
-    def getService( self, name, tryDefaultConfigurable=None, checkType=True, indent="", propStack=None ):
-        if not name: return None
+    def getService( self, name, tryDefaultConfigurable=None, checkType=True, allowNone=False, indent="", propStack=None ):
+        if not name:
+            if allowNone: return None
+            else: raise ConfigurationError("Requested Service with empty name")
+
         confType,confName = getTypeAndName(name)
-        if not confName: return None
+        if not confName:
+            if allowNone: return None
+            else: raise ConfigurationError("Requested Service with empty instance name: %r" % (name,) )
+
+
         global ServiceMgr
         # first try to get it from ServiceMgr
         try:
                 tryDefault = tryDefaultConfigurable
             # make it and add to ServiceMgr
             theSvc = self.getConfigured( name, tryDefault, checkType, indent, propStack )
-            if theSvc is None: return None
+            if theSvc is None:
+                if allowNone: return None
+                else: raise ConfigurationError("Service %r not found" % (name,) )
+
             self.checkService(theSvc)
             ServiceMgr += theSvc
             return theSvc
         self._addConfiguredClone(originalName, cloneName, **kwargs)
 
 
-    def getAlgorithm( self, name, tryDefaultConfigurable=None, checkType=True, indent="", propStack=None ):
-        if not name: return None
+    def getAlgorithm( self, name, tryDefaultConfigurable=None, checkType=True, allowNone=False, indent="", propStack=None ):
+        if not name:
+            if allowNone: return None
+            else: raise ConfigurationError("Requested Algorithm with empty name")
+
         if tryDefaultConfigurable is None:
             tryDefault = self._tryDefaultAlgorithm or None
         else:
             tryDefault = tryDefaultConfigurable
 
         theAlg = self.getConfigured( name, tryDefault, checkType, indent, propStack )
-        if theAlg is None: return None
+        if theAlg is None:
+            if allowNone: return None
+            else: raise ConfigurationError("Algorithm %r not found" % (name,) )
+
         self.checkAlgorithm(theAlg)        
         return theAlg
 
         if self._excludedDefaultProperties:
             lines = [ "%i properties with the following names and default values were not explicitly configured:" % \
                       len(self._excludedDefaultProperties) ]
-            for c in self._excludedDefaultProperties:
-                lines.append("  %s" % c)
+            for c,count in self._excludedDefaultProperties.items():
+                lines.append("  %s (%d times)" % (c,count) )
             log.info( os.linesep.join(lines) )
 
         if self._excludedOnlyTypes:
                 try:
                     mod = __import__( confDbModule, globals(), locals(), [dbFile] )
                 except Exception, err:
-                    self.logger().warning( "Could not import module %s !", confDbModule )
+                    self.logger().warning( "Error importing module %s !", confDbModule )
                     self.logger().warning( "Reason: %s", err )
                 else:
                     nFiles += 1
 
         stopTime = time.time()
-        self.logger().debug( "importing configDb modules... DONE" )
-        self.logger().debug( "imported %i confDb modules in %.2f seconds" % (nFiles,stopTime-startTime) )
+        self.logger().info( "imported %i confDb modules in %.2f seconds" % (nFiles,stopTime-startTime) )
         self._hasReadDB = True
         
 

python/PropertyProxy.py

 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
 # Author: Martin Woudstra (Martin.Woudstra@cern.ch)
 
-import os, sys, weakref
+import os, sys, weakref, copy
 try:
    from GaudiKernel.GaudiHandles import *
 except ImportError:
          # Get default
          try:
             default = obj.__class__.getDefaultProperty( self.descr.__name__ )
+            # if printing, just show the toolhandle. No need to auto-retrieve default configurable instance
+            if obj._isPrinting: return default
             default = self.convertDefaultToBeSet( obj, default )
-            islocked = obj._isLocked
-            obj._isLocked = False       # by-pass potential warnings
-            self.__set__( obj, default )
-            obj._isLocked = islocked
+            # special case if default is auto-retrieved configurable instance
+            if self.isConfig(default):
+               if obj._isLocked:
+                  # return a locked copy to produce error in case of setting any property
+                  # rather then changing the value of the default
+                  default = copy.deepcopy(default)
+                  default.lock()
+                  return default
+               else:
+                  # Set to default configurable instance to allow MyTool.MySubTool.MyProperty = MyValue
+                  self.__set__( obj, default )
+            elif isinstance(default,GaudiHandleArray):
+               if obj._isLocked:
+                  # return a locked copy to produce error in case of setting any property
+                  # rather then changing the value of the default
+                  default = copy.deepcopy(default)
+                  for c in default:
+                     if self.isConfig(c):
+                        c.lock()
+                  return default
+               else:
+                  # Set array to allow to add to default with syntax: MyTool.MyArray.append()
+                  self.__set__( obj, default )
+            else:
+               return default
          except AttributeError,e:
+            import traceback
+            traceback.print_exc()
             # change type of exception to avoid false error message
-            raise RuntimeError(*e.args)
+            raise RuntimeError("AttributeError(%s)" % e.args)
 
       return self.descr.__get__( obj, type )