15f9996aaSopenharmony_ci#!/usr/bin/env python3 25f9996aaSopenharmony_ci# -*- coding: utf-8 -*- 35f9996aaSopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport os 175f9996aaSopenharmony_ciimport json 185f9996aaSopenharmony_ciimport sys 195f9996aaSopenharmony_ciimport argparse 205f9996aaSopenharmony_cifrom pyecharts import options as opts 215f9996aaSopenharmony_cifrom pyecharts.charts import Tree 225f9996aaSopenharmony_cifrom pyecharts.globals import CurrentConfig 235f9996aaSopenharmony_ci 245f9996aaSopenharmony_ci 255f9996aaSopenharmony_cidef read_json_file(input_file: str): 265f9996aaSopenharmony_ci if not os.path.exists(input_file): 275f9996aaSopenharmony_ci print("file '{}' doesn't exist.".format(input_file)) 285f9996aaSopenharmony_ci return None 295f9996aaSopenharmony_ci 305f9996aaSopenharmony_ci data = None 315f9996aaSopenharmony_ci try: 325f9996aaSopenharmony_ci with open(input_file, 'r') as input_f: 335f9996aaSopenharmony_ci data = json.load(input_f) 345f9996aaSopenharmony_ci except json.decoder.JSONDecodeError: 355f9996aaSopenharmony_ci print("The file '{}' format is incorrect.".format(input_file)) 365f9996aaSopenharmony_ci raise 375f9996aaSopenharmony_ci return data 385f9996aaSopenharmony_ci 395f9996aaSopenharmony_ci 405f9996aaSopenharmony_ciclass ModuleTree: 415f9996aaSopenharmony_ci def __init__(self, data, inner_kits_adapter): 425f9996aaSopenharmony_ci self.data = data 435f9996aaSopenharmony_ci self.inner_kits_adapter = inner_kits_adapter 445f9996aaSopenharmony_ci self.isroot = True 455f9996aaSopenharmony_ci self.module_count = {} 465f9996aaSopenharmony_ci 475f9996aaSopenharmony_ci def parse_part_module_name(self, node_name: str): 485f9996aaSopenharmony_ci split_result = node_name.split(':') 495f9996aaSopenharmony_ci part_name = split_result[0] 505f9996aaSopenharmony_ci module_name = split_result[1] 515f9996aaSopenharmony_ci return part_name, module_name 525f9996aaSopenharmony_ci 535f9996aaSopenharmony_ci def get_label_color(self, node_name: str): 545f9996aaSopenharmony_ci if self.module_count.get(node_name, 'no_module') == 'no_module': 555f9996aaSopenharmony_ci self.module_count[node_name] = 1 565f9996aaSopenharmony_ci label_opt = opts.LabelOpts(color='#000000', 575f9996aaSopenharmony_ci font_style='normal', 585f9996aaSopenharmony_ci font_family='Times New Roman', 595f9996aaSopenharmony_ci font_size=16) 605f9996aaSopenharmony_ci else: 615f9996aaSopenharmony_ci self.module_count[node_name] += 1 625f9996aaSopenharmony_ci label_opt = opts.LabelOpts(color='#ff0000', 635f9996aaSopenharmony_ci font_style='normal', 645f9996aaSopenharmony_ci font_family='Times New Roman', 655f9996aaSopenharmony_ci font_size=16) 665f9996aaSopenharmony_ci return label_opt 675f9996aaSopenharmony_ci 685f9996aaSopenharmony_ci def node_tree(self, node_name: str): 695f9996aaSopenharmony_ci if node_name not in self.data: 705f9996aaSopenharmony_ci part_name, module_name = self.parse_part_module_name(node_name) 715f9996aaSopenharmony_ci new_part_name = self.inner_kits_adapter.get( 725f9996aaSopenharmony_ci part_name, "no_adapter") 735f9996aaSopenharmony_ci old_node_name = node_name 745f9996aaSopenharmony_ci if new_part_name != "no_adapter": 755f9996aaSopenharmony_ci node_name = "{}:{}".format(new_part_name, module_name) 765f9996aaSopenharmony_ci if node_name not in self.data: 775f9996aaSopenharmony_ci if self.isroot: 785f9996aaSopenharmony_ci raise Exception( 795f9996aaSopenharmony_ci "module '{}' doesn't exist.".format(old_node_name)) 805f9996aaSopenharmony_ci else: 815f9996aaSopenharmony_ci print("Warning! module '{}' doesn't exist.".format( 825f9996aaSopenharmony_ci old_node_name)) 835f9996aaSopenharmony_ci tree_data = {"name": node_name} 845f9996aaSopenharmony_ci return tree_data 855f9996aaSopenharmony_ci 865f9996aaSopenharmony_ci self.isroot = False 875f9996aaSopenharmony_ci module_deps = self.data.get(node_name) 885f9996aaSopenharmony_ci if len(module_deps) > 0: 895f9996aaSopenharmony_ci children = [] 905f9996aaSopenharmony_ci for module_dep in module_deps: 915f9996aaSopenharmony_ci children.append(self.node_tree(module_dep)) 925f9996aaSopenharmony_ci tree_data = {"name": node_name, "children": children} 935f9996aaSopenharmony_ci else: 945f9996aaSopenharmony_ci tree_data = {"name": node_name} 955f9996aaSopenharmony_ci return tree_data 965f9996aaSopenharmony_ci 975f9996aaSopenharmony_ci def color_tree(self, tree_data: dict): 985f9996aaSopenharmony_ci color_tree_data = {} 995f9996aaSopenharmony_ci queue = [tree_data] 1005f9996aaSopenharmony_ci while len(queue) > 0: 1015f9996aaSopenharmony_ci node = queue.pop(0) 1025f9996aaSopenharmony_ci label_opt = self.get_label_color(node["name"]) 1035f9996aaSopenharmony_ci node["label_opt"] = label_opt 1045f9996aaSopenharmony_ci children = node.get("children", "no_children") 1055f9996aaSopenharmony_ci if children != "no_children": 1065f9996aaSopenharmony_ci queue.extend(children) 1075f9996aaSopenharmony_ci return tree_data 1085f9996aaSopenharmony_ci 1095f9996aaSopenharmony_ci def graph_tree(self, tree_data: dict): 1105f9996aaSopenharmony_ci children = tree_data.get("children", "no_children") 1115f9996aaSopenharmony_ci if children != "no_children": 1125f9996aaSopenharmony_ci for index, value in enumerate(children): 1135f9996aaSopenharmony_ci children[index] = self.graph_tree(children[index]) 1145f9996aaSopenharmony_ci return opts.TreeItem(name=tree_data["name"], 1155f9996aaSopenharmony_ci label_opts=tree_data["label_opt"], 1165f9996aaSopenharmony_ci children=children) 1175f9996aaSopenharmony_ci else: 1185f9996aaSopenharmony_ci return opts.TreeItem(name=tree_data["name"], 1195f9996aaSopenharmony_ci label_opts=tree_data["label_opt"]) 1205f9996aaSopenharmony_ci 1215f9996aaSopenharmony_ci def get_node_tree(self, node_name: str): 1225f9996aaSopenharmony_ci self.isroot = True 1235f9996aaSopenharmony_ci tree_data = self.node_tree(node_name) 1245f9996aaSopenharmony_ci self.module_count = {} 1255f9996aaSopenharmony_ci tree_data = self.color_tree(tree_data) 1265f9996aaSopenharmony_ci tree = self.graph_tree(tree_data) 1275f9996aaSopenharmony_ci return tree 1285f9996aaSopenharmony_ci 1295f9996aaSopenharmony_ci 1305f9996aaSopenharmony_cidef main(argv): 1315f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 1325f9996aaSopenharmony_ci parser.add_argument('--module-name', required=True) 1335f9996aaSopenharmony_ci parser.add_argument('--module-deps-file', required=True) 1345f9996aaSopenharmony_ci args = parser.parse_args(argv) 1355f9996aaSopenharmony_ci 1365f9996aaSopenharmony_ci node_name = args.module_name 1375f9996aaSopenharmony_ci inner_kits_adapter_file = os.path.join( 1385f9996aaSopenharmony_ci os.path.dirname( 1395f9996aaSopenharmony_ci os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 1405f9996aaSopenharmony_ci "ohos", "inner_kits_adapter.json") 1415f9996aaSopenharmony_ci output_file = os.path.join(os.path.dirname(args.module_deps_file), 1425f9996aaSopenharmony_ci "{}.html".format(node_name.replace(":", "__"))) 1435f9996aaSopenharmony_ci tree_title = "{} module dependency tree".format(node_name) 1445f9996aaSopenharmony_ci CurrentConfig.ONLINE_HOST = ("https://cdn.jsdelivr.net/npm/" 1455f9996aaSopenharmony_ci "echarts@latest/dist/") 1465f9996aaSopenharmony_ci 1475f9996aaSopenharmony_ci print("------Generate module dependency tree------") 1485f9996aaSopenharmony_ci module_deps = read_json_file(args.module_deps_file) 1495f9996aaSopenharmony_ci inner_kits_adapter = read_json_file(inner_kits_adapter_file) 1505f9996aaSopenharmony_ci 1515f9996aaSopenharmony_ci module_tree_ = ModuleTree(module_deps, inner_kits_adapter) 1525f9996aaSopenharmony_ci tree_data = module_tree_.get_node_tree(node_name) 1535f9996aaSopenharmony_ci 1545f9996aaSopenharmony_ci tree = (Tree(opts.InitOpts(width="1920px", height="1080px")).add( 1555f9996aaSopenharmony_ci "", [tree_data], 1565f9996aaSopenharmony_ci orient="LR", 1575f9996aaSopenharmony_ci initial_tree_depth=1, 1585f9996aaSopenharmony_ci is_roam=True, 1595f9996aaSopenharmony_ci symbol_size=10).set_global_opts(title_opts=opts.TitleOpts( 1605f9996aaSopenharmony_ci title=tree_title)).render(output_file)) 1615f9996aaSopenharmony_ci print('module deps tree output to {}'.format(output_file)) 1625f9996aaSopenharmony_ci return 0 1635f9996aaSopenharmony_ci 1645f9996aaSopenharmony_ci 1655f9996aaSopenharmony_ciif __name__ == '__main__': 1665f9996aaSopenharmony_ci sys.exit(main(sys.argv[1:])) 167