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 sys
175f9996aaSopenharmony_ciimport os
185f9996aaSopenharmony_ciimport argparse
195f9996aaSopenharmony_ci
205f9996aaSopenharmony_ciimport file_utils
215f9996aaSopenharmony_ciimport dependence_analysis
225f9996aaSopenharmony_ci
235f9996aaSopenharmony_ci
245f9996aaSopenharmony_cidef gen_part_dependence(deps_data: dict):
255f9996aaSopenharmony_ci    part_allowlist = ['unittest', 'moduletest', 'systemtest']
265f9996aaSopenharmony_ci    label_to_alias = {}
275f9996aaSopenharmony_ci    for _module_alias, _info in deps_data.items():
285f9996aaSopenharmony_ci        _module_label = _info.get('module_label').split('(')[0]
295f9996aaSopenharmony_ci        label_to_alias[_module_label] = _module_alias
305f9996aaSopenharmony_ci
315f9996aaSopenharmony_ci    part_deps_data = {}
325f9996aaSopenharmony_ci    for _module_alias, _info in deps_data.items():
335f9996aaSopenharmony_ci        deps_part_list = []
345f9996aaSopenharmony_ci        _part_name = _info.get('part_name')
355f9996aaSopenharmony_ci        if _part_name in part_allowlist:
365f9996aaSopenharmony_ci            continue
375f9996aaSopenharmony_ci        _deps_label_list = _info.get('deps')
385f9996aaSopenharmony_ci        for _deps_label in _deps_label_list:
395f9996aaSopenharmony_ci            _alias = label_to_alias.get(_deps_label)
405f9996aaSopenharmony_ci            if _alias is None:
415f9996aaSopenharmony_ci                continue
425f9996aaSopenharmony_ci            _dep_part_name = _alias.split(':')[0]
435f9996aaSopenharmony_ci            if _dep_part_name == _part_name:
445f9996aaSopenharmony_ci                continue
455f9996aaSopenharmony_ci            deps_part_list.append(_dep_part_name)
465f9996aaSopenharmony_ci        _external_deps_list = _info.get('external_deps')
475f9996aaSopenharmony_ci        for _ext_deps in _external_deps_list:
485f9996aaSopenharmony_ci            _dep_part_name = _ext_deps.split(':')[0]
495f9996aaSopenharmony_ci            if _dep_part_name == _part_name:
505f9996aaSopenharmony_ci                continue
515f9996aaSopenharmony_ci            deps_part_list.append(_dep_part_name)
525f9996aaSopenharmony_ci
535f9996aaSopenharmony_ci        deps_value = part_deps_data.get(_part_name, [])
545f9996aaSopenharmony_ci        deps_value.extend(deps_part_list)
555f9996aaSopenharmony_ci        part_deps_data[_part_name] = list(set(deps_value))
565f9996aaSopenharmony_ci    return part_deps_data
575f9996aaSopenharmony_ci
585f9996aaSopenharmony_ci
595f9996aaSopenharmony_cidef _drawing_part_deps(part_deps_data: dict, output_path: str):
605f9996aaSopenharmony_ci    from pyecharts.charts import Graph
615f9996aaSopenharmony_ci    from pyecharts import options as opts
625f9996aaSopenharmony_ci    from pyecharts.globals import CurrentConfig
635f9996aaSopenharmony_ci
645f9996aaSopenharmony_ci    CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm"\
655f9996aaSopenharmony_ci                                "/echarts@latest/dist/"
665f9996aaSopenharmony_ci
675f9996aaSopenharmony_ci    part_allowlist = ['unittest', 'moduletest', 'systemtest']
685f9996aaSopenharmony_ci    part_nodes = []
695f9996aaSopenharmony_ci    parts_links = []
705f9996aaSopenharmony_ci    nodes_sets = set()
715f9996aaSopenharmony_ci    for _part_name, _dep_parts in part_deps_data.items():
725f9996aaSopenharmony_ci        if _part_name in part_allowlist:
735f9996aaSopenharmony_ci            continue
745f9996aaSopenharmony_ci        if _part_name not in nodes_sets:
755f9996aaSopenharmony_ci            nodes_sets.add(_part_name)
765f9996aaSopenharmony_ci            part_nodes.append(opts.GraphNode(
775f9996aaSopenharmony_ci                name=_part_name,
785f9996aaSopenharmony_ci                symbol='circle',
795f9996aaSopenharmony_ci                symbol_size=20,
805f9996aaSopenharmony_ci                label_opts=opts.LabelOpts(
815f9996aaSopenharmony_ci                    font_style='normal',
825f9996aaSopenharmony_ci                    font_family='Times New Roman',
835f9996aaSopenharmony_ci                    font_size=16
845f9996aaSopenharmony_ci                )
855f9996aaSopenharmony_ci            ))
865f9996aaSopenharmony_ci        for _dep_part in _dep_parts:
875f9996aaSopenharmony_ci            if _part_name in part_deps_data.get(_dep_part, []):
885f9996aaSopenharmony_ci                parts_links.append(opts.GraphLink(
895f9996aaSopenharmony_ci                    source=_part_name,
905f9996aaSopenharmony_ci                    target=_dep_part,
915f9996aaSopenharmony_ci                    linestyle_opts=opts.LineStyleOpts(
925f9996aaSopenharmony_ci                        color='#ff0000', width=0.5)
935f9996aaSopenharmony_ci                ))
945f9996aaSopenharmony_ci            else:
955f9996aaSopenharmony_ci                parts_links.append(opts.GraphLink(
965f9996aaSopenharmony_ci                    source=_part_name,
975f9996aaSopenharmony_ci                    target=_dep_part,
985f9996aaSopenharmony_ci                    linestyle_opts=opts.LineStyleOpts(
995f9996aaSopenharmony_ci                        color='#000000', width=0.5)
1005f9996aaSopenharmony_ci                ))
1015f9996aaSopenharmony_ci    _output_graph_file = os.path.join(output_path, 'part-deps-grahp.html')
1025f9996aaSopenharmony_ci    graph = (
1035f9996aaSopenharmony_ci        Graph(opts.InitOpts(width="1920px", height="1080px"))
1045f9996aaSopenharmony_ci        .add(
1055f9996aaSopenharmony_ci            "",
1065f9996aaSopenharmony_ci            part_nodes,
1075f9996aaSopenharmony_ci            parts_links,
1085f9996aaSopenharmony_ci            repulsion=800,
1095f9996aaSopenharmony_ci            edge_symbol=['', 'arrow'],
1105f9996aaSopenharmony_ci            edge_symbol_size=6
1115f9996aaSopenharmony_ci        )
1125f9996aaSopenharmony_ci        .set_global_opts(title_opts=opts.TitleOpts(title="part-deps-grahp"))
1135f9996aaSopenharmony_ci        .render(_output_graph_file)
1145f9996aaSopenharmony_ci    )
1155f9996aaSopenharmony_ci
1165f9996aaSopenharmony_ci
1175f9996aaSopenharmony_cidef run(deps_files_path: str, output_path: str, is_graph: bool):
1185f9996aaSopenharmony_ci    all_deps_data = dependence_analysis.get_all_deps_data(deps_files_path)
1195f9996aaSopenharmony_ci    all_deps_data_file = os.path.join(output_path, 'all_deps_data.json')
1205f9996aaSopenharmony_ci    file_utils.write_json_file(all_deps_data_file, all_deps_data)
1215f9996aaSopenharmony_ci
1225f9996aaSopenharmony_ci    part_deps_data = gen_part_dependence(all_deps_data)
1235f9996aaSopenharmony_ci    part_deps_data_file = os.path.join(output_path, 'part_deps_info.json')
1245f9996aaSopenharmony_ci    file_utils.write_json_file(part_deps_data_file, part_deps_data)
1255f9996aaSopenharmony_ci    if is_graph:
1265f9996aaSopenharmony_ci        _drawing_part_deps(part_deps_data, output_path)
1275f9996aaSopenharmony_ci
1285f9996aaSopenharmony_ci
1295f9996aaSopenharmony_cidef main(argv):
1305f9996aaSopenharmony_ci    parser = argparse.ArgumentParser()
1315f9996aaSopenharmony_ci    parser.add_argument('--deps-files-path', required=True)
1325f9996aaSopenharmony_ci    parser.add_argument('--graph', action='store_true')
1335f9996aaSopenharmony_ci    parser.set_defaults(graph=False)
1345f9996aaSopenharmony_ci    args = parser.parse_args(argv)
1355f9996aaSopenharmony_ci
1365f9996aaSopenharmony_ci    if not os.path.exists(args.deps_files_path):
1375f9996aaSopenharmony_ci        raise Exception("'{}' doesn't exist.".format(args.deps_files_path))
1385f9996aaSopenharmony_ci    output_path = os.path.join(os.path.dirname(
1395f9996aaSopenharmony_ci        args.deps_files_path.replace('deps_files', '')), 'part_deps_info')
1405f9996aaSopenharmony_ci    print("------Generate part dependency info------")
1415f9996aaSopenharmony_ci    run(args.deps_files_path, output_path, args.graph)
1425f9996aaSopenharmony_ci    print('part deps data output to {}'.format(output_path))
1435f9996aaSopenharmony_ci
1445f9996aaSopenharmony_ci
1455f9996aaSopenharmony_ciif __name__ == '__main__':
1465f9996aaSopenharmony_ci    sys.exit(main(sys.argv[1:]))
147