1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys 17import os 18import argparse 19 20import file_utils 21import dependence_analysis 22 23 24def gen_part_dependence(deps_data: dict): 25 part_allowlist = ['unittest', 'moduletest', 'systemtest'] 26 label_to_alias = {} 27 for _module_alias, _info in deps_data.items(): 28 _module_label = _info.get('module_label').split('(')[0] 29 label_to_alias[_module_label] = _module_alias 30 31 part_deps_data = {} 32 for _module_alias, _info in deps_data.items(): 33 deps_part_list = [] 34 _part_name = _info.get('part_name') 35 if _part_name in part_allowlist: 36 continue 37 _deps_label_list = _info.get('deps') 38 for _deps_label in _deps_label_list: 39 _alias = label_to_alias.get(_deps_label) 40 if _alias is None: 41 continue 42 _dep_part_name = _alias.split(':')[0] 43 if _dep_part_name == _part_name: 44 continue 45 deps_part_list.append(_dep_part_name) 46 _external_deps_list = _info.get('external_deps') 47 for _ext_deps in _external_deps_list: 48 _dep_part_name = _ext_deps.split(':')[0] 49 if _dep_part_name == _part_name: 50 continue 51 deps_part_list.append(_dep_part_name) 52 53 deps_value = part_deps_data.get(_part_name, []) 54 deps_value.extend(deps_part_list) 55 part_deps_data[_part_name] = list(set(deps_value)) 56 return part_deps_data 57 58 59def _drawing_part_deps(part_deps_data: dict, output_path: str): 60 from pyecharts.charts import Graph 61 from pyecharts import options as opts 62 from pyecharts.globals import CurrentConfig 63 64 CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm"\ 65 "/echarts@latest/dist/" 66 67 part_allowlist = ['unittest', 'moduletest', 'systemtest'] 68 part_nodes = [] 69 parts_links = [] 70 nodes_sets = set() 71 for _part_name, _dep_parts in part_deps_data.items(): 72 if _part_name in part_allowlist: 73 continue 74 if _part_name not in nodes_sets: 75 nodes_sets.add(_part_name) 76 part_nodes.append(opts.GraphNode( 77 name=_part_name, 78 symbol='circle', 79 symbol_size=20, 80 label_opts=opts.LabelOpts( 81 font_style='normal', 82 font_family='Times New Roman', 83 font_size=16 84 ) 85 )) 86 for _dep_part in _dep_parts: 87 if _part_name in part_deps_data.get(_dep_part, []): 88 parts_links.append(opts.GraphLink( 89 source=_part_name, 90 target=_dep_part, 91 linestyle_opts=opts.LineStyleOpts( 92 color='#ff0000', width=0.5) 93 )) 94 else: 95 parts_links.append(opts.GraphLink( 96 source=_part_name, 97 target=_dep_part, 98 linestyle_opts=opts.LineStyleOpts( 99 color='#000000', width=0.5) 100 )) 101 _output_graph_file = os.path.join(output_path, 'part-deps-grahp.html') 102 graph = ( 103 Graph(opts.InitOpts(width="1920px", height="1080px")) 104 .add( 105 "", 106 part_nodes, 107 parts_links, 108 repulsion=800, 109 edge_symbol=['', 'arrow'], 110 edge_symbol_size=6 111 ) 112 .set_global_opts(title_opts=opts.TitleOpts(title="part-deps-grahp")) 113 .render(_output_graph_file) 114 ) 115 116 117def run(deps_files_path: str, output_path: str, is_graph: bool): 118 all_deps_data = dependence_analysis.get_all_deps_data(deps_files_path) 119 all_deps_data_file = os.path.join(output_path, 'all_deps_data.json') 120 file_utils.write_json_file(all_deps_data_file, all_deps_data) 121 122 part_deps_data = gen_part_dependence(all_deps_data) 123 part_deps_data_file = os.path.join(output_path, 'part_deps_info.json') 124 file_utils.write_json_file(part_deps_data_file, part_deps_data) 125 if is_graph: 126 _drawing_part_deps(part_deps_data, output_path) 127 128 129def main(argv): 130 parser = argparse.ArgumentParser() 131 parser.add_argument('--deps-files-path', required=True) 132 parser.add_argument('--graph', action='store_true') 133 parser.set_defaults(graph=False) 134 args = parser.parse_args(argv) 135 136 if not os.path.exists(args.deps_files_path): 137 raise Exception("'{}' doesn't exist.".format(args.deps_files_path)) 138 output_path = os.path.join(os.path.dirname( 139 args.deps_files_path), 'part_deps_info') 140 print("------Generate part dependency info------") 141 run(args.deps_files_path, output_path, args.graph) 142 print('part deps data output to {}'.format(output_path)) 143 144 145if __name__ == '__main__': 146 sys.exit(main(sys.argv[1:])) 147