Marlin  01.17.01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
compareMarlinSteeringFiles.py
Go to the documentation of this file.
1 #!/bin/env python
2 
3 import sys
4 from pprint import pprint
5 from copy import deepcopy
6 
7 from xml.etree.ElementTree import ElementTree
8 
9 def getTree( xmlFile ):
10  """ parse file and return XML tree """
11  et = ElementTree()
12  et.parse( xmlFile )
13  return et
14 
15 
16 def getProcessors( tree ):
17  """ return a dict of all processors and their parameters """
18  processors = dict()
19  procElements = tree.findall('processor')
20  for proc in procElements:
21  procName = proc.attrib.get("name")
22  paramDict = dict()
23  parameters = proc.findall('parameter')
24  for param in parameters:
25  paramName = param.attrib.get('name')
26  paramDict[paramName] = getValue( param , "<This Value did not Exist in this file or was empty>" )
27  processors[procName] = paramDict
28 
29  groupElements = tree.findall('group')
30  for group in groupElements:
31  groupParam = dict()
32  parameters = group.findall('parameter')
33  for param in parameters:
34  paramName = param.attrib.get('name')
35  groupParam[paramName] = getValue( param , "<This Value did not Exist in this file or was empty>" )
36 
37  procElements = group.findall("processor")
38  for proc in procElements:
39  procName = proc.attrib.get("name")
40  paramDict = deepcopy(groupParam)
41  parameters = proc.findall('parameter')
42  for param in parameters:
43  paramName = param.attrib.get('name')
44  paramDict[paramName] = getValue( param , "<This Value did not Exist in this file or was empty>" )
45  processors[procName] = paramDict
46 
47 
48  return processors
49 
50 
51 def getValue( element, default=None ):
52  if element.get('value'):
53  return element.get('value').strip()
54  if element.text:
55  return element.text.strip()
56  return default
57 
58 
59 def getGlobalDict( globalElements ):
60  """return dict of global parameters and values """
61  pars = dict()
62  for param in globalElements:
63  name = param.get('name')
64  value = getValue( param )
65  pars[name] = value
66 
67  return pars
68 
69 def compareGlobalParameters( tree1, tree2 ):
70  """ compare the global parameters in the marlin steering files """
71 
72  par1 = getGlobalDict( tree1.findall('global/parameter') )
73  par2 = getGlobalDict( tree2.findall('global/parameter') )
74  parCopy1 = deepcopy(par1)
75  parCopy2 = deepcopy(par2)
76 
77  for name1, value1 in par1.iteritems():
78  if name1 in par2 and value1 == par2.get(name1, "<Unknown Parameter>"):
79  ## remove parameters that are equal
80  del parCopy1[name1]
81  del parCopy2[name1]
82 
83  print "\n++++ GlobalParameters that exist in the first file that are different or non-existent in the second file"
84  pprint( parCopy1 )
85  print "\n++++ GlobalParameters that exist in the second file that are different or non-existent in the first file"
86  pprint( parCopy2 )
87 
88 
89 def compareExecutingProcessors( tree1, tree2 ):
90  """ compare the list of processors to execute, order matters """
91  exec1 = tree1.findall('execute/processor')
92  exec2 = tree2.findall('execute/processor')
93  if len(exec1) != len(exec2):
94  print "Mismatch in number of executing processors!", len(exec1), "vs", len(exec2)
95 
96  for index, proc1 in enumerate( exec1 ):
97  if index >= len(exec2):
98  print "More processors in first file than in second"
99  break
100  proc2 = exec2[index]
101  name1 = proc1.get('name')
102  name2 = proc2.get('name')
103  if name1 != name2:
104  print "Difference in executing processors", name1, "does not match processor", name2
105  print "Check the order of processor execution!"
106  break
107 
108 def compareExecutingGroups( tree1, tree2 ):
109  """ compare the list of groups to execute, order matters """
110  exec1 = tree1.findall('execute/group')
111  exec2 = tree2.findall('execute/group')
112  if len(exec1) != len(exec2):
113  print "Mismatch in number of executing groups!", len(exec1), "vs", len(exec2)
114 
115  for index, grp1 in enumerate( exec1 ):
116  if index >= len(exec2):
117  print "More groups in first file than in second"
118  break
119  grp2 = exec2[index]
120  name1 = grp1.get('name')
121  name2 = grp2.get('name')
122  if name1 != name2:
123  print "Difference in executing groups", name1, "does not match group", name2
124  print "Check the order of group execution!"
125  break
126 
127 def __keepOnlySelected( processors, selectedProcessors ):
128  """ keep only those processors we want to compare """
129  if not selectedProcessors:
130  return
131 
132  for processor in processors.keys():
133  keep = False
134  for procString in selectedProcessors:
135  if procString.lower() in processor.lower():
136  keep=True
137  break
138 
139  if not keep:
140  del processors[processor]
141 
142 def compareTrees( tree1, tree2, selectedProcessors=None ):
143  """compare the content of the two xml trees, as these are marlin steering
144  files we only look for processors, get their parameters and then compare the
145  value of all the processor parameters
146 
147  """
148 
149  processors1 = getProcessors( tree1 )
150  processors2 = getProcessors( tree2 )
151 
152  __keepOnlySelected( processors1, selectedProcessors )
153  __keepOnlySelected( processors2, selectedProcessors )
154 
155  ### we need a copy so we can remove all parameters/processors that are equal
156  procCopy1 = deepcopy(processors1)
157  procCopy2 = deepcopy(processors2)
158 
159  for proc1, parameters1 in processors1.iteritems():
160  if proc1 in processors2:
161  parameters2 = processors2[ proc1 ]
162 
163  for param1, value1 in parameters1.iteritems():
164  if param1 in parameters2:
165  value2 = parameters2[param1].strip()
166  if value2 == value1.strip():
167  del procCopy1[proc1][param1]
168  del procCopy2[proc1][param1]
169 
170  ## remove empty parameter dicts
171  if not procCopy1.get(proc1):
172  del procCopy1[proc1]
173  #default is true to not trying to delete non-existent entry
174  if not procCopy2.get(proc1, True):
175  del procCopy2[proc1]
176 
177  print "\n++++ Entries that exist in the first file that are different or non-existent in the second file"
178  pprint( procCopy1 )
179  print "\n++++ Entries that exist in the second file that are different or non-existent in the first file"
180  pprint( procCopy2 )
181 
182 
183 def run():
184  args = sys.argv
185  if len(args) < 3:
186  print "incorrect number of input files, need two marlin steering files as argument and optionally select processors to compare"
187  print "compareMarlinSteeringFiles.py file1.xml file2.xml [processor1] [...]"
188  exit(1)
189 
190  try:
191  tree1 = getTree( args[1] )
192  tree2 = getTree( args[2] )
193  selectedProcessors = args[3:]
194  except Exception as ex:
195  print "Exception when getting trees: %r " % ex
196  exit(1)
197 
198  print "\n++++ Start comparing"
199  compareExecutingProcessors( tree1, tree2 )
200  print ""
201  compareExecutingGroups( tree1, tree2 )
202  print ""
203  compareGlobalParameters( tree1, tree2 )
204  print ""
205  compareTrees( tree1, tree2, selectedProcessors)
206  print "\n++++ Done comparing"
207 
208 
209 if __name__ == "__main__":
210  run()