7 Script to compare trigger chain counts in YAML format produced by
8 chainDump.py --yaml and providing information and instructions for
9 updating counts reference in the athena repository.
19 from AthenaCommon.Utils
import unixtools
20 from TrigValTools.TrigValSteering.Common
import package_prefix_dict
as packages
21 from TrigValTools.TrigValSteering.Common
import running_in_CI
25 parser = argparse.ArgumentParser(usage=
'%(prog)s [options] inputFile',
27 parser.add_argument(
'inputFile',
29 help=
'Name of input counts file')
30 parser.add_argument(
'-r',
'--referenceFile',
32 help=
'Name of reference counts file. If empty, try to guess from inputFile')
33 parser.add_argument(
'-s',
'--sourceRepository',
35 help=
'Path to the git checkout of the athena repository.'
36 'If empty, try to guess from the environment')
37 parser.add_argument(
'-p',
'--patch',
39 help=
'Create a git patch file with the count differences')
40 parser.add_argument(
'-m',
'--matchingOnly',
42 help=
'Ignore added and removed chains, and only compare counts for chains ' + \
43 'present in both reference and input file')
44 parser.add_argument(
'-v',
'--verbose',
46 help=
'Increase output verbosity')
52 if inputFile.endswith(
'.new'):
53 inp_name = os.path.split(inputFile)[-1]
54 ref_name = inp_name[0:-4] +
'.ref'
55 logging.debug(
'Searching for file %s in DATAPATH', ref_name)
56 for pkg_name
in packages:
57 ref_path = unixtools.find_datafile(pkg_name+
'/'+ref_name)
61 logging.debug(
'Found %s', ref_path)
63 logging.debug(
'Not found')
69 Try to find the athena git repository based on paths in env.
70 Needs to work both in local WorkDir build and in full/incremental CI build.
72 logging.debug(
'Searching for the source repository path')
73 search_str =
'/Trigger/TrigValidation'
75 logging.debug(
'Trying %s', p)
76 if os.path.islink(p)
and os.path.isfile(p)
and search_str
in os.path.realpath(p):
77 candidate = os.path.realpath(p).
split(search_str)[0]
78 logging.debug(
'Candidate %s', candidate)
79 if os.path.isdir(candidate +
'/.git'):
83 result = try_path(ref_path)
87 env_vars = [
'DATAPATH',
'JOBOPTSEARCHPATH',
'CALIBPATH',
'XMLPATH']
88 path_lists = [os.getenv(var).
split(os.pathsep)
for var
in env_vars]
89 max_len =
max([len(pl)
for pl
in path_lists])
90 max_len =
min(max_len, 2)
91 for i
in range(max_len):
95 paths = glob.glob(pl[i]+
'/**', recursive=
True)
105 if not os.path.isfile(path):
106 logging.error(
'Not a file: %s', path)
108 with open(path)
as f:
109 result = yaml.safe_load(f)
114 if inp_data[key] != ref_data[key]:
115 logging.info(
' %s: %d -> %d', key, ref_data[key], inp_data[key])
119 inp_steps = inp_data.get(key, dict())
120 ref_steps = ref_data.get(key, dict())
121 if inp_steps != ref_steps:
122 logging.info(
' %s:', key)
123 for step
in range(
max(len(inp_steps), len(ref_steps))):
124 inp_count = inp_steps.get(step, 0)
125 ref_count = ref_steps.get(step, 0)
126 if inp_count != ref_count:
127 logging.info(
' %d: %d -> %d', step, ref_count, inp_count)
132 chains_not_in_ref = [c[0]
for c
in inp_dict.items()
if c[0]
not in ref_dict]
133 chains_not_in_inp = [c[0]
for c
in ref_dict.items()
if c[0]
not in inp_dict]
134 chains_count_diff = [c[0]
for c
in inp_dict.items()
if c[0]
in ref_dict
and c[1] != ref_dict[c[0]]]
137 n_new_chains = len(chains_not_in_ref)
138 if n_new_chains > 0
and not matching_only:
140 logging.info(
'Found %d new chain%s added:', n_new_chains,
's' if n_new_chains > 1
else '')
141 for chain_name
in chains_not_in_ref:
142 logging.info(
' %s', chain_name)
145 n_removed_chains = len(chains_not_in_inp)
146 if n_removed_chains > 0
and not matching_only:
148 logging.info(
'Found %d chain%s removed:', n_removed_chains,
's' if n_removed_chains > 1
else '')
149 for chain_name
in chains_not_in_inp:
150 logging.info(
' %s', chain_name)
153 n_diff_chains = len(chains_count_diff)
154 if n_diff_chains > 0:
156 logging.info(
'Found %d chain%s with count differences:', n_diff_chains,
's' if n_diff_chains > 1
else '')
157 for chain_name
in chains_count_diff:
158 logging.info(
' %s:', chain_name)
159 inp_data = inp_dict[chain_name]
160 ref_data = ref_dict[chain_name]
169 def find_ref_package():
172 if '/data/'+pkg
in ref_path:
173 return pkg, os.path.split(path)[1]
175 package_name, ref_file_name = find_ref_package()
177 logging.warning(
'Failed to find reference package name, cannot create git patch file')
180 ref_rel_path =
'/Trigger/TrigValidation/' + package_name +
'/share/' + ref_file_name
182 diff_cmd =
'diff -U 1 -b'
183 diff_cmd +=
' --label a' + ref_rel_path +
' ' + ref_path
184 diff_cmd +=
' --label b' + ref_rel_path +
' ' + inp_path
186 diff_txt = subprocess.getoutput(diff_cmd)
187 patch_name = os.path.split(ref_path)[1]
188 if patch_name.endswith(
'.ref')
or patch_name.endswith(
'.new'):
189 patch_name = patch_name[0:-4]
190 patch_name +=
'.patch'
191 with open(patch_name,
'w')
as patch_file:
192 patch_file.write(
'diff --git a{p:s} b{p:s}\n'.
format(p=ref_rel_path))
193 patch_file.write(diff_txt +
'\n')
194 logging.info(
'Patch file created. To apply, run in the athena source directory:')
195 logging.info(
'git apply %s/%s', os.getcwd(), patch_name)
196 logging.info(
'Then check with git diff and, if everything is correct, add and commit')
198 logging.info(
'or see the patch below:\n')
199 subprocess.call(
'cat ' + patch_name, shell=
True)
205 logging.basicConfig(stream=sys.stdout,
206 format=
'chainComp %(levelname)-8s %(message)s',
207 level=logging.DEBUG
if args.verbose
else logging.INFO)
209 inp_path = args.inputFile
212 logging.error(
'No reference file specified and couldn\'t guess from '
213 'input name. Please use the -r argument (see --help).')
216 logging.info(
'Test file: %s', inp_path)
217 logging.info(
'Reference file: %s', ref_path)
225 if (
not inp_dict)
or (
not ref_dict):
228 retcode =
print_diff(inp_dict, ref_dict, args.matchingOnly)
230 logging.error(
'Trigger counts differ from the reference. If the above differences are intended, update the reference')
234 logging.info(
'Trigger counts match the reference')
239 if '__main__' in __name__: