diff --git a/Control/AthenaConfiguration/python/ComponentAccumulator.py b/Control/AthenaConfiguration/python/ComponentAccumulator.py index 10117474e268505f7a07c59478ba2853aa295d37..a3da15d73e5430f6bb3c99b11206c242667f797d 100644 --- a/Control/AthenaConfiguration/python/ComponentAccumulator.py +++ b/Control/AthenaConfiguration/python/ComponentAccumulator.py @@ -7,6 +7,7 @@ from AthenaCommon.AlgSequence import AthSequencer from AthenaConfiguration.AthConfigFlags import AthConfigFlags import GaudiKernel.GaudiHandles as GaudiHandles +from GaudiKernel.GaudiHandles import PublicToolHandle, PublicToolHandleArray, ServiceHandle, PrivateToolHandle import ast import collections @@ -198,8 +199,10 @@ class ComponentAccumulator(object): def _deduplicate(self,newComp,compList): #Check for duplicates: for comp in compList: - if comp.getType()==newComp.getType() and comp.getJobOptName()==newComp.getJobOptName(): + if comp.getType()==newComp.getType() and comp.getFullName()==newComp.getFullName(): #Found component of the same type and name + if isinstance(comp,PublicToolHandle) or isinstance(comp,ServiceHandle): + continue # For public tools/services we check only their full name because they are already de-duplicated in addPublicTool/addSerivce self._deduplicateComponent(newComp,comp) #We found a service of the same type and name and could reconcile the two instances self._msg.debug("Reconciled configuration of component %s", comp.getJobOptName()) @@ -221,7 +224,7 @@ class ComponentAccumulator(object): def _deduplicateComponent(self,newComp,comp): - #print "Checking ", comp.getType(), comp.getJobOptName() + #print "Checking ", comp, comp.getType(), comp.getJobOptName() allProps=frozenset(comp.getValuedProperties().keys()+newComp.getValuedProperties().keys()) for prop in allProps: if not prop.startswith('_'): @@ -234,14 +237,29 @@ class ComponentAccumulator(object): except AttributeError: newprop=None + if type(oldprop) != type(newprop): + raise DeduplicationFailed(" '%s' defined multiple times with conflicting types %s and %s" % \ + (comp.getJobOptName(),type(oldprop),type(newprop))) + #Note that getattr for a list property works, even if it's not in ValuedProperties if (oldprop!=newprop): #found property mismatch - if isinstance(oldprop,GaudiHandles.GaudiHandle): + if isinstance(oldprop,PublicToolHandle) or isinstance(oldprop,ServiceHandle): + if oldprop.getFullName()==newprop.getFullName(): + # For public tools/services we check only their full name because they are already de-duplicated in addPublicTool/addSerivce + continue + else: + raise DeduplicationFailed("PublicToolHandle / ServiceHandle '%s.%s' defined multiple times with conflicting values %s and %s" % \ + (comp.getJobOptName(),oldprop.getFullName(),newprop.getFullName())) + elif isinstance(oldprop,PublicToolHandleArray): + for newtool in newprop: + if newtool not in oldprop: + oldprop+=[newtool,] + continue + elif isinstance(oldprop,ConfigurableAlgTool): self._deduplicateComponent(oldprop,newprop) pass elif isinstance(oldprop,GaudiHandles.GaudiHandleArray): - print oldprop,newprop for newTool in newprop: self._deduplicate(newTool,oldprop) pass @@ -261,6 +279,9 @@ class ComponentAccumulator(object): mergeprop=oldprop mergeprop.update(prop) setattr(comp,prop,mergeprop) + elif isinstance(oldprop,PrivateToolHandle): + # This is because we get a PTH if the Property is set to None, and for some reason the equality doesn't work as expected here. + continue else: #self._msg.error("component '%s' defined multiple times with mismatching configuration", svcs[i].getJobOptName()) raise DeduplicationFailed("component '%s' defined multiple times with mismatching property %s" % \