1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2015 gRPC authors. 3*cc02d7e2SAndroid Build Coastguard Worker# 4*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*cc02d7e2SAndroid Build Coastguard Worker# 8*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*cc02d7e2SAndroid Build Coastguard Worker# 10*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 15*cc02d7e2SAndroid Build Coastguard Worker 16*cc02d7e2SAndroid Build Coastguard Worker# produces cleaner build.yaml files 17*cc02d7e2SAndroid Build Coastguard Worker 18*cc02d7e2SAndroid Build Coastguard Workerimport collections 19*cc02d7e2SAndroid Build Coastguard Workerimport os 20*cc02d7e2SAndroid Build Coastguard Workerimport sys 21*cc02d7e2SAndroid Build Coastguard Worker 22*cc02d7e2SAndroid Build Coastguard Workerimport yaml 23*cc02d7e2SAndroid Build Coastguard Worker 24*cc02d7e2SAndroid Build Coastguard WorkerTEST = os.environ.get("TEST", "false") == "true" 25*cc02d7e2SAndroid Build Coastguard Worker 26*cc02d7e2SAndroid Build Coastguard Worker_TOP_LEVEL_KEYS = [ 27*cc02d7e2SAndroid Build Coastguard Worker "settings", 28*cc02d7e2SAndroid Build Coastguard Worker "proto_deps", 29*cc02d7e2SAndroid Build Coastguard Worker "filegroups", 30*cc02d7e2SAndroid Build Coastguard Worker "libs", 31*cc02d7e2SAndroid Build Coastguard Worker "targets", 32*cc02d7e2SAndroid Build Coastguard Worker "vspackages", 33*cc02d7e2SAndroid Build Coastguard Worker] 34*cc02d7e2SAndroid Build Coastguard Worker_ELEM_KEYS = [ 35*cc02d7e2SAndroid Build Coastguard Worker "name", 36*cc02d7e2SAndroid Build Coastguard Worker "gtest", 37*cc02d7e2SAndroid Build Coastguard Worker "cpu_cost", 38*cc02d7e2SAndroid Build Coastguard Worker "flaky", 39*cc02d7e2SAndroid Build Coastguard Worker "build", 40*cc02d7e2SAndroid Build Coastguard Worker "run", 41*cc02d7e2SAndroid Build Coastguard Worker "language", 42*cc02d7e2SAndroid Build Coastguard Worker "plugin_option", 43*cc02d7e2SAndroid Build Coastguard Worker "public_headers", 44*cc02d7e2SAndroid Build Coastguard Worker "headers", 45*cc02d7e2SAndroid Build Coastguard Worker "src", 46*cc02d7e2SAndroid Build Coastguard Worker "deps", 47*cc02d7e2SAndroid Build Coastguard Worker] 48*cc02d7e2SAndroid Build Coastguard Worker 49*cc02d7e2SAndroid Build Coastguard Worker 50*cc02d7e2SAndroid Build Coastguard Workerdef repr_ordered_dict(dumper, odict): 51*cc02d7e2SAndroid Build Coastguard Worker return dumper.represent_mapping( 52*cc02d7e2SAndroid Build Coastguard Worker "tag:yaml.org,2002:map", list(odict.items()) 53*cc02d7e2SAndroid Build Coastguard Worker ) 54*cc02d7e2SAndroid Build Coastguard Worker 55*cc02d7e2SAndroid Build Coastguard Worker 56*cc02d7e2SAndroid Build Coastguard Workeryaml.add_representer(collections.OrderedDict, repr_ordered_dict) 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard Worker 59*cc02d7e2SAndroid Build Coastguard Workerdef _rebuild_as_ordered_dict(indict, special_keys): 60*cc02d7e2SAndroid Build Coastguard Worker outdict = collections.OrderedDict() 61*cc02d7e2SAndroid Build Coastguard Worker for key in sorted(indict.keys()): 62*cc02d7e2SAndroid Build Coastguard Worker if "#" in key: 63*cc02d7e2SAndroid Build Coastguard Worker outdict[key] = indict[key] 64*cc02d7e2SAndroid Build Coastguard Worker for key in special_keys: 65*cc02d7e2SAndroid Build Coastguard Worker if key in indict: 66*cc02d7e2SAndroid Build Coastguard Worker outdict[key] = indict[key] 67*cc02d7e2SAndroid Build Coastguard Worker for key in sorted(indict.keys()): 68*cc02d7e2SAndroid Build Coastguard Worker if key in special_keys: 69*cc02d7e2SAndroid Build Coastguard Worker continue 70*cc02d7e2SAndroid Build Coastguard Worker if "#" in key: 71*cc02d7e2SAndroid Build Coastguard Worker continue 72*cc02d7e2SAndroid Build Coastguard Worker outdict[key] = indict[key] 73*cc02d7e2SAndroid Build Coastguard Worker return outdict 74*cc02d7e2SAndroid Build Coastguard Worker 75*cc02d7e2SAndroid Build Coastguard Worker 76*cc02d7e2SAndroid Build Coastguard Workerdef _clean_elem(indict): 77*cc02d7e2SAndroid Build Coastguard Worker for name in ["public_headers", "headers", "src"]: 78*cc02d7e2SAndroid Build Coastguard Worker if name not in indict: 79*cc02d7e2SAndroid Build Coastguard Worker continue 80*cc02d7e2SAndroid Build Coastguard Worker inlist = indict[name] 81*cc02d7e2SAndroid Build Coastguard Worker protos = list(x for x in inlist if os.path.splitext(x)[1] == ".proto") 82*cc02d7e2SAndroid Build Coastguard Worker others = set(x for x in inlist if x not in protos) 83*cc02d7e2SAndroid Build Coastguard Worker indict[name] = protos + sorted(others) 84*cc02d7e2SAndroid Build Coastguard Worker return _rebuild_as_ordered_dict(indict, _ELEM_KEYS) 85*cc02d7e2SAndroid Build Coastguard Worker 86*cc02d7e2SAndroid Build Coastguard Worker 87*cc02d7e2SAndroid Build Coastguard Workerdef cleaned_build_yaml_dict_as_string(indict): 88*cc02d7e2SAndroid Build Coastguard Worker """Takes dictionary which represents yaml file and returns the cleaned-up yaml string""" 89*cc02d7e2SAndroid Build Coastguard Worker js = _rebuild_as_ordered_dict(indict, _TOP_LEVEL_KEYS) 90*cc02d7e2SAndroid Build Coastguard Worker for grp in ["filegroups", "libs", "targets"]: 91*cc02d7e2SAndroid Build Coastguard Worker if grp not in js: 92*cc02d7e2SAndroid Build Coastguard Worker continue 93*cc02d7e2SAndroid Build Coastguard Worker js[grp] = sorted( 94*cc02d7e2SAndroid Build Coastguard Worker [_clean_elem(x) for x in js[grp]], 95*cc02d7e2SAndroid Build Coastguard Worker key=lambda x: (x.get("language", "_"), x["name"]), 96*cc02d7e2SAndroid Build Coastguard Worker ) 97*cc02d7e2SAndroid Build Coastguard Worker output = yaml.dump(js, indent=2, width=80, default_flow_style=False) 98*cc02d7e2SAndroid Build Coastguard Worker # massage out trailing whitespace 99*cc02d7e2SAndroid Build Coastguard Worker lines = [] 100*cc02d7e2SAndroid Build Coastguard Worker for line in output.splitlines(): 101*cc02d7e2SAndroid Build Coastguard Worker lines.append(line.rstrip() + "\n") 102*cc02d7e2SAndroid Build Coastguard Worker output = "".join(lines) 103*cc02d7e2SAndroid Build Coastguard Worker return output 104*cc02d7e2SAndroid Build Coastguard Worker 105*cc02d7e2SAndroid Build Coastguard Worker 106*cc02d7e2SAndroid Build Coastguard Workerif __name__ == "__main__": 107*cc02d7e2SAndroid Build Coastguard Worker for filename in sys.argv[1:]: 108*cc02d7e2SAndroid Build Coastguard Worker with open(filename) as f: 109*cc02d7e2SAndroid Build Coastguard Worker js = yaml.safe_load(f) 110*cc02d7e2SAndroid Build Coastguard Worker output = cleaned_build_yaml_dict_as_string(js) 111*cc02d7e2SAndroid Build Coastguard Worker if TEST: 112*cc02d7e2SAndroid Build Coastguard Worker with open(filename) as f: 113*cc02d7e2SAndroid Build Coastguard Worker if not f.read() == output: 114*cc02d7e2SAndroid Build Coastguard Worker raise Exception( 115*cc02d7e2SAndroid Build Coastguard Worker "Looks like build-cleaner.py has not been run for file" 116*cc02d7e2SAndroid Build Coastguard Worker ' "%s"?' % filename 117*cc02d7e2SAndroid Build Coastguard Worker ) 118*cc02d7e2SAndroid Build Coastguard Worker else: 119*cc02d7e2SAndroid Build Coastguard Worker with open(filename, "w") as f: 120*cc02d7e2SAndroid Build Coastguard Worker f.write(output) 121