diff --git a/meta/templates/sai_adapter_utils.tt b/meta/templates/sai_adapter_utils.tt index 119d92bff..1589929d6 100644 --- a/meta/templates/sai_adapter_utils.tt +++ b/meta/templates/sai_adapter_utils.tt @@ -10,6 +10,7 @@ from functools import wraps [%- BLOCK invocation_logger_imports %] import inspect import logging +from functools import wraps [% END -%] [%- ######################################################################## -%] @@ -180,7 +181,7 @@ def invocation_logger(func): SAI interface invocation logger. Use it to log all the invocated method in this sai_adapater. """ - + @wraps(func) def inner_logger(*args, **kwargs): args_name = inspect.getargspec(func)[0] diff --git a/test/saithriftv2/Makefile b/test/saithriftv2/Makefile index 358d0aadf..0026426f3 100644 --- a/test/saithriftv2/Makefile +++ b/test/saithriftv2/Makefile @@ -83,6 +83,9 @@ $(PY_SOURCES): $(METADIR)sai.thrift $(SAI_PY_HEADERS): $(SAI_HEADERS) $(CTYPESGEN) --output-language=py32 -I/usr/include -I$(SAI_HEADER_DIR) -I../../experimental --include /usr/include/linux/limits.h $^ -o $@ + python3 convert_header.py -i $(SAI_PY_HEADERS) -o ./new_header.py + mv $(SAI_PY_HEADERS) ./sai_headers.py.bk + mv ./new_header.py $(SAI_PY_HEADERS) $(ODIR)/%.o: gen-cpp/%.cpp meta $(CXX) $(CPPFLAGS) -c $< -o $@ -I../../meta diff --git a/test/saithriftv2/convert_header.py b/test/saithriftv2/convert_header.py new file mode 100644 index 000000000..2c5a958cf --- /dev/null +++ b/test/saithriftv2/convert_header.py @@ -0,0 +1,151 @@ +import logging +import argparse + +""" +Convert the generated code in sai_header.py. +For the generated code from c++ enum, convert it to python enum class. + +the code like + ```C++ + /** + * @brief SAI common API type + */ + typedef enum _sai_common_api_t + { + SAI_COMMON_API_CREATE = 0, + SAI_COMMON_API_REMOVE = 1, + ... + } sai_common_api_t; + ``` + original converted by ctypesgen + ``` + enum__sai_common_api_t = c_int# /usr/include/sai/saitypes.h: 183 + + SAI_COMMON_API_CREATE = 0# /usr/include/sai/saitypes.h: 183 + + SAI_COMMON_API_REMOVE = 1# /usr/include/sai/saitypes.h: 183 + ... + ``` + new code + ``` + class sai_common_api(SAIEnum): + + SAI_COMMON_API_CREATE = 0# /usr/include/sai/saitypes.h: 183 + + SAI_COMMON_API_REMOVE = 1# /usr/include/sai/saitypes.h: 183 + ... + + SAI_COMMON_API_CREATE = sai_common_api.SAI_COMMON_API_CREATE + SAI_COMMON_API_REMOVE = sai_common_api.SAI_COMMON_API_REMOVE + ... + ``` + +""" + + +ENUM_DEF = """ +import enum +class SAIEnum(enum.IntEnum): + def __str__(self): + return super().__str__().split(\".\")[1]\n""" +ENUM_PREFIX = "enum__sai_" +SAI_NAME = "SAI" +ENUM_TYPE = "= c_int" +ENUM_END = " = enum__sai_" +ENUM_CLASS_TEMPLATE = "class {}(SAIEnum):\n" + +def parse_param(): + ''' + Parse param. + ''' + parser = argparse.ArgumentParser( + description=""" + Convert python file after ctypesgen convert. + """ + ) + + parser.add_argument( + "-i", type=str, dest="input_file", + help="input file name", required=True) + parser.add_argument( + "-o", type=str, dest="output_file", + help="output file name", required=True) + return parser.parse_args() + +def convert_enum_start_to_class(line): + """ + Convert the enum to class. + args: + line: input + """ + class_name = line.strip("enum__").split("_t = c_int", 1)[0] + return class_name + +def convert_file(input_file_name, output_file_name): + """ + Convert the input file to a output file. + + """ + input_file = open(input_file_name, 'r') + output_file = open(output_file_name, 'w') + enum_times = 0 + enum_items = [] + enum_start = False + class_name = None + + for line in input_file.readlines(): + if not enum_start and enum_times == 0 and ENUM_PREFIX in line and ENUM_TYPE in line: + # first time hit a enum + # add import + output_file.writelines(line) + output_file.write(ENUM_DEF) + enum_times= enum_times + 1 + enum_start = True + enum_items = [] + output_file.write("\n") + class_name = convert_enum_start_to_class(line) + output_file.writelines(ENUM_CLASS_TEMPLATE.format(class_name)) + output_file.flush() + continue + elif not enum_start and enum_times > 0 and ENUM_PREFIX in line and ENUM_TYPE in line: + output_file.writelines(line) + enum_times= enum_times + 1 + enum_start = True + enum_items = [] + output_file.write("\n") + class_name = convert_enum_start_to_class(line) + output_file.writelines(ENUM_CLASS_TEMPLATE.format(class_name)) + output_file.flush() + continue + elif enum_start and ENUM_END not in line and SAI_NAME in line: + line = line.split("\n", 1)[0] + enum_name = line.split(" =", 1)[0] + enum_items.append(enum_name) + output_file.write(" {}\n".format(line)) + output_file.flush() + continue + elif ENUM_END in line: + enum_start = False + output_file.write("\n") + for item in enum_items: + output_file.write("{} = {}.{}".format(item, class_name, item)) + output_file.write("\n") + output_file.write("\n") + output_file.writelines(line) + output_file.flush() + continue + else: + output_file.writelines(line) + + + output_file.flush() + input_file.close() + output_file.close() + + +if __name__ == "__main__": + ''' + For the generated code from c++ enum, convert it to python enum class. + ''' + args = parse_param() + convert_file(args.input_file, args.output_file)