ATLAS Offline Software
diff-jobo-cfg.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 
5 # @file: diff-jobo-cfg.py
6 # @purpose: check that 2 jobosvc.ascii files (produced with find_cfg_dups.py)
7 # have same content (both in configurables and properties)
8 # @author: Sebastien Binet <binet@cern.ch>
9 # Adrien Renaud <renaud@lal.in2p3.fr>
10 # @date: May 2010
11 #
12 # @example:
13 #
14 # diff-jobo-cfg ref.josvc.ascii chk.josvc.ascii
15 #
16 
17 from __future__ import print_function
18 
19 __author__ = "Sebastien Binet, Adrien Renaud"
20 
21 import sys
22 import os
23 
24 from optparse import OptionParser
25 
26 def dump_seq(seq):
27  for i in seq:
28  print (i)
29  pass
30 
31 def cxx_sort(dpp):
32  from collections import defaultdict
33  cxx_dpp = defaultdict(list)
34 
35  for k,v in dpp.iteritems():
36  #print (v['cxx_type'])
37  cxx_dpp[v['cxx_type']].append({k:v})
38 
39  for k,v in cxx_dpp.iteritems():
40  print ('---',k)
41  for vv in v:
42  print ('------',vv.keys())
43  print ('---------',vv.values())#['comp_type']
44  return cxx_dpp
45 
46 def load_cfg_file(fname):
47  """return the dictionary of components and their properties
48  """
49  comps_db = {}
50  try:
51  import shelve
52  comps_db = shelve.open(fname, 'r')
53  return comps_db['all-cfgs']
54  except Exception:
55  from past.builtins import execfile
56  execfile(fname, comps_db)
57  return comps_db['d']
58 
59 def dict_diff(ref, chk):
60  """ Return a dict of keys that differ with another config object. If a value is
61  not found in one fo the configs, it will be represented by KEYNOTFOUND.
62  @param ref: First dictionary to diff.
63  @param chk: Second dicationary to diff.
64  @return diff: Dict of Key => (ref.val, chk.val)
65  """
66  diff = {}
67  # Check all keys in ref dict
68  for k in ref.iterkeys():
69  if not (k in chk):
70  diff[k] = (ref[k], '<KEYNOTFOUND>')
71  elif (ref[k] != chk[k]):
72  diff[k] = (ref[k], chk[k])
73  # Check all keys in chk dict to find missing
74  for k in chk.iterkeys():
75  if not (k in ref):
76  diff[k] = ('<KEYNOTFOUND>', chk[k])
77  return diff
78 
79 def cmp_component_db(ref, chk, verbose=True):
80  """ compare 2 dicts of components
81  dicts are of the form:
82  { 'comp_type' : <name of component>,
83  'cxx_type' : <C++ type of the component>,
84  'props' : { 'property-name' : 'property-value', }
85  }
86  """
87  common_keys = []
88  ref_keys = set(ref.keys())
89  chk_keys = set(chk.keys())
90 
91  common_keys = ref_keys & chk_keys
92  ref_only_keys = ref_keys - chk_keys
93  chk_only_keys = chk_keys - ref_keys
94 
95  print ("::: components in both files: [%5s]" % (len(common_keys),))
96  print ("::: components in ref only: [%5s]" % (len(ref_only_keys),))
97  if len(ref_only_keys)>0:
98  dump_seq(ref_only_keys)
99  print ("="*80)
100  print ("::: components in chk only: [%5s]" % (len(chk_only_keys),))
101  if len(chk_only_keys)>0:
102  dump_seq(chk_only_keys)
103  print ("="*80)
104 
105  diff = []
106  for comp_name in common_keys:
107  comp_ref = ref[comp_name]
108  comp_chk = chk[comp_name]
109 
110  ref_props = sorted([(k,v) for k,v in comp_ref['props'].iteritems()])
111  chk_props = sorted([(k,v) for k,v in comp_chk['props'].iteritems()])
112  if ref_props != chk_props:
113  diff.append((comp_name, ref_props, chk_props,
114  dict_diff(ref=comp_ref['props'],
115  chk=comp_chk['props'])))
116  pass
117 
118  print ("::: components with different properties: [%5s]" % (len(diff),))
119  for name, ref_props, chk_props, diff_props in diff:
120  print ("::: - component: [%s]" % (name,))
121  for prop_name, prop_value in diff_props.iteritems():
122  ref_value = prop_value[0]
123  chk_value = prop_value[1]
124  if isinstance(ref_value, list):
125  ref_value = sorted(ref_value)
126  if isinstance(chk_value, list):
127  chk_value = sorted(chk_value)
128 
129  if isinstance(ref_value, list) and isinstance(chk_value, list):
130  dref_value = set(ref_value) - set(chk_value)
131  dchk_value = set(chk_value) - set(ref_value)
132  ref_value = sorted(list(dref_value))
133  chk_value = sorted(list(dchk_value))
134  print ("-%s: %r" %(prop_name, ref_value,))
135  print ("+%s: %r" %(prop_name, chk_value,))
136 
137 
138  if (len(ref_only_keys) > 0 or
139  len(chk_only_keys) > 0 or
140  len(diff) > 0):
141  return 1
142  return 0
143 
144 if __name__ == "__main__":
145 
146  parser = OptionParser(
147  usage="usage: %prog [options] [-r] ref.josvc.ascii [-f] chk.josvc.ascii"
148  )
149  _add = parser.add_option
150 
151  _add( "-r",
152  "--ref",
153  dest = "ref_fname",
154  help = "The path to the first josvc.ascii file to analyze" )
155 
156  _add( "-f",
157  "--file",
158  dest = "chk_fname",
159  help = "The path to the second josvc.ascii file to analyze" )
160 
161 # _add("-o", "--output",
162 # dest = "o_fname",
163 # default = "cfg.diff",
164 # help = "file where to store the output of `which diff` run on the input files given to %PROG")
165 
166  _add( "-v",
167  "--verbose",
168  action = "store_true",
169  dest = "verbose",
170  default = False,
171  help = "Switch to activate verbose printout" )
172 
173 
174  (options, args) = parser.parse_args()
175 
176  if len(args) > 0 and args[0][0] != "-":
177  options.ref_fname = args[0]
178  pass
179  if len(args) > 1 and args[1][0] != "-":
180  options.chk_fname = args[1]
181  pass
182 
183  if (options.chk_fname is None or options.ref_fname is None) :
184  str(parser.print_help() or "")
185  sys.exit(1)
186  pass
187 
188  chk_fname = os.path.expandvars(os.path.expanduser(options.chk_fname))
189  ref_fname = os.path.expandvars(os.path.expanduser(options.ref_fname))
190 
191  print (":"*80)
192  print ("::: comparing configurations")
193  print ("::: ref: %s" % ref_fname)
194  ref_db = load_cfg_file(ref_fname)
195  print ("::: -> [%d] components" % (len(ref_db.keys()),))
196  print ("::: chk: %s" % chk_fname)
197  chk_db = load_cfg_file(chk_fname)
198  print ("::: -> [%d] components" % (len(chk_db.keys()),))
199 
200  sc = cmp_component_db(ref_db, chk_db, options.verbose)
201 
202  if sc==0:
203  print ("::: all good")
204  else:
205  print ("::: configurations differ !")
206  print ("::: bye.")
207  print (":"*80)
208  sys.exit(sc)
python.Bindings.iteritems
iteritems
Definition: Control/AthenaPython/python/Bindings.py:812
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
diff-jobo-cfg.dict_diff
def dict_diff(ref, chk)
Definition: diff-jobo-cfg.py:59
diff-jobo-cfg.dump_seq
def dump_seq(seq)
Definition: diff-jobo-cfg.py:26
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
diff-jobo-cfg.cxx_sort
def cxx_sort(dpp)
Definition: diff-jobo-cfg.py:31
diff-jobo-cfg.load_cfg_file
def load_cfg_file(fname)
Definition: diff-jobo-cfg.py:46
str
Definition: BTagTrackIpAccessor.cxx:11
diff-jobo-cfg._add
_add
Definition: diff-jobo-cfg.py:149
diff-jobo-cfg.cmp_component_db
def cmp_component_db(ref, chk, verbose=True)
Definition: diff-jobo-cfg.py:79