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 os 17import json 18import sys 19import argparse 20from pyecharts import options as opts 21from pyecharts.charts import Tree 22from pyecharts.globals import CurrentConfig 23 24 25def read_json_file(input_file): 26 if not os.path.exists(input_file): 27 print("file '{}' doesn't exist.".format(input_file)) 28 return None 29 30 data = None 31 try: 32 with open(input_file, 'r') as input_f: 33 data = json.load(input_f) 34 except json.decoder.JSONDecodeError: 35 print("The file '{}' format is incorrect.".format(input_file)) 36 raise 37 return data 38 39 40class ModuleTree: 41 def __init__(self, data, inner_kits_adapter): 42 self.data = data 43 self.inner_kits_adapter = inner_kits_adapter 44 self.isroot = True 45 self.module_count = {} 46 47 def parse_part_module_name(self, node_name): 48 split_result = node_name.split(':') 49 part_name = split_result[0] 50 module_name = split_result[1] 51 return part_name, module_name 52 53 def get_label_color(self, node_name): 54 if self.module_count.get(node_name, 'no_module') == 'no_module': 55 self.module_count[node_name] = 1 56 label_opt = opts.LabelOpts(color='#000000', 57 font_style='normal', 58 font_family='Times New Roman', 59 font_size=16) 60 else: 61 self.module_count[node_name] += 1 62 label_opt = opts.LabelOpts(color='#ff0000', 63 font_style='normal', 64 font_family='Times New Roman', 65 font_size=16) 66 return label_opt 67 68 def node_tree(self, node_name): 69 if node_name not in self.data: 70 part_name, module_name = self.parse_part_module_name(node_name) 71 new_part_name = self.inner_kits_adapter.get( 72 part_name, "no_adapter") 73 old_node_name = node_name 74 if new_part_name != "no_adapter": 75 node_name = "{}:{}".format(new_part_name, module_name) 76 if node_name not in self.data: 77 if self.isroot: 78 raise Exception( 79 "module '{}' doesn't exist.".format(old_node_name)) 80 else: 81 print("Warning! module '{}' doesn't exist.".format( 82 old_node_name)) 83 tree_data = {"name": node_name} 84 return tree_data 85 86 self.isroot = False 87 module_deps = self.data.get(node_name) 88 if len(module_deps) > 0: 89 children = [] 90 for module_dep in module_deps: 91 children.append(self.node_tree(module_dep)) 92 tree_data = {"name": node_name, "children": children} 93 else: 94 tree_data = {"name": node_name} 95 return tree_data 96 97 def color_tree(self, tree_data): 98 color_tree_data = {} 99 queue = [tree_data] 100 while len(queue) > 0: 101 node = queue.pop(0) 102 label_opt = self.get_label_color(node["name"]) 103 node["label_opt"] = label_opt 104 children = node.get("children", "no_children") 105 if children != "no_children": 106 queue.extend(children) 107 return tree_data 108 109 def graph_tree(self, tree_data): 110 children = tree_data.get("children", "no_children") 111 if children != "no_children": 112 for index, value in enumerate(children): 113 children[index] = self.graph_tree(children[index]) 114 return opts.TreeItem(name=tree_data["name"], 115 label_opts=tree_data["label_opt"], 116 children=children) 117 else: 118 return opts.TreeItem(name=tree_data["name"], 119 label_opts=tree_data["label_opt"]) 120 121 def get_node_tree(self, node_name): 122 self.isroot = True 123 tree_data = self.node_tree(node_name) 124 self.module_count = {} 125 tree_data = self.color_tree(tree_data) 126 tree = self.graph_tree(tree_data) 127 return tree 128 129 130def main(argv): 131 parser = argparse.ArgumentParser() 132 parser.add_argument('--module-name', required=True) 133 parser.add_argument('--module-deps-file', required=True) 134 args = parser.parse_args(argv) 135 136 node_name = args.module_name 137 inner_kits_adapter_file = os.path.join( 138 os.path.dirname( 139 os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 140 "ohos", "inner_kits_adapter.json") 141 output_file = os.path.join(os.path.dirname(args.module_deps_file), 142 "{}.html".format(node_name.replace(":", "__"))) 143 tree_title = "{} module dependency tree".format(node_name) 144 CurrentConfig.ONLINE_HOST = ("https://cdn.jsdelivr.net/npm/" 145 "echarts@latest/dist/") 146 147 print("------Generate module dependency tree------") 148 module_deps = read_json_file(args.module_deps_file) 149 inner_kits_adapter = read_json_file(inner_kits_adapter_file) 150 151 module_tree_ = ModuleTree(module_deps, inner_kits_adapter) 152 tree_data = module_tree_.get_node_tree(node_name) 153 154 tree = (Tree(opts.InitOpts(width="1920px", height="1080px")).add( 155 "", [tree_data], 156 orient="LR", 157 initial_tree_depth=1, 158 is_roam=True, 159 symbol_size=10).set_global_opts(title_opts=opts.TitleOpts( 160 title=tree_title)).render(output_file)) 161 print('module deps tree output to {}'.format(output_file)) 162 return 0 163 164 165if __name__ == '__main__': 166 sys.exit(main(sys.argv[1:])) 167