On 15/06/2022 09:47, Neha Malcom Francis wrote: > For validating config files and generating binary config artifacts, here > board specific config class is added. > > Add function cfgBinaryGen() in tibcfg_gen.py. It uses TIBoardConfig > class to load given schema and config files in YAML, validate them and > generate binaries. > > Signed-off-by: Tarun Sahu <t-s...@ti.com> > [n-fran...@ti.com: prepared patch for upstreaming] > Signed-off-by: Neha Malcom Francis <n-fran...@ti.com> > --- > test/py/requirements.txt | 1 + > tools/tibcfg_gen.py | 114 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 115 insertions(+) > create mode 100644 tools/tibcfg_gen.py > > diff --git a/test/py/requirements.txt b/test/py/requirements.txt > index 33c5c0bbc4..a91ba64563 100644 > --- a/test/py/requirements.txt > +++ b/test/py/requirements.txt > @@ -4,6 +4,7 @@ coverage==4.5.4 > extras==1.0.0 > fixtures==3.0.0 > importlib-metadata==0.23 > +jsonschema==4.0.0 > linecache2==1.0.0 > more-itertools==7.2.0 > packaging==19.2 > diff --git a/tools/tibcfg_gen.py b/tools/tibcfg_gen.py > new file mode 100644 > index 0000000000..e5fa2690c8 > --- /dev/null > +++ b/tools/tibcfg_gen.py > @@ -0,0 +1,114 @@ > +# SPDX-License-Identifier: GPL-2.0+ > +# Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ > +# > +# TI Board Configuration Class for Schema Validation and Binary Generation > +# > + > +import os > +import getopt > +import sys > + > +import yaml > + > +from jsonschema import validate > + > + > +class TIBoardConfig: > + > + """ Texas Instruments Board Configuration File""" > + > + def __init__(self, file, schema, data_rules=""): > + """Load a YAML configuration file and YAML schema > + > + Validation of the config file against the schema is also done.""" > + with open(file, 'r') as f: > + self.file_yaml = yaml.safe_load(f) > + with open(schema, 'r') as sch: > + self.schema_yaml = yaml.safe_load(sch) > + self.data_rules = data_rules > + try: > + validate(self.file_yaml, self.schema_yaml) > + except Exception as e: > + print(e)
Don't catch the exception here, so that we never have a non-validated TIBoardConfig object. Instead, catch it in cfgBinaryGen() below to report the validation error. > + > + def _convert_to_byte_chunk(self, val, data_type): > + """Convert value into byte array""" > + size = 0 > + if(data_type == "#/definitions/u8"): > + size = 1 > + elif(data_type == "#/definitions/u16"): > + size = 2 > + elif(data_type == "#/definitions/u32"): > + size = 4 Parentheses are unnecessary for these as well. > + else: > + raise Exception("Data type not present in definitions") > + if type(val) == int: > + br = val.to_bytes(size, byteorder="little") > + return br > + > + def _compile_yaml(self, schema_yaml, file_yaml): > + """Convert YAML file into byte array based on YAML schema""" > + br = bytearray() > + for key in file_yaml.keys(): > + node = file_yaml[key] > + node_schema = schema_yaml['properties'][key] > + node_type = node_schema.get('type') > + if not 'type' in node_schema: > + br += self._convert_to_byte_chunk(node, > + node_schema.get('$ref')) > + elif node_type == 'object': > + br += self._compile_yaml(node_schema, node) > + elif node_type == 'array': > + for item in node: > + if not isinstance(item, dict): > + br += self._convert_to_byte_chunk( > + item, > schema_yaml['properties'][key]['items']["$ref"]) > + else: > + br += self._compile_yaml(node_schema.get('items'), > item) > + return br > + > + def generate_binaries(self, out_path=""): > + """Generate config binary artifacts from the loaded YAML > configuration file""" > + if not os.path.isdir(out_path): > + os.mkdir(out_path) > + for key in self.file_yaml.keys(): > + node = self.file_yaml[key] > + node_schema = self.schema_yaml['properties'][key] > + br = self._compile_yaml(node_schema, node) > + path = os.path.join(out_path, key + ".bin") > + with open(path, 'wb') as cfg: > + cfg.write(br) > + > + def delete_binaries(self, out_path=""): > + """Delete generated binaries""" > + if os.path.isdir(out_path): > + for key in self.file_yaml.keys(): > + path = os.path.join(out_path, key + ".bin") > + if os.path.isfile(path): > + os.remove(path) > + > + > +def cfgBinaryGen(): > + """Generate config binaries from YAML config file and YAML schema > + Arguments: > + - config_yaml: board config file in YAML > + - schema_yaml: schema file in YAML to validate config_yaml > against > + - output_dir: output directory where generated binaries can be > populated > + Pass the arguments along with the filename in the Makefile. > + """ > + opts, args = getopt.getopt(sys.argv[1:], "c:s:o") I'd prefer argparse, with both long/short forms of arguments and proper help messages. > + for opt, val in opts: > + if opt == "-c": > + config_yaml = val > + elif opt == "-s": > + schema_yaml = val > + elif opt == "-o": > + output_dir = os.path.abspath(val) > + try: > + tibcfg = TIBoardConfig(config_yaml, schema_yaml) > + tibcfg.generate_binaries(output_dir) > + except: > + raise ValueError("Could not find config files!") > + > + > +cfgBinaryGen() This needs to be if __name__ == "__main__": cfgBinaryGen() or it will be run when anything uses 'import tibcfg_gen' in Python.