Greg Edelston | fa64921 | 2020-10-13 14:40:38 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """Consolidate platform-specific data into CONSOLIDATE.json. |
| 7 | |
| 8 | This script consolidates all the platform-specific config data into one file. |
| 9 | This enables test libraries to only rely on a single file. |
| 10 | |
| 11 | The resulting file contains a single JSON object whose keys are the platform |
| 12 | names and whose values are the contents of that platform's original .json file. |
| 13 | The platforms are sorted alphabetically by name, with DEFAULTS first. Within |
| 14 | each platform, the order of keys is preserved from the original .json file. |
| 15 | |
| 16 | Design doc: go/consolidate-fwtc |
| 17 | """ |
| 18 | |
| 19 | import argparse |
| 20 | import collections |
| 21 | import json |
| 22 | import os |
| 23 | import stat |
| 24 | import sys |
| 25 | |
| 26 | |
| 27 | DEFAULT_OUTPUT_FILEPATH = 'CONSOLIDATED.json' |
| 28 | |
| 29 | |
| 30 | def parse_args(argv=None): |
| 31 | """Determine input dir and output file from command-line args. |
| 32 | |
| 33 | Args: |
| 34 | argv: List of command-line args, excluding the invoked script. |
| 35 | Typically, this should be set to sys.argv[1:]. |
| 36 | |
| 37 | Returns: |
| 38 | An argparse.Namespace with two attributes: |
| 39 | input_dir: The directory containing fw-testing-configs JSON files |
| 40 | output: The filepath where the final JSON output should be written |
| 41 | """ |
| 42 | parser = argparse.ArgumentParser() |
| 43 | parser.add_argument('-i', '--input-dir', |
| 44 | help='Directory with fw-testing-configs JSON files', |
| 45 | default=os.path.dirname(__file__)) |
| 46 | parser.add_argument('-o', '--output', help='Filepath to write output to', |
| 47 | default=DEFAULT_OUTPUT_FILEPATH) |
| 48 | return parser.parse_args(argv) |
| 49 | |
| 50 | |
| 51 | def get_platform_names(fwtc_dir): |
| 52 | """Create a list of platforms with JSON files. |
| 53 | |
| 54 | Args: |
| 55 | fwtc_dir: The fw-testing-configs directory containing platform JSON files. |
| 56 | |
| 57 | Returns: |
| 58 | A list of strings representing the names of platforms which have JSON |
| 59 | files in fwtc_dir, starting with DEFAULTS and then alphabetically. |
| 60 | These names do not include .json. |
| 61 | """ |
| 62 | platforms = [] |
| 63 | for fname in os.listdir(fwtc_dir): |
| 64 | platform, ext = os.path.splitext(fname) |
| 65 | if ext != '.json': |
| 66 | continue |
| 67 | elif platform in ('DEFAULTS', 'CONSOLIDATED'): |
| 68 | continue |
| 69 | platforms.append(platform) |
| 70 | platforms.sort() |
| 71 | platforms = ['DEFAULTS'] + platforms |
| 72 | return platforms |
| 73 | |
| 74 | |
| 75 | def load_json(fwtc_dir, platforms): |
| 76 | """Create an OrderedDict of {platform_name: json_contents}. |
| 77 | |
| 78 | Args: |
| 79 | fwtc_dir: The fw-testing-configs directory containing platform JSON files. |
| 80 | platforms: A sorted list of names which have JSON files in fwtc_dir. |
| 81 | |
| 82 | Returns: |
| 83 | An OrderedDict whose keys are platforms in the same order as in the |
| 84 | passed-in param, and whose values OrderedDicts representing the contents |
| 85 | of that platform's corresponding ${PLATFORM}.json file. |
| 86 | """ |
| 87 | consolidated = collections.OrderedDict() |
| 88 | for platform in platforms: |
| 89 | json_path = os.path.join(fwtc_dir, platform + '.json') |
| 90 | with open(json_path) as json_file: |
| 91 | j = json.load(json_file, object_pairs_hook=collections.OrderedDict) |
| 92 | consolidated[platform] = j |
| 93 | return consolidated |
| 94 | |
| 95 | |
| 96 | def write_output(consolidated_json, output_path): |
| 97 | """Write consolidated JSON to a read-only file. |
| 98 | |
| 99 | Args: |
| 100 | consolidated_json: Dict containing contents to write as JSON. |
| 101 | output_path: The destination of the JSON. |
| 102 | """ |
| 103 | if os.path.isfile(output_path): |
| 104 | os.remove(output_path) |
| 105 | with open(output_path, 'w') as output_file: |
Greg Edelston | 0ed40c8 | 2020-11-01 11:53:37 -0700 | [diff] [blame] | 106 | json.dump(consolidated_json, output_file, indent='\t') |
Greg Edelston | fa64921 | 2020-10-13 14:40:38 -0600 | [diff] [blame] | 107 | os.chmod(output_path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) |
| 108 | |
| 109 | |
| 110 | def main(argv=None): |
| 111 | """Load JSON from platform files, and write to output file. |
| 112 | |
| 113 | Args: |
| 114 | argv: List of command-line args, excluding the invoked script. |
| 115 | Typically, this should be set to sys.argv[1:]. |
| 116 | """ |
| 117 | args = parse_args(argv) |
| 118 | platforms = get_platform_names(args.input_dir) |
| 119 | consolidated_json = load_json(args.input_dir, platforms) |
| 120 | write_output(consolidated_json, args.output) |
| 121 | |
| 122 | |
| 123 | if __name__ == '__main__': |
| 124 | main(sys.argv[1:]) |