初始提交
This commit is contained in:
174
build/script/nv/conf_parser.py
Executable file
174
build/script/nv/conf_parser.py
Executable file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2022. All rights reserved.
|
||||
|
||||
"""
|
||||
* Description: Settings parsers.
|
||||
* Create: 2020-1-2
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
from build_utils import color_red
|
||||
from build_utils import color_end
|
||||
|
||||
__all__ = ["MconfParser", "BuildConfParser"]
|
||||
|
||||
def nv_repeat_check(pairs):
|
||||
key_list = []
|
||||
for key_temp in pairs:
|
||||
if key_temp[0] not in key_list:
|
||||
key_list.append(key_temp[0])
|
||||
else:
|
||||
raise Exception("nv items(%s) repeat"%key_temp[0])
|
||||
pairs = dict(pairs)
|
||||
return pairs
|
||||
|
||||
class ParserError(Exception):
|
||||
"""
|
||||
Parse errors, highlight in red.
|
||||
"""
|
||||
def __init__(self, err):
|
||||
emsg = "%s%s%s"%(color_red(), err, color_end())
|
||||
Exception.__init__(self, emsg)
|
||||
pass
|
||||
|
||||
"""
|
||||
Json format config file parser
|
||||
"""
|
||||
class BuildConfParser:
|
||||
def __init__(self, conf_path):
|
||||
if not os.path.isfile(conf_path):
|
||||
raise ParserError("Configration file %s NOT found!"%conf_path)
|
||||
|
||||
with open(conf_path, 'r', encoding='utf-8') as conf:
|
||||
try:
|
||||
myread = conf.read()
|
||||
self.conf_data = json.loads(myread)
|
||||
self.nvconf_data = json.loads(myread, object_pairs_hook = nv_repeat_check)
|
||||
except Exception as err:
|
||||
msg = "%s\nParsing file:%s"%(err, conf_path)
|
||||
raise ParserError(msg)
|
||||
|
||||
self.conf_data = self._parse(self.conf_data)
|
||||
self.nvconf_data = self._parse(self.nvconf_data)
|
||||
|
||||
def get_conf_data(self):
|
||||
return self.conf_data
|
||||
|
||||
def get_nvconf_data(self):
|
||||
return self.nvconf_data
|
||||
|
||||
def get(self, option):
|
||||
return self.conf_data.get(option)
|
||||
|
||||
def _parse(self, data):
|
||||
"""
|
||||
parse the python sentence starts with ###
|
||||
"""
|
||||
for key, value in data.items():
|
||||
if isinstance(value, dict):
|
||||
# Recursion
|
||||
value = self._parse(value)
|
||||
if isinstance(value, list):
|
||||
# Recursion
|
||||
data[key] = self._parse_list(value)
|
||||
if isinstance(value, int):
|
||||
data[key] = value
|
||||
if isinstance(value, str) and value.startswith('###'):
|
||||
value = self._exec(value)
|
||||
data[key] = value
|
||||
return data
|
||||
|
||||
def _parse_list(self, values):
|
||||
new_list = []
|
||||
for val in values:
|
||||
if type(val) is str and val.startswith('###'):
|
||||
value = self._exec(val)
|
||||
new_list.append(value)
|
||||
elif isinstance(val, dict):
|
||||
new_list.append(self._parse(val))
|
||||
else:
|
||||
new_list.append(val)
|
||||
return new_list
|
||||
|
||||
def _exec(self, code):
|
||||
"""
|
||||
Execute the simple python sentence.
|
||||
For the security reason, only allows 'os.path.join' to be input, as a path string
|
||||
to support multiple platforms.
|
||||
If it needs to support more python features, please use compile and eval, but careful about
|
||||
the security issues.
|
||||
"""
|
||||
start = code.find("os.path.join")
|
||||
if start < 0:
|
||||
raise ParserError("The input doesn't support!")
|
||||
lpt = code.find("(")
|
||||
if lpt < 0 or lpt < start:
|
||||
raise ParserError("The input doesn't support!")
|
||||
rpt = code.find(")")
|
||||
if rpt < 0 or rpt < lpt:
|
||||
raise ParserError("The input doesn't support!")
|
||||
path_parts = code[lpt + 1:rpt].split(",")
|
||||
ret = ""
|
||||
for part in path_parts:
|
||||
ret = os.path.join(ret, part.lstrip(" '\"").rstrip(" '\""))
|
||||
return ret
|
||||
|
||||
"""
|
||||
Menuconfig format config file parser
|
||||
"""
|
||||
class MconfParser:
|
||||
def __init__(self, conf_path):
|
||||
if not os.path.isfile(conf_path):
|
||||
raise ParserError("Configration file %s NOT found!"%conf_path)
|
||||
|
||||
with open(conf_path, 'r', encoding='utf-8') as conf:
|
||||
self.conf_data = conf.readlines()
|
||||
|
||||
self.conf_data = self._parse(self.conf_data)
|
||||
|
||||
def get(self, option):
|
||||
data = self.conf_data.get(option)
|
||||
if data is None:
|
||||
# Option not found be treated as false.
|
||||
return 'n'
|
||||
# strip " when met string values.
|
||||
return data.replace('"', '')
|
||||
|
||||
def _parse(self, data):
|
||||
settings = {}
|
||||
for option in data:
|
||||
if self._option_is_valid(option) is True:
|
||||
key, value = self._parse_option(option)
|
||||
settings[key] = value.strip().replace('\n', '').replace('\r', '')
|
||||
return settings
|
||||
|
||||
def _option_is_valid(self, option):
|
||||
option = option.strip()
|
||||
if (option is None) or (option == '') or (option.startswith('#') is True):
|
||||
# skip blanks and comments.
|
||||
return False
|
||||
return True
|
||||
|
||||
def _parse_option(self, option):
|
||||
cfg = option.split('=')
|
||||
if len(cfg) == 2:
|
||||
# like "KEY=value", length always be 2. return in KEY, value
|
||||
return cfg[0], cfg[1]
|
||||
else:
|
||||
raise ParserError("Unknow format of the option:%s"%option)
|
||||
|
||||
def test():
|
||||
"""
|
||||
Test only.
|
||||
"""
|
||||
parser = BuildConfParser("build/config/riscv32_toolchain.json")
|
||||
print(parser.get('TargetFolder'))
|
||||
mparser = MconfParser("build/config/settings.json")
|
||||
print(mparser.get('CONFIG_TARGET_SOFT_VER'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
|
Reference in New Issue
Block a user