10 """Shelves for writing jars of configuration. Example:
14 shelve = ConfigurationShelve( "myjob" )
15 jar = ConfigurationJar( 'myjar' )
19 shelve = ConfigurationShelve( "myjob" )
20 jar = shelve.retrieve( 'myjar' )
27 Wim Lavrijsen (WLavrijsen@lbl.gov),
28 Sebastien Binet <binet@cern.ch>"""
30 __all__ = [
'ConfigurationShelve',
'ConfigurationJar',
31 'saveToAscii',
'loadFromAscii',
32 'saveToPickle',
'loadFromPickle',
44 self.
_shelve = shelve.open( name, protocol = pickle.HIGHEST_PROTOCOL )
51 from AthenaCommon.AlgSequence
import AlgSequence
56 from AthenaCommon.AppMgr
import theApp, ServiceMgr, ToolSvc, theAuditorSvc
58 theApp._streams.removeAll()
59 ServiceMgr.removeAll()
61 theAuditorSvc.removeAll()
63 del topSeq, theApp, ServiceMgr, ToolSvc, theAuditorSvc
82 from AthenaCommon.AppMgr
import theApp, ServiceMgr
83 from AthenaCommon.JobProperties
import jobproperties
85 from .
import AlgSequence
as _as
103 d[
'name' ] = self.
name
108 d[
'AppMgr' ] = self.
AppMgr
109 d[
'Streams' ] = self.
AppMgr._streams
123 import AthenaCommon.JobProperties
as JobProperties
124 JobProperties.jobproperties = d[
'JobProperties']
128 return os.linesep.join( [
"%s" % v
for v
in self.
content().
values() ] )
135 """Inspect the 'configured' JobOptionsSvc and existing services,
136 then dump the properties of each component into a pickle file.
139 from collections
import defaultdict
140 jocat = defaultdict( dict )
141 jocfg = defaultdict( dict )
143 def _fillCfg( client, props ):
146 if hasattr( v,
'toStringProperty' ):
147 v =
str( v.toStringProperty() )
148 elif hasattr( v,
'toString' ):
149 v =
str( v.toString() )
150 elif type (v)
is float:
157 jocfg[ client ][ n ] = v
159 from AthenaCommon.AppMgr
import theApp
160 from AthenaCommon.AppMgr
import ServiceMgr
as svcMgr
164 theApp.setup( recursive =
True )
166 app_props = [ (k,v.value())
168 _fillCfg(
'ApplicationMgr', app_props )
173 svcs = theApp.getHandle().
services()
178 svc = getattr( svcMgr, svcname,
None )
180 _fillCfg( svcname, svc.getValuedProperties().
items() )
184 evLoopName = theApp.EventLoop.split(
'/')[-1]
185 evLoop = getattr( svcMgr, evLoopName )
188 for k,v
in evLoop.properties().
items():
189 if v != C.propertyNoValue:
190 props.append( (k,v) )
191 _fillCfg( evLoopName, props )
193 except AttributeError:
198 import AthenaPython.PyAthena
as PyAthena
199 josvc = PyAthena.py_svc(
'JobOptionsSvc',iface=
"Gaudi::Interfaces::IOptionsSvc")
200 allProps=josvc.items()
201 for prop
in allProps:
204 client=
".".
join(cn[:-1])
206 jocat[ client ][ n ] = v
209 for k
in (
'Go',
'Exit' ):
210 if k
in jocfg[
'ApplicationMgr' ]:
211 del jocfg[
'ApplicationMgr' ][k]
215 for c
in C.allConfigurables.values():
225 except AttributeError:
233 cfg =
open( cfg_fname,
'wb' )
235 pickle.dump( jocat, cfg )
236 pickle.dump( jocfg, cfg )
237 pickle.dump( pycomps, cfg )
246 """Load properties from a pickle file, previously dumped by
247 storeConfiguration, back into the JobOptionsSvc.
250 cfg =
open( cfg_fname,
'rb' )
252 jocat = pickle.load( cfg )
253 jocfg = pickle.load( cfg )
254 pycomps = pickle.load( cfg )
258 kw = jocfg[
'ApplicationMgr' ]
259 from AthenaCommon.AppMgr
import theApp
260 theApp.JobOptionsSvcType = kw[
'JobOptionsSvcType' ]
261 theApp.MessageSvcType = kw[
'MessageSvcType' ]
262 theApp.getHandle( kw )
263 del jocfg[
'ApplicationMgr' ]
270 theApp.__class__.setup = noop
272 import AthenaPython.PyAthena
as PyAthena
273 josvc = PyAthena.py_svc(
'JobOptionsSvc', createIf =
False, iface =
'Gaudi::Interfaces::IOptionsSvc')
276 import GaudiPython.Bindings
as gaudi
278 if client ==
"ApplicationMgr":
281 for n,v
in jocat[ client ].
items():
282 josvc.set( client+
'.'+n, v )
286 svc = PyAthena.py_svc( client, createIf =
False, iface=
'IProperty' )
287 for n,v
in jocfg[ client ].
items():
289 p = gaudi.StringProperty()
296 import AthenaPython.Configurables
as _C
297 _C.PyComponents.instances = dict( (p.name, p)
for p
in pycomps )
299 if hasattr( p,
'setup' ):
300 if callable( p.setup ):
307 Helper function to store the current configuration to (ASCII) file
313 from AthenaCommon
import Configurable
314 from AthenaCommon
import Constants
315 llevel = Configurable.log.level
316 Configurable.log.setLevel( Constants.INFO )
318 if cfgName
is None: cfgName =
"Snapshot"
322 out =
open( out,
"w" )
323 for v
in content.values(): out.write(
str(v) + os.linesep )
325 Configurable.log.setLevel( llevel )
331 Helper function to retrieve a configuration from an ASCII file.
333 raise NotImplementedError(
"Sorry no restoration from ASCII file (yet?)")
337 Helper function to store the current configuration to a pickle file
339 if cfgName
is None: cfgName =
"Snapshot"
348 Helper function to retrieve a configuration from a pickle file
350 if cfgName
is None: cfgName =
"Snapshot"
352 fileName = os.path.expanduser(os.path.expandvars(fileName))
355 jar = shelve.retrieve( cfgName )
360 Helper function to compare 2 configurations.
361 @param ref the path to a pickle file where a configuration was stored
362 @param chk the path to a pickle file where a configuration was stored
363 @param refName the name of the configuration jar to load
364 @param chkName the name of the configuration jar to load
365 if `ref` and/or `chk` are joboptions (ie: their extension is '.py') a shelve
366 is automatically created on the fly
370 ref = _path.expanduser(_path.expandvars(ref))
371 chk = _path.expanduser(_path.expandvars(chk))
373 from PyUtils.Decorators
import forking
376 def _create_shelve (joboname):
377 from tempfile
import NamedTemporaryFile
378 fname = os.path.basename (joboname)
379 fname = os.path.splitext(fname)[0] +
'.pkl'
380 fname = NamedTemporaryFile(prefix=fname, suffix=
'.pkl').name
381 job = [
"from AthenaCommon.Include import include",
382 "include ('%s')" % joboname,
383 "from AthenaCommon.ConfigurationShelve import saveToPickle",
384 "saveToPickle ('%s')" % fname,
386 "raise SystemExit(0)",
388 jobofile = NamedTemporaryFile(suffix=
'.py')
389 map (jobofile.writelines, [l+os.linesep
for l
in job])
392 from subprocess
import getstatusoutput
393 sc,out = getstatusoutput (
'athena.py %s' % jobofile.name)
400 if os.path.splitext(ref)[1]==
'.py':
401 print (
"::: creating a shelve on the fly for [%s]..."%ref)
402 ref = _create_shelve (ref)
403 if not isinstance(ref, str):
405 'could not create a shelve on the fly:\n%s'%ref[1])
407 atexit.register (os.unlink, ref)
409 if os.path.splitext(chk)[1]==
'.py':
410 print (
"::: creating a shelve on the fly for [%s]..."%chk)
411 chk = _create_shelve (chk)
412 if not isinstance(chk, str):
414 'could not create a shelve on the fly:\n%s'%chk[1])
416 atexit.register (os.unlink, chk)
418 for fname
in (ref, chk):
419 if not _path.exists (fname):
420 raise RuntimeError (
'file [%s] does not exist'%fname)
423 def _dict_cfg (fname, cfgName):
425 jar = loadFromPickle (fname, cfgName)
428 all_cfgs.setdefault (dict)
429 def _visit_cfg (cfg):
430 name = cfg.getJobOptName()
432 all_cfgs[name] = dict()
433 props = cfg.getProperties()
434 def _get_value (cfg, k, v):
435 _no_value = cfg.propertyNoValue
437 v = cfg.getDefaultProperty(k)
441 for k,v
in props.items():
442 if not isinstance(v, Configurable):
443 all_cfgs[name][k] = _get_value(cfg,k,v)
445 all_cfgs[name][k] = v.getJobOptName()
446 if v
not in cfg.getAllChildren():
447 values.extend (_visit_cfg(v))
449 if hasattr(cfg,
'getAllChildren'):
450 for c
in cfg.getAllChildren():
451 values.extend (_visit_cfg(c))
454 for c
in jar.athAlgSeq.getChildren():
455 d.extend (_visit_cfg(c))
457 for c
in jar.ServiceMgr.getChildren():
458 d.extend (_visit_cfg(c))
461 ref_list, ref_cfgs = _dict_cfg (ref, refName)
462 chk_list, chk_cfgs = _dict_cfg (chk, chkName)
465 addNames,subNames = [],[]
466 if ref_list != chk_list:
467 report.append (
"::: configurable list in 'ref' and in 'chk' differ !")
468 addNames =
sorted([ n
for n
in chk_cfgs
if not (n
in ref_cfgs) ])
469 if len (addNames) > 0:
470 report.append (
"::: configurables in 'chk' and not in 'ref':")
471 report.extend ([
" + %s" % n
for n
in addNames])
472 subNames =
sorted([ n
for n
in ref_cfgs
if not (n
in chk_cfgs) ])
473 if len (subNames) > 0:
474 report.append (
"::: configurables in 'ref' and not in 'chk':")
475 report.extend ([
" - %s" % n
for n
in subNames])
478 [n
for n
in ref_list
if not (n
in addNames
or n
in subNames)] +
479 [n
for n
in chk_list
if not (n
in addNames
or n
in subNames)]
481 for n
in common_cfgs:
482 ref_cfg = ref_cfgs[n]
483 chk_cfg = chk_cfgs[n]
484 diff_props_report = []
485 for k
in ref_cfg.iterkeys():
486 ref_val =
str(ref_cfg.get(k,
'**N/A**'))
487 chk_val =
str(chk_cfg.get(k,
'**N/A**'))
489 if ref_val != chk_val:
490 diff_props_report.append (
" ref: %s = %r" % (k, ref_val))
491 diff_props_report.append (
" chk: %s = %r" % (k, chk_val))
492 if len(diff_props_report)>0:
493 report.append (
"::: properties differing for [%s]:"%n)
494 report.extend (diff_props_report)
495 return (ref_list, ref_cfgs), (chk_list, chk_cfgs), report