ATLAS Offline Software
Control/AthenaPython/python/Configurables.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 # @file: Configurables.py
4 # @purpose: a set of Configurables for the PyAthena components
5 # @author: Sebastien Binet <binet@cern.ch>, Frank Winklmeier
6 # @author: Frank Winklmeier (rewrite for GaudiConfig2)
7 
8 import GaudiConfig2
9 from AthenaConfiguration.ComponentAccumulator import isComponentAccumulatorCfg
10 from AthenaCommon.Configurable import (Configurable as LegacyConfigurable,
11  ConfigurableAlgorithm,
12  ConfigurableService,
13  ConfigurableAlgTool,
14  ConfigurableAuditor)
15 
16 
17 
19  """@c PyComponents is a placeholder where all factories for the python
20  components will be collected and stored for easy look-up and call from
21  the C++ side.
22  The @a PyComponents.instances dictionary will store the instance
23  e.g.:
24  PyComponents.instances[ 'alg1' ] = <PyAthena::Alg/alg1 instance>
25  All this boilerplate code will of course be done automatically for the user
26  as soon as she uses the (python) @PyConfigurable classes.
27  """
28  instances = {}
29  pass
30 
31 
32 def _get_prop_value(pycomp, propname):
33  v = pycomp.properties()[propname]
34  if v == pycomp.propertyNoValue:
35  from AthenaCommon.AppMgr import ServiceMgr as svcMgr
36  if propname == 'OutputLevel' and hasattr (svcMgr, 'MessageSvc'):
37  # special case of OutputLevel...
38  v = getattr(svcMgr.MessageSvc, propname)
39  else:
40  v = pycomp.getDefaultProperty(propname)
41  pass
42  return v
43 
44 
45 
47  def __init__(self, name, **kw):
48  self.__dict__['__cpp_type__'] = self.getType()
49  for n,v in kw.items():
50  setattr(self, n, v)
51 
52  def getDlls(self):
53  return 'AthenaPython'
54 
55  @property
56  def msg(self):
57  import AthenaCommon.Logging as _L
58  return _L.logging.getLogger( self.getName() )
59 
60  def getHandle(self):
61  return None
62 
63  def __getstate__(self):
64  state = super().__getstate__()
65  state.update(self.__dict__)
66  return state
67 
68  def __setstate__(self, state):
69  self.__dict__.update(state)
70  super().__setstate__(state)
71 
72  def setup(self):
73  if isinstance(self, LegacyConfigurable):
74  from AthenaCommon.AppMgr import ServiceMgr as svcMgr
75  if not hasattr( svcMgr, 'PyComponentMgr' ):
76  from AthenaPython.AthenaPythonCompsConf import PyAthena__PyComponentMgr
77  svcMgr += PyAthena__PyComponentMgr('PyComponentMgr')
78 
79 
81  self.OutputLevel = _get_prop_value (self, 'OutputLevel')
82 
83 
84  o = PyComponents.instances.get(self.getName(), None)
85  if not (o is None) and not (o is self):
86  err = "A python component [%r] has already been "\
87  "registered with the PyComponents registry !" % o
88  raise RuntimeError(err)
89  PyComponents.instances[self.getName()] = self
90 
91  def merge(self, other):
92  """Basic merge for Python components.
93  Checks that all attributes/properties are identical.
94  """
95  if self is other:
96  return self
97 
98  if type(self) is not type(other):
99  raise TypeError(f"cannot merge instance of {type(other).__name__} into "
100  f"an instance of { type(self).__name__}")
101 
102  if self.name != other.name:
103  raise ValueError(f"cannot merge configurables with different names ({self.name} and {other.name})")
104 
105  for prop in other.__dict__:
106  if (hasattr(self, prop) and getattr(self, prop) == getattr(other, prop)):
107  continue
108  else:
109  raise ValueError(f"conflicting settings for property {prop} of {self.name}: "
110  f"{getattr(self,prop)} vs {getattr(other,prop)}")
111  return self
112 
113 
114 
121  _alg_base = _svc_base = _tool_base = _aud_base = GaudiConfig2.Configurable
122 else:
123  _alg_base = ConfigurableAlgorithm
124  _svc_base = ConfigurableService
125  _tool_base = ConfigurableAlgTool
126  _aud_base = ConfigurableAuditor
127 
128 
129 
131  def __init__( self, name, **kw ):
132  if isinstance(self, LegacyConfigurable):
133  _alg_base.__init__(self, name)
134  else:
135  _alg_base.__init__(self, name, **kw)
136  CfgPyComponent.__init__(self, name, **kw)
137 
138  def getGaudiType( self ): return 'Algorithm'
139  def getType(self): return 'PyAthena::Alg'
140 
141  def setup(self):
142 
143  from AthenaPython import PyAthena
144  setattr(PyAthena.algs, self.getName(), self)
145 
146 
147  CfgPyComponent.setup(self)
148  if isinstance(self, LegacyConfigurable):
149  ConfigurableAlgorithm.setup(self)
150 
151 
152 
154  def __init__( self, name, **kw ):
155  if isinstance(self, LegacyConfigurable):
156  _svc_base.__init__(self, name)
157  else:
158  _svc_base.__init__(self, name, **kw)
159  CfgPyComponent.__init__(self, name, **kw)
160 
161  def getGaudiType( self ): return 'Service'
162  def getType(self): return 'PyAthena::Svc'
163 
164  def setup(self):
165 
166  from AthenaPython import PyAthena
167  setattr(PyAthena.services, self.getName(), self)
168 
169 
170  CfgPyComponent.setup(self)
171  if isinstance(self, LegacyConfigurable):
172  _svc_base.setup(self)
173 
174 
175 
177  def __init__( self, name, **kw ):
178  if isinstance(self, LegacyConfigurable):
179  _tool_base.__init__(self, name)
180  else:
181  _tool_base.__init__(self, name, **kw)
182  CfgPyComponent.__init__(self, name, **kw)
183 
184  def getGaudiType( self ): return 'AlgTool'
185  def getType(self): return 'PyAthena::Tool'
186 
187  def setup(self):
188  CfgPyComponent.setup(self)
189  if isinstance(self, LegacyConfigurable):
190  _tool_base.setup(self)
191 
192 
193 
195  def __init__( self, name, **kw ):
196  _aud_base.__init__(self, name)
197  CfgPyComponent.__init__(self, name, **kw)
198 
199  def getGaudiType( self ): return 'Auditor'
200  def getType(self): return 'PyAthena::Aud'
201 
202  def setup(self):
203  CfgPyComponent.setup(self)
204  if isinstance(self, LegacyConfigurable):
205  _aud_base.setup(self)
206 
207 
208 
210  """a class to mimic the gaudi C++ {Tool,Svc}Handle classes: automatic call
211  to `initialize` when __getattr__ is called on the instance.
212  """
213  def __init__(self, parent, attr_name):
214  msg = parent.msg.verbose
215  try:
216  parentName=parent.name()
217  except TypeError:
218  parentName=parent.name
219  msg('installing py-comp-handle for [%s.%s]...',
220  parentName, attr_name)
221  self.__dict__.update({
222  '_parent': parent,
223  '_name': attr_name,
224  '_attr': getattr(parent, attr_name),
225  '_init_called': False,
226  })
227  msg('installing py-comp-handle for [%s.%s]... [done]',
228  parentName, attr_name)
229  return
230 
231  def _init_once(self, obj):
232  if self.__dict__['_init_called']:
233  return
234  parent = self.__dict__['_parent']
235  # FIXME: should we raise something in case initialize failed ?
236  obj.initialize()
237  self.__dict__['_init_called'] = True
238  # replace the handle with the proxied object
239  setattr(parent, self.__dict__['_name'], obj)
240 
241  def __getattribute__(self, n):
242  if n.startswith('_'):
243  return super().__getattribute__(n)
244  obj = self.__dict__['_attr']
245  self._init_once(obj)
246  return getattr(obj, n)
247 
248  def __setattr__(self, n, v):
249  if n.startswith('_'):
250  return super().__setattr__(n,v)
251  obj = self.__dict__['_attr']
252  self._init_once(obj)
253  return setattr(obj, n, v)
254 
255 
256 def _is_pycomp(obj):
257  return isinstance(
258  obj,
259  (CfgPyAlgorithm, CfgPyService, CfgPyAlgTool, CfgPyAud)
260  )
261 
263  """loop over all pycomponents, inspect their attributes and install
264  a handle in place of (sub) pycomponents to trigger the auto-initialize
265  behaviour of (C++) XyzHandles.
266  """
267  import PyUtils.Logging as L
268  msg = L.logging.getLogger('PyComponentMgr').verbose
269  comps = PyComponents.instances.items()
270  ncomps = len(comps)
271  msg('installing fancy getattrs... (%i)', ncomps)
272  for k,comp in comps:
273  msg('handling [%s]...', k)
274  for attr_name, attr in comp.__dict__.items():
275  if _is_pycomp(attr):
276  msg(' ==> [%s]...', attr_name)
277  setattr(comp, attr_name,
278  _PyCompHandle(parent=comp, attr_name=attr_name))
279  msg(' ==> [%s]... [done]', attr_name)
280  msg('installing fancy getattrs... (%i) [done]',ncomps)
python.Configurables.CfgPyService.__init__
def __init__(self, name, **kw)
Definition: Control/AthenaPython/python/Configurables.py:154
python.Configurables.CfgPyComponent.OutputLevel
OutputLevel
special case of the OutputLevel: take the value from the svcMgr.MessageSvc if none already set by use...
Definition: Control/AthenaPython/python/Configurables.py:81
python.Configurables.CfgPyAlgTool.__init__
def __init__(self, name, **kw)
Definition: Control/AthenaPython/python/Configurables.py:177
python.Configurables.PyComponents
Definition: Control/AthenaPython/python/Configurables.py:18
python.Configurables.CfgPyAlgorithm.__init__
def __init__(self, name, **kw)
Definition: Control/AthenaPython/python/Configurables.py:131
python.Configurables._PyCompHandle
Definition: Control/AthenaPython/python/Configurables.py:209
python.Configurables.CfgPyComponent
Configurable base class for all Py compmonents -------------------------—.
Definition: Control/AthenaPython/python/Configurables.py:46
python.Configurables.CfgPyService.setup
def setup(self)
Definition: Control/AthenaPython/python/Configurables.py:164
python.Configurables.CfgPyAud.getGaudiType
def getGaudiType(self)
Definition: Control/AthenaPython/python/Configurables.py:199
python.Configurables.CfgPyComponent.setup
def setup(self)
Definition: Control/AthenaPython/python/Configurables.py:72
python.Configurables._PyCompHandle.__init__
def __init__(self, parent, attr_name)
Definition: Control/AthenaPython/python/Configurables.py:213
python.Configurables._PyCompHandle.__setattr__
def __setattr__(self, n, v)
Definition: Control/AthenaPython/python/Configurables.py:248
python.Configurables.CfgPyComponent.getHandle
def getHandle(self)
Definition: Control/AthenaPython/python/Configurables.py:60
python.Configurables.CfgPyAlgorithm.getGaudiType
def getGaudiType(self)
Definition: Control/AthenaPython/python/Configurables.py:138
python.Configurables.CfgPyService.getGaudiType
def getGaudiType(self)
Definition: Control/AthenaPython/python/Configurables.py:161
python.Configurables.CfgPyComponent.msg
def msg(self)
Definition: Control/AthenaPython/python/Configurables.py:56
python.Configurables._install_fancy_attrs
def _install_fancy_attrs()
Definition: Control/AthenaPython/python/Configurables.py:262
python.Configurables._is_pycomp
def _is_pycomp(obj)
Definition: Control/AthenaPython/python/Configurables.py:256
python.Configurables._tool_base
_tool_base
Definition: Control/AthenaPython/python/Configurables.py:125
python.Configurables.CfgPyAlgorithm
Configurable base class for PyAlgorithms -------------------------------—.
Definition: Control/AthenaPython/python/Configurables.py:130
python.Configurables.CfgPyAlgorithm.setup
def setup(self)
Definition: Control/AthenaPython/python/Configurables.py:141
python.Configurables._PyCompHandle._init_once
def _init_once(self, obj)
Definition: Control/AthenaPython/python/Configurables.py:231
python.Configurables._alg_base
_alg_base
Definition: Control/AthenaPython/python/Configurables.py:121
Configurable
athena/gaudi ----------------------------------------------------------—
python.Configurables.CfgPyComponent.getDlls
def getDlls(self)
Definition: Control/AthenaPython/python/Configurables.py:52
python.Configurables.CfgPyAud.__init__
def __init__(self, name, **kw)
Definition: Control/AthenaPython/python/Configurables.py:195
python.Configurables.CfgPyAlgTool.getGaudiType
def getGaudiType(self)
Definition: Control/AthenaPython/python/Configurables.py:184
python.Configurables._PyCompHandle.__getattribute__
def __getattribute__(self, n)
Definition: Control/AthenaPython/python/Configurables.py:241
python.Configurables.CfgPyComponent.merge
def merge(self, other)
Definition: Control/AthenaPython/python/Configurables.py:91
python.JetAnalysisCommon.isComponentAccumulatorCfg
isComponentAccumulatorCfg
Definition: JetAnalysisCommon.py:263
python.Configurables._aud_base
_aud_base
Definition: Control/AthenaPython/python/Configurables.py:126
python.Configurables._svc_base
_svc_base
Definition: Control/AthenaPython/python/Configurables.py:124
dqt_zlumi_pandas.update
update
Definition: dqt_zlumi_pandas.py:42
python.Configurables.CfgPyAud.setup
def setup(self)
Definition: Control/AthenaPython/python/Configurables.py:202
python.Configurables.CfgPyAlgTool.setup
def setup(self)
Definition: Control/AthenaPython/python/Configurables.py:187
python.Configurables.CfgPyComponent.__getstate__
def __getstate__(self)
Definition: Control/AthenaPython/python/Configurables.py:63
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
python.Configurables._get_prop_value
def _get_prop_value(pycomp, propname)
Definition: Control/AthenaPython/python/Configurables.py:32
python.Configurables.CfgPyAlgTool
Definition: Control/AthenaPython/python/Configurables.py:176
python.Configurables.CfgPyAud
Definition: Control/AthenaPython/python/Configurables.py:194
pickleTool.object
object
Definition: pickleTool.py:30
python.Configurables.CfgPyService
Definition: Control/AthenaPython/python/Configurables.py:153
python.Configurables.CfgPyComponent.__init__
def __init__(self, name, **kw)
Definition: Control/AthenaPython/python/Configurables.py:47
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
python.Configurables.CfgPyComponent.__setstate__
def __setstate__(self, state)
Definition: Control/AthenaPython/python/Configurables.py:68