358def cmpConfigs (ref, chk, refName=None, chkName=None):
359 """
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
367 """
368 import os
369 _path = os.path
370 ref = _path.expanduser(_path.expandvars(ref))
371 chk = _path.expanduser(_path.expandvars(chk))
372
373 from PyUtils.Decorators import forking
374
375 @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,
385
386 "raise SystemExit(0)",
387 ]
388 jobofile = NamedTemporaryFile(suffix='.py')
389 map (jobofile.writelines, [l+os.linesep for l in job])
390 jobofile.flush()
391
392 from subprocess import getstatusoutput
393 sc,out = getstatusoutput ('athena.py %s' % jobofile.name)
394
395 jobofile.close()
396 if sc==0:
397 return fname
398 return (sc, out)
399
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):
404 raise RuntimeError (
405 'could not create a shelve on the fly:\n%s'%ref[1])
406 import atexit
407 atexit.register (os.unlink, ref)
408
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):
413 raise RuntimeError (
414 'could not create a shelve on the fly:\n%s'%chk[1])
415 import atexit
416 atexit.register (os.unlink, chk)
417
418 for fname in (ref, chk):
419 if not _path.exists (fname):
420 raise RuntimeError ('file [%s] does not exist'%fname)
421
422 @forking
423 def _dict_cfg (fname, cfgName):
424
425 jar = loadFromPickle (fname, cfgName)
426 d = list()
427 all_cfgs = dict()
428 all_cfgs.setdefault (dict)
429 def _visit_cfg (cfg):
430 name = cfg.getJobOptName()
431 values = [name]
432 all_cfgs[name] = dict()
433 props = cfg.getProperties()
434 def _get_value (cfg, k, v):
435 _no_value = cfg.propertyNoValue
436 if v == _no_value:
437 v = cfg.getDefaultProperty(k)
438 return v
439
441 for k,v in props.items():
442 if not isinstance(v, Configurable):
443 all_cfgs[name][k] = _get_value(cfg,k,v)
444 else:
445 all_cfgs[name][k] = v.getJobOptName()
446 if v not in cfg.getAllChildren():
447 values.extend (_visit_cfg(v))
448
449 if hasattr(cfg, 'getAllChildren'):
450 for c in cfg.getAllChildren():
451 values.extend (_visit_cfg(c))
452 return values
453
454 for c in jar.athAlgSeq.getChildren():
455 d.extend (_visit_cfg(c))
456
457 for c in jar.ServiceMgr.getChildren():
458 d.extend (_visit_cfg(c))
459 return d, all_cfgs
460
461 ref_list, ref_cfgs = _dict_cfg (ref, refName)
462 chk_list, chk_cfgs = _dict_cfg (chk, chkName)
463
464 report = []
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])
476
477 common_cfgs = set (
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)]
480 )
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**'))
488
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