1#!/usr/bin/env python
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#
16
17import sys
18import os
19import traceback
20
21try:
22    from configparser import ConfigParser as cfgParser
23    USE_ENCODING = True
24except ImportError:
25    from ConfigParser import ConfigParser as cfgParser
26    USE_ENCODING = False
27
28INI_LICENSE = """;
29; Copyright (c) 2021 Huawei Device Co., Ltd.
30; Licensed under the Apache License, Version 2.0 (the "License");
31; you may not use this file except in compliance with the License.
32; You may obtain a copy of the License at
33;
34;     http://www.apache.org/licenses/LICENSE-2.0
35;
36; Unless required by applicable law or agreed to in writing, software
37; distributed under the License is distributed on an "AS IS" BASIS,
38; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
39; See the License for the specific language governing permissions and
40; limitations under the License.
41;
42
43"""
44INI_CONFIG_PATH_PREFIX = "foundation/ai/"
45
46INI_CONFIG_PATH_SUFFIX = "/services/common/protocol/plugin_config" \
47                         "/plugin_config_ini"
48
49# Ini config file relative path in build folder
50OUT_INI_CONFIG_PATH = "etc/ai_engine_plugin.ini"
51# Ini config file relative path in out folder
52FAIL_CODE = -1
53PARA_NUM = 5
54BASE_SESSION = "base"
55SUPPORTED_BOARDS = "supported_boards"
56RELATED_SESSIONS = "related_sessions"
57ALL_BOARDS = "ALL"
58DELIMITER = ","
59
60
61class ConfigParserUper(cfgParser):
62    def optionxform(self, optionstr):
63        return optionstr
64
65
66def get_ini_object(config_file_path, encoding=None):
67    """
68    Get the config in ini file
69    getConfig().get("base", "userDataPath")
70    :param config_file_path:
71    :return:
72    """
73    config = ConfigParserUper()
74    if not USE_ENCODING:
75        config.read(config_file_path)
76        return config
77    all_encodings = ["gbk", "utf-8-sig", "utf-8"]
78    if encoding is None:
79        for code in all_encodings:
80            try:
81                config.read(config_file_path, encoding=code)
82                break
83            except UnicodeDecodeError as exception:
84                if code == all_encodings[-1]:
85                    print(traceback.format_exc())
86                    print(repr(exception))
87                    raise Exception("Unknown encoding(%s)" % config_file_path)
88    else:
89        config.read(config_file_path, encoding=encoding)
90    return config
91
92
93class IniManager:
94    def __init__(self):
95        pass
96
97    def get_files_in_folder(self, build_folder, plugin_list):
98        """
99        Get all ini file path
100        :return: file path list
101        """
102
103        plugin_list = plugin_list.split(',')
104        plugin_list = [plugin.strip('[]\\ "') for plugin in plugin_list]
105        plugin_list.append('engine')
106
107        ini_config_folder = [
108            INI_CONFIG_PATH_PREFIX + folder + INI_CONFIG_PATH_SUFFIX
109            for folder in plugin_list
110        ]
111        config_folder = [
112            os.path.join(build_folder, folder) for folder in ini_config_folder
113        ]
114
115        file_path_list = []
116        for path in config_folder:
117            if not os.path.isdir(path):
118                continue
119            for file_name in os.listdir(path):
120                file_path_list.append(os.path.join(path, file_name))
121        return file_path_list
122
123    def get_config_ini(self, file_path_list, board_name):
124        """
125        Generate ini file
126        :param file_path_list: Input files
127        :param board_name: Board name
128        :return: ini config object
129        """
130        cfg = ConfigParserUper()
131        for ini_file_path in file_path_list:
132            if not ini_file_path.endswith(".ini"):
133                continue
134            origin_cfg = get_ini_object(ini_file_path)
135            if not origin_cfg.has_section(BASE_SESSION):
136                continue
137            if not origin_cfg.has_option(BASE_SESSION, SUPPORTED_BOARDS) or \
138                not origin_cfg.has_option(BASE_SESSION, RELATED_SESSIONS):
139                continue
140            supported_boards = origin_cfg.get(BASE_SESSION, SUPPORTED_BOARDS)
141            related_sessions = origin_cfg.get(BASE_SESSION, RELATED_SESSIONS)
142            legal_boards = supported_boards.split(DELIMITER)
143            if board_name not in legal_boards and \
144                ALL_BOARDS not in legal_boards:
145                continue
146            for session in related_sessions.split(DELIMITER):
147                cfg.add_section(session)
148                for key in origin_cfg.options(session):
149                    val = origin_cfg.get(session, key)
150                    cfg.set(session, key, val)
151        return cfg
152
153    def copy_config_ini(self, build_folder, out_folder, board_name,
154                        plugin_list):
155        """
156        Copy needed config ini in build_folder
157        :param build_folder: The root path of build scripts
158        :param out_folder: The out path for all outputs
159        :param board_name: The board name
160        :param board_name: The plugin list
161        :return:
162        """
163
164        out_config_path = os.path.join(out_folder, OUT_INI_CONFIG_PATH)
165        ini_file_list = self.get_files_in_folder(build_folder, plugin_list)
166        ini_cfg_obj = self.get_config_ini(ini_file_list, board_name)
167        out_config_folder = os.path.dirname(out_config_path)
168        if not os.path.exists(out_config_folder):
169            os.mkdir(out_config_folder)
170        with open(out_config_path, mode="w") as file_object:
171            ini_cfg_obj.write(file_object)
172        with open(out_config_path, "r+") as file_object:
173            ini_content = file_object.read()
174            file_object.seek(0)
175            file_object.write(INI_LICENSE)
176            file_object.write(ini_content)
177
178
179if __name__ == "__main__":
180    if len(sys.argv) != PARA_NUM:
181        print("[ERROR]The input para number is not correct!")
182        print("usage: copy_config_ini.py "
183              "[build_dir] [out_dir] [board_name] [plugin_list]")
184        sys.exit(FAIL_CODE)
185    else:
186        BUILD_PATH, OUT_PATH, BOARD_NAME, PLUGIN_LIST = sys.argv[1:]
187        INI_MANAGER = IniManager()
188        INI_MANAGER.copy_config_ini(BUILD_PATH, OUT_PATH, BOARD_NAME,
189                                    PLUGIN_LIST)
190
191