-
Frank Winklmeier authored
Remove the sequence merge semantics workaround as the problem does not seem to be reproducible anymore.
Frank Winklmeier authoredRemove the sequence merge semantics workaround as the problem does not seem to be reproducible anymore.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
AtlasSemantics.py 7.94 KiB
# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
import GaudiConfig2.semantics
from GaudiKernel.GaudiHandles import PrivateToolHandleArray, PublicToolHandle, ServiceHandle
import re
import copy
from collections import abc
Sequence = abc.Sequence
class AppendListSemantics(GaudiConfig2.semantics.SequenceSemantics):
'''
Extend the sequence-semantics with a merge-method that appends the lists
Use 'appendList<T>' as fifth parameter of the Gaudi::Property<T> constructor
to invoke this merging method. The template parameter is important, also
in the string that forms the fifth argument.
'''
__handled_types__ = (re.compile(r"^appendList<.*>$"),)
def __init__(self, cpp_type, name=None):
super(AppendListSemantics, self).__init__(cpp_type, name)
def merge(self,b,a):
a.extend(b)
return a
class MapMergeNoReplaceSemantics(GaudiConfig2.semantics.MappingSemantics):
'''
Extend the mapping-semantics with a merge-method that merges two mappings as long as they do not have different values for the same key
Use 'mapMergeNoReplace<T>' as fifth parameter of the Gaudi::Property<T> constructor
to invoke this merging method.
'''
__handled_types__ = (re.compile(r"^mapMergeNoReplace<.*>$"),)
def __init__(self, cpp_type, name=None):
super(MapMergeNoReplaceSemantics, self).__init__(cpp_type, name)
def merge(self,a,b):
for k in b.keys():
if k in a and b[k] != a[k]:
raise ValueError('conflicting values in map under key %r and %r %r' % (k, b[k], a[k]))
a[k] = b[k]
return a
class VarHandleSematics(GaudiConfig2.semantics.StringSemantics):
'''
Treat VarHandleKeys like strings
'''
__handled_types__ = ("SG::VarHandleKey",)
def __init__(self,cpp_type,name=None):
super(VarHandleSematics,self).__init__(cpp_type, name)
pass
class VarHandleArraySematics(GaudiConfig2.semantics.PropertySemantics):
'''
Treat VarHandleKeyArrays like arrays of strings
'''
__handled_types__ = ("SG::VarHandleKeyArray",)
def __init__(self,cpp_type,name=None):
super(VarHandleArraySematics,self).__init__(cpp_type, name)
pass
def merge(self,bb,aa):
for b in bb:
if b not in aa:
aa.append(b)
return aa
#union=set(a) | set(b)
#return list(union)
class ToolHandleSemantics(GaudiConfig2.semantics.PropertySemantics):
'''
Private alg-tools need recusive merging (de-duplication):
'''
__handled_types__ = ("PrivateToolHandle",)
def __init__(self,cpp_type,name=None):
super(ToolHandleSemantics, self).__init__(cpp_type,name)
def merge(self,b,a):
#Deal with 'None'
if a is None or a=='': return b
if b is None or b=='': return a
return a.merge(b)
class PublicHandleSemantics(GaudiConfig2.semantics.PropertySemantics):
'''
ServiceHandles (and the deprecated PublicToolHandles) are assigned as strings
'''
__handled_types__ = ("PublicToolHandle","ServiceHandle")
def __init__(self,cpp_type,name=None):
super(PublicHandleSemantics, self).__init__(cpp_type,name)
def default(self,value):
return value.typeAndName
def store(self,value):
if isinstance(value,str): #Assume the string is correct and the tool/svc alreayd in the CA ...
return value
if value is None:
return ""
if not hasattr(value,"__component_type__"):
raise TypeError("Got {}, expected Tool or Service in assignment to {}".format(type(value),self.name))
if value.__component_type__ not in ('Service','AlgTool'):
raise TypeError('{} expected, got {!r} in assignemnt to {}'.\
format(value.__component_type__,value, self.name))
#It would be great if at this point we could verify that the service was
#ineed added to the ComponentAccumulator. Latest, do that when bootstapping
#the application
return "{}/{}".format(value.__cpp_type__,value.name)
class PublicHandleArraySemantics(GaudiConfig2.semantics.PropertySemantics):
'''
Semantics for arrays of string-based pointers to components defined elsewhere
'''
__handled_types__ = ("PublicToolHandleArray","ServiceHandleArray")
def __init__(self,cpp_type,name=None):
super(PublicHandleArraySemantics, self).__init__(cpp_type,name)
def store(self, value):
if not isinstance(value,Sequence) and not isinstance(value,set):
value=[value,]
newValue=[]
for v in value:
if isinstance(v,GaudiConfig2._configurables.Configurable):
if v.__component_type__ not in ('Service','AlgTool'):
raise TypeError('{} expected, got {!r} in assignemnt to {}'.\
format(value.__component_type__,v, self.name))
else:
newValue.append("{}/{}".format(v.__cpp_type__,v.name))
elif isinstance(v,(PublicToolHandle,ServiceHandle)):
newValue.append("{}/{}".format(v.getType(),v.getName()))
elif isinstance(v,str):
#Check if component is known ...
newValue.append(v)
pass
else:
raise TypeError('Configurable expected, got {!r} in assignment to {}'.\
format(v,self.name))
return newValue
def default(self, value):
return copy.copy(value)
def merge(self,bb,aa):
for b in bb:
if b not in aa:
aa.append(b)
return aa
#union=set(a) | set(b)
#return union
class ToolHandleArraySemantics(GaudiConfig2.semantics.PropertySemantics):
'''
Private alg-tools need recusive merging (de-duplication):
'''
__handled_types__ = ("PrivateToolHandleArray",)
def __init__(self,cpp_type,name=None):
super(ToolHandleArraySemantics, self).__init__(cpp_type,name)
def default(self,value):
return copy.copy(value)
def store(self,value):
if not isinstance(value,PrivateToolHandleArray):
#try to convert the value to a PrivateToolHandleArray
value=PrivateToolHandleArray(value)
return value
def merge(self,b,a):
for bTool in b:
try:
#If a tool with that name exists in a, we'll merge it
a.__getitem__(bTool.getName()).merge(bTool)
except IndexError:
#Tool does not exists in a, append it
a.append(bTool)
return a
class SubAlgoSemantics(GaudiConfig2.semantics.PropertySemantics):
__handled_types__ = ("SubAlgorithm",)
def __init__(self,cpp_type,name=None):
super(SubAlgoSemantics, self).__init__(cpp_type,name)
def store(self,value):
if not isinstance(value,Sequence):
value=[value,]
for v in value:
if v.__component_type__ != 'Algorithm':
raise TypeError('Algorithm expected, got {!r} in assignemnt to {}'.\
format(value, self.name))
return value
#Without explicitly definig a default, calling .append or += will change the class-default,
#affecting all instances of the same class.
def default(self,value):
return []
GaudiConfig2.semantics.SEMANTICS.append(AppendListSemantics)
GaudiConfig2.semantics.SEMANTICS.append(VarHandleSematics)
GaudiConfig2.semantics.SEMANTICS.append(VarHandleArraySematics)
GaudiConfig2.semantics.SEMANTICS.append(ToolHandleSemantics)
GaudiConfig2.semantics.SEMANTICS.append(ToolHandleArraySemantics)
GaudiConfig2.semantics.SEMANTICS.append(PublicHandleSemantics)
GaudiConfig2.semantics.SEMANTICS.append(PublicHandleArraySemantics)
GaudiConfig2.semantics.SEMANTICS.append(SubAlgoSemantics)
GaudiConfig2.semantics.SEMANTICS.append(MapMergeNoReplaceSemantics)