1#!/usr/bin/env python2.7
2
3from __future__ import print_function
4
5desc = '''Generate the difference of two YAML files into a new YAML file (works on
6pair of directories too).  A new attribute 'Added' is set to True or False
7depending whether the entry is added or removed from the first input to the
8next.
9
10The tools requires PyYAML.'''
11
12import yaml
13# Try to use the C parser.
14try:
15    from yaml import CLoader as Loader
16except ImportError:
17    from yaml import Loader
18
19import optrecord
20import argparse
21from collections import defaultdict
22from multiprocessing import cpu_count, Pool
23
24if __name__ == '__main__':
25    parser = argparse.ArgumentParser(description=desc)
26    parser.add_argument(
27        'yaml_dir_or_file_1',
28        help='An optimization record file or a directory searched for optimization '
29             'record files that are used as the old version for the comparison')
30    parser.add_argument(
31        'yaml_dir_or_file_2',
32        help='An optimization record file or a directory searched for optimization '
33             'record files that are used as the new version for the comparison')
34    parser.add_argument(
35        '--jobs',
36        '-j',
37        default=cpu_count(),
38        type=int,
39        help='Max job count (defaults to %(default)s, the current CPU count)')
40    parser.add_argument(
41        '--no-progress-indicator',
42        '-n',
43        action='store_true',
44        default=False,
45        help='Do not display any indicator of how many YAML files were read.')
46    parser.add_argument('--output', '-o', default='diff.opt.yaml')
47    args = parser.parse_args()
48
49    files1 = optrecord.find_opt_files(args.yaml_dir_or_file_1)
50    files2 = optrecord.find_opt_files(args.yaml_dir_or_file_2)
51
52    print_progress = not args.no_progress_indicator
53    all_remarks1, _, _ = optrecord.gather_results(files1, args.jobs, print_progress)
54    all_remarks2, _, _ = optrecord.gather_results(files2, args.jobs, print_progress)
55
56    added = set(all_remarks2.values()) - set(all_remarks1.values())
57    removed = set(all_remarks1.values()) - set(all_remarks2.values())
58
59    for r in added:
60        r.Added = True
61    for r in removed:
62        r.Added = False
63
64    result = added | removed
65    for r in result:
66        r.recover_yaml_structure()
67
68    with open(args.output, 'w') as stream:
69        yaml.dump_all(result, stream)
70