Skip to content

Commit 161f9f7

Browse files
authored
[cherry-pick][1.10][SAI-PTF] Convert generated enum code from ctypesgen into pythoon enum class (opencomputeproject#1760)
why cherry-pick from opencomputeproject#1758 When ctypesgen generated the python code for c++ enum, the python cannot be logged by it enum name, we need to change it to 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_SET = 2, SAI_COMMON_API_GET = 3, SAI_COMMON_API_BULK_CREATE = 4, SAI_COMMON_API_BULK_REMOVE = 5, SAI_COMMON_API_BULK_SET = 6, SAI_COMMON_API_BULK_GET = 7, SAI_COMMON_API_MAX = 8, } 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 SAI_COMMON_API_SET = 2# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_GET = 3# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_CREATE = 4# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_REMOVE = 5# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_SET = 6# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_GET = 7# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_MAX = 8# /usr/include/sai/saitypes.h: 183 sai_common_api_t = enum__sai_common_api_t# /usr/include/sai/saitypes.h: 183 enum__sai_object_type_t = c_int# /usr/include/sai/saitypes.h: 294 ``` 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_SET = 2# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_GET = 3# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_CREATE = 4# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_REMOVE = 5# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_SET = 6# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_BULK_GET = 7# /usr/include/sai/saitypes.h: 183 SAI_COMMON_API_MAX = 8# /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 SAI_COMMON_API_SET = sai_common_api.SAI_COMMON_API_SET SAI_COMMON_API_GET = sai_common_api.SAI_COMMON_API_GET SAI_COMMON_API_BULK_CREATE = sai_common_api.SAI_COMMON_API_BULK_CREATE SAI_COMMON_API_BULK_REMOVE = sai_common_api.SAI_COMMON_API_BULK_REMOVE SAI_COMMON_API_BULK_SET = sai_common_api.SAI_COMMON_API_BULK_SET SAI_COMMON_API_BULK_GET = sai_common_api.SAI_COMMON_API_BULK_GET SAI_COMMON_API_MAX = sai_common_api.SAI_COMMON_API_MAX ``` how Convert the python code after generated from ctypesgen verify pipeline local testing reformat refactor code Signed-off-by: richardyu-ms <[email protected]>
1 parent 2972f73 commit 161f9f7

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

meta/templates/sai_adapter_utils.tt

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from functools import wraps
1010
[%- BLOCK invocation_logger_imports %]
1111
import inspect
1212
import logging
13+
from functools import wraps
1314
[% END -%]
1415

1516
[%- ######################################################################## -%]
@@ -180,7 +181,7 @@ def invocation_logger(func):
180181
SAI interface invocation logger.
181182
Use it to log all the invocated method in this sai_adapater.
182183
"""
183-
184+
@wraps(func)
184185
def inner_logger(*args, **kwargs):
185186

186187
args_name = inspect.getargspec(func)[0]

test/saithriftv2/Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ $(PY_SOURCES): $(METADIR)sai.thrift
8282
$(THRIFT) -o ./ --gen py -r $^
8383

8484
$(SAI_PY_HEADERS): $(SAI_HEADERS)
85-
$(CTYPESGEN) --output-language=py32 -I/usr/include -I$(SAI_HEADER_DIR) --include /usr/include/linux/limits.h $^ -o $@
85+
$(CTYPESGEN) --output-language=py32 -I/usr/include -I$(SAI_HEADER_DIR) -I../../experimental --include /usr/include/linux/limits.h $^ -o $@
86+
python3 convert_header.py -i $(SAI_PY_HEADERS) -o ./new_header.py
87+
mv $(SAI_PY_HEADERS) ./sai_headers.py.bk
88+
mv ./new_header.py $(SAI_PY_HEADERS)
8689

8790
$(ODIR)/%.o: gen-cpp/%.cpp meta
8891
$(CXX) $(CPPFLAGS) -c $< -o $@ -I../../meta

test/saithriftv2/convert_header.py

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import logging
2+
import argparse
3+
4+
"""
5+
Convert the generated code in sai_header.py.
6+
For the generated code from c++ enum, convert it to python enum class.
7+
8+
the code like
9+
```C++
10+
/**
11+
* @brief SAI common API type
12+
*/
13+
typedef enum _sai_common_api_t
14+
{
15+
SAI_COMMON_API_CREATE = 0,
16+
SAI_COMMON_API_REMOVE = 1,
17+
...
18+
} sai_common_api_t;
19+
```
20+
original converted by ctypesgen
21+
```
22+
enum__sai_common_api_t = c_int# /usr/include/sai/saitypes.h: 183
23+
24+
SAI_COMMON_API_CREATE = 0# /usr/include/sai/saitypes.h: 183
25+
26+
SAI_COMMON_API_REMOVE = 1# /usr/include/sai/saitypes.h: 183
27+
...
28+
```
29+
new code
30+
```
31+
class sai_common_api(SAIEnum):
32+
33+
SAI_COMMON_API_CREATE = 0# /usr/include/sai/saitypes.h: 183
34+
35+
SAI_COMMON_API_REMOVE = 1# /usr/include/sai/saitypes.h: 183
36+
...
37+
38+
SAI_COMMON_API_CREATE = sai_common_api.SAI_COMMON_API_CREATE
39+
SAI_COMMON_API_REMOVE = sai_common_api.SAI_COMMON_API_REMOVE
40+
...
41+
```
42+
43+
"""
44+
45+
46+
ENUM_DEF = """
47+
import enum
48+
class SAIEnum(enum.IntEnum):
49+
def __str__(self):
50+
return super().__str__().split(\".\")[1]\n"""
51+
ENUM_PREFIX = "enum__sai_"
52+
SAI_NAME = "SAI"
53+
ENUM_TYPE = "= c_int"
54+
ENUM_END = " = enum__sai_"
55+
ENUM_CLASS_TEMPLATE = "class {}(SAIEnum):\n"
56+
57+
def parse_param():
58+
'''
59+
Parse param.
60+
'''
61+
parser = argparse.ArgumentParser(
62+
description="""
63+
Convert python file after ctypesgen convert.
64+
"""
65+
)
66+
67+
parser.add_argument(
68+
"-i", type=str, dest="input_file",
69+
help="input file name", required=True)
70+
parser.add_argument(
71+
"-o", type=str, dest="output_file",
72+
help="output file name", required=True)
73+
return parser.parse_args()
74+
75+
def convert_enum_start_to_class(line):
76+
"""
77+
Convert the enum to class.
78+
args:
79+
line: input
80+
"""
81+
class_name = line.strip("enum__").split("_t = c_int", 1)[0]
82+
return class_name
83+
84+
def convert_file(input_file_name, output_file_name):
85+
"""
86+
Convert the input file to a output file.
87+
88+
"""
89+
input_file = open(input_file_name, 'r')
90+
output_file = open(output_file_name, 'w')
91+
enum_times = 0
92+
enum_items = []
93+
enum_start = False
94+
class_name = None
95+
96+
for line in input_file.readlines():
97+
if not enum_start and enum_times == 0 and ENUM_PREFIX in line and ENUM_TYPE in line:
98+
# first time hit a enum
99+
# add import
100+
output_file.writelines(line)
101+
output_file.write(ENUM_DEF)
102+
enum_times= enum_times + 1
103+
enum_start = True
104+
enum_items = []
105+
output_file.write("\n")
106+
class_name = convert_enum_start_to_class(line)
107+
output_file.writelines(ENUM_CLASS_TEMPLATE.format(class_name))
108+
output_file.flush()
109+
continue
110+
elif not enum_start and enum_times > 0 and ENUM_PREFIX in line and ENUM_TYPE in line:
111+
output_file.writelines(line)
112+
enum_times= enum_times + 1
113+
enum_start = True
114+
enum_items = []
115+
output_file.write("\n")
116+
class_name = convert_enum_start_to_class(line)
117+
output_file.writelines(ENUM_CLASS_TEMPLATE.format(class_name))
118+
output_file.flush()
119+
continue
120+
elif enum_start and ENUM_END not in line and SAI_NAME in line:
121+
line = line.split("\n", 1)[0]
122+
enum_name = line.split(" =", 1)[0]
123+
enum_items.append(enum_name)
124+
output_file.write(" {}\n".format(line))
125+
output_file.flush()
126+
continue
127+
elif ENUM_END in line:
128+
enum_start = False
129+
output_file.write("\n")
130+
for item in enum_items:
131+
output_file.write("{} = {}.{}".format(item, class_name, item))
132+
output_file.write("\n")
133+
output_file.write("\n")
134+
output_file.writelines(line)
135+
output_file.flush()
136+
continue
137+
else:
138+
output_file.writelines(line)
139+
140+
141+
output_file.flush()
142+
input_file.close()
143+
output_file.close()
144+
145+
146+
if __name__ == "__main__":
147+
'''
148+
For the generated code from c++ enum, convert it to python enum class.
149+
'''
150+
args = parse_param()
151+
convert_file(args.input_file, args.output_file)

0 commit comments

Comments
 (0)