openubmc-bingo 0.5.254__py3-none-any.whl → 0.5.261__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of openubmc-bingo might be problematic. Click here for more details.
- bmcgo/__init__.py +1 -1
- bmcgo/codegen/lua/codegen.py +23 -0
- bmcgo/codegen/lua/script/model_consistency_check.py +242 -0
- bmcgo/codegen/lua/script/render_utils/__init__.py +7 -4
- bmcgo/codegen/lua/script/render_utils/client_lua.py +1 -1
- bmcgo/codegen/lua/script/render_utils/message_lua.py +2 -1
- bmcgo/codegen/lua/script/render_utils/service_lua.py +1 -1
- bmcgo/codegen/lua/script/utils.py +30 -3
- bmcgo/codegen/lua/templates/apps/Makefile +70 -2
- bmcgo/codegen/lua/v1/script/render_utils/client_lua.py +108 -0
- bmcgo/codegen/lua/v1/script/render_utils/db_lua.py +223 -0
- bmcgo/codegen/lua/v1/script/render_utils/model_lua.py +29 -0
- bmcgo/codegen/lua/v1/templates/apps/client.lua.mako +244 -0
- bmcgo/codegen/lua/v1/templates/apps/db.lua.mako +62 -0
- bmcgo/codegen/lua/v1/templates/apps/local_db.lua.mako +184 -0
- bmcgo/codegen/lua/v1/templates/apps/message.lua.mako +35 -0
- bmcgo/codegen/lua/v1/templates/apps/model.lua.mako +3 -0
- bmcgo/codegen/lua/v1/templates/apps/service.lua.mako +8 -47
- bmcgo/codegen/lua/v1/templates/apps/utils/mdb_intf.lua.mako +27 -0
- bmcgo/codegen/lua/v1/templates/apps/utils/mdb_obj.lua.mako +14 -0
- bmcgo/component/coverage/incremental_cov.py +4 -4
- bmcgo/tasks/task_build_rootfs_img.py +2 -2
- {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/METADATA +1 -1
- {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/RECORD +28 -19
- /bmcgo/codegen/lua/script/{render_utils/mdb_register.py → mdb_register.py} +0 -0
- {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/WHEEL +0 -0
- {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/entry_points.txt +0 -0
- {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding=utf-8
|
|
3
|
+
# Copyright (c) 2024 Huawei Technologies Co., Ltd.
|
|
4
|
+
# openUBMC is licensed under Mulan PSL v2.
|
|
5
|
+
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
6
|
+
# You may obtain a copy of Mulan PSL v2 at:
|
|
7
|
+
# http://license.coscl.org.cn/MulanPSL2
|
|
8
|
+
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
9
|
+
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
10
|
+
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
11
|
+
# See the Mulan PSL v2 for more details.
|
|
12
|
+
|
|
13
|
+
from utils import Utils
|
|
14
|
+
from bmcgo.codegen.lua.script.dto.options import Options
|
|
15
|
+
from bmcgo.codegen.lua.script.mdb_register import MdbRegister
|
|
16
|
+
from bmcgo.codegen.lua.script.base import Base
|
|
17
|
+
from bmcgo.codegen.lua.script.factory import Factory
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConsistencyClientLuaUtils(Base, Utils, MdbRegister):
|
|
21
|
+
def __init__(self, data: dict, options: Options):
|
|
22
|
+
super().__init__(data, options=options)
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def message_type(t):
|
|
26
|
+
if t == ".google.protobuf.Empty":
|
|
27
|
+
return 'nil'
|
|
28
|
+
return t[1:] if t.startswith('.') else t
|
|
29
|
+
|
|
30
|
+
def sig(self, msg_type):
|
|
31
|
+
msg = Utils(self.data, self.options).make_get_message(msg_type)
|
|
32
|
+
return "".join(
|
|
33
|
+
[Utils(self.data, self.options).do_type_to_dbus(p['type'], p['repeated']) for p in msg.get('properties')])
|
|
34
|
+
|
|
35
|
+
def props(self, msg_type):
|
|
36
|
+
msg = Utils(self.data, self.options).make_get_message(msg_type)
|
|
37
|
+
return msg.get('properties')
|
|
38
|
+
|
|
39
|
+
def params(self, msg_type):
|
|
40
|
+
return ", ".join([p['name'] for p in self.props(msg_type)])
|
|
41
|
+
|
|
42
|
+
def cb_name(self, rpc):
|
|
43
|
+
return Utils(self.data, self.options).camel_to_snake('__On' + rpc['name'])
|
|
44
|
+
|
|
45
|
+
def rsp_message(self, rpc):
|
|
46
|
+
return self.message_type(rpc['rsp'])
|
|
47
|
+
|
|
48
|
+
def req_message(self, rpc):
|
|
49
|
+
return self.message_type(rpc['req'])
|
|
50
|
+
|
|
51
|
+
def make_path_with_params(self, path):
|
|
52
|
+
path = self.force_to_colon(path)
|
|
53
|
+
params = self.get_path_params(path)
|
|
54
|
+
if not params:
|
|
55
|
+
return f"'{path}'"
|
|
56
|
+
result = []
|
|
57
|
+
for name in params:
|
|
58
|
+
parts = path.partition(f':{name}')
|
|
59
|
+
result.append(f"'{parts[0]}'")
|
|
60
|
+
result.append(f"path_params['{name}']")
|
|
61
|
+
path = parts[2]
|
|
62
|
+
ret = ' .. '.join(result)
|
|
63
|
+
if path:
|
|
64
|
+
ret += f" .. '{path}'"
|
|
65
|
+
return ret
|
|
66
|
+
|
|
67
|
+
def get_path_arg(self, path, with_comma=True):
|
|
68
|
+
if not self.get_path_params(path):
|
|
69
|
+
return ""
|
|
70
|
+
if with_comma:
|
|
71
|
+
return ", path_params"
|
|
72
|
+
return "path_params"
|
|
73
|
+
|
|
74
|
+
def get_path_namespace_name(self, index):
|
|
75
|
+
return f"path_namespace{index + 1}"
|
|
76
|
+
|
|
77
|
+
def get_path_namespace_list(self, paths):
|
|
78
|
+
indexed_path_namespace = [
|
|
79
|
+
f"path_namespace{index + 1}"
|
|
80
|
+
for index, _ in enumerate(paths)
|
|
81
|
+
]
|
|
82
|
+
return "{" + ", ".join(indexed_path_namespace) + "}"
|
|
83
|
+
|
|
84
|
+
def get_dep_properties(self, properties):
|
|
85
|
+
if properties == ["*"]:
|
|
86
|
+
return ""
|
|
87
|
+
|
|
88
|
+
return ', {"' + '", "'.join(properties) + '"}'
|
|
89
|
+
|
|
90
|
+
def get_path_namespace(self, path):
|
|
91
|
+
if not self.get_path_params(path):
|
|
92
|
+
return f"'{path}'"
|
|
93
|
+
path_with_params = self.make_path_with_params(path)
|
|
94
|
+
if Utils.get_lua_codegen_version() >= 17:
|
|
95
|
+
return f"path_params and ({path_with_params}) or '{path}'"
|
|
96
|
+
prefix = path_with_params.split("/' ..")[0]
|
|
97
|
+
return f"path_params and ({path_with_params}) or {prefix}'"
|
|
98
|
+
|
|
99
|
+
def get_path_patterns(self, paths):
|
|
100
|
+
return MdbRegister.convert_to_lua(self, paths)
|
|
101
|
+
|
|
102
|
+
def get_object_path(self, path):
|
|
103
|
+
if not self.get_path_params(path):
|
|
104
|
+
return f"'{path}'"
|
|
105
|
+
path_with_params = self.make_path_with_params(path)
|
|
106
|
+
return f"path_params and ({path_with_params}) or '{path}'"
|
|
107
|
+
|
|
108
|
+
Factory().register("v1/templates/apps/client.lua.mako", ConsistencyClientLuaUtils)
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding=utf-8
|
|
3
|
+
# Copyright (c) 2024 Huawei Technologies Co., Ltd.
|
|
4
|
+
# openUBMC is licensed under Mulan PSL v2.
|
|
5
|
+
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
6
|
+
# You may obtain a copy of Mulan PSL v2 at:
|
|
7
|
+
# http://license.coscl.org.cn/MulanPSL2
|
|
8
|
+
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
9
|
+
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
10
|
+
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
11
|
+
# See the Mulan PSL v2 for more details.
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
from utils import Utils
|
|
15
|
+
from bmcgo.codegen.lua.script.dto.options import Options
|
|
16
|
+
from bmcgo.codegen.lua.script.base import Base
|
|
17
|
+
from bmcgo.codegen.lua.script.factory import Factory
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConsistencyDbLuaUtils(Base, Utils):
|
|
21
|
+
TYPE_TO_DB_MAP = {
|
|
22
|
+
"int8": 'IntegerField',
|
|
23
|
+
'uint8': 'IntegerField',
|
|
24
|
+
'int16': 'IntegerField',
|
|
25
|
+
'uint16': 'IntegerField',
|
|
26
|
+
'int32': 'IntegerField',
|
|
27
|
+
'uint32': 'IntegerField',
|
|
28
|
+
'int64': 'IntegerField',
|
|
29
|
+
'uint64': 'IntegerField',
|
|
30
|
+
'double': 'RealField',
|
|
31
|
+
'float': 'RealField',
|
|
32
|
+
'bytes': 'BolbField',
|
|
33
|
+
'string': 'TextField',
|
|
34
|
+
'bool': 'BooleandField',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
per_type_map = {
|
|
38
|
+
'PoweroffPer': 'protect_power_off',
|
|
39
|
+
'ResetPer': 'protect_reset',
|
|
40
|
+
'PermanentPer': 'protect_permanent',
|
|
41
|
+
'TemporaryPer': 'protect_temporary',
|
|
42
|
+
'PoweroffPerRetain': 'protect_power_off_retain',
|
|
43
|
+
'ResetPerRetain': 'protect_reset_retain',
|
|
44
|
+
'TemporaryPerRetain': 'protect_temporary_retain'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
def __init__(self, data: dict, options: Options):
|
|
48
|
+
super().__init__(data, options=options)
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def table_name(msg):
|
|
52
|
+
if msg['type'] != 'Message' or not msg['options'] or not msg['options']['table_name']:
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
return msg['options']['table_name']
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def table_max_rows(msg):
|
|
59
|
+
return msg.get('type') == 'Message' and msg.get('options', {}).get('table_max_rows', False)
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def all_persistence(msg):
|
|
63
|
+
if msg['type'] != 'Message' or not msg['options']:
|
|
64
|
+
return 'nil'
|
|
65
|
+
|
|
66
|
+
if 'persistence' in msg['options']:
|
|
67
|
+
return msg['options']['persistence']
|
|
68
|
+
|
|
69
|
+
if 'table_type' in msg['options']:
|
|
70
|
+
if msg['options']['table_type'] in ConsistencyDbLuaUtils.per_type_map:
|
|
71
|
+
return ConsistencyDbLuaUtils.per_type_map[msg['options']['table_type']]
|
|
72
|
+
return 'nil'
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def check_local_per_type(root):
|
|
76
|
+
per_map = {
|
|
77
|
+
"PoweroffPer": False,
|
|
78
|
+
"ResetPer": False,
|
|
79
|
+
"TemporaryPer": False
|
|
80
|
+
}
|
|
81
|
+
for msg in root["data"]:
|
|
82
|
+
table_type = msg["options"].get("table_type", "PoweroffPer")
|
|
83
|
+
if table_type not in per_map:
|
|
84
|
+
continue
|
|
85
|
+
per_map[table_type] = True
|
|
86
|
+
return per_map.values()
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def check_local_per_poweroff(msg):
|
|
90
|
+
if "options" not in msg or "table_type" not in msg["options"]:
|
|
91
|
+
return True
|
|
92
|
+
return "options" in msg and "table_type" in msg["options"] and msg["options"]["table_type"] == "PoweroffPer"
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def check_local_per_reset(msg):
|
|
96
|
+
return "options" in msg and "table_type" in msg["options"] and msg["options"]["table_type"] == "ResetPer"
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def check_local_per_temporary(msg):
|
|
100
|
+
return "options" in msg and "table_type" in msg["options"] and msg["options"]["table_type"] == "TemporaryPer"
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def column_max_len(prop):
|
|
104
|
+
if prop['repeated']:
|
|
105
|
+
return 0
|
|
106
|
+
type_name = prop['type']
|
|
107
|
+
if type_name == "int8" or type_name == 'uint8':
|
|
108
|
+
return 8
|
|
109
|
+
if type_name == "int16" or type_name == 'uint16':
|
|
110
|
+
return 16
|
|
111
|
+
if type_name == "int32" or type_name == 'uint32':
|
|
112
|
+
return 32
|
|
113
|
+
if type_name == "int64" or type_name == 'uint64':
|
|
114
|
+
return 64
|
|
115
|
+
if 'max_len' in prop['options']:
|
|
116
|
+
return prop['options']['max_len']
|
|
117
|
+
return 0
|
|
118
|
+
|
|
119
|
+
@staticmethod
|
|
120
|
+
def unique(prop):
|
|
121
|
+
if 'unique' not in prop['options']:
|
|
122
|
+
return ''
|
|
123
|
+
return f':unique()'
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def primary_key(prop):
|
|
127
|
+
if 'primary_key' not in prop['options']:
|
|
128
|
+
return ''
|
|
129
|
+
return f':primary_key()'
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def persistence_key(prop):
|
|
133
|
+
if 'persistence_ex' in prop['options']:
|
|
134
|
+
val = prop['options']['persistence_ex']
|
|
135
|
+
return f':persistence_key("{val}")'
|
|
136
|
+
|
|
137
|
+
if 'usage' not in prop['options']:
|
|
138
|
+
return ''
|
|
139
|
+
val = ''
|
|
140
|
+
for use_type in prop['options']['usage']:
|
|
141
|
+
if use_type in ConsistencyDbLuaUtils.per_type_map:
|
|
142
|
+
val = ConsistencyDbLuaUtils.per_type_map[use_type]
|
|
143
|
+
break
|
|
144
|
+
if val == '':
|
|
145
|
+
return ''
|
|
146
|
+
|
|
147
|
+
return f':persistence_key("{val}")'
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def allow_null(prop):
|
|
151
|
+
if prop['options'].get('allow_null', False):
|
|
152
|
+
return ':null()'
|
|
153
|
+
return ''
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def extend_field(prop):
|
|
157
|
+
if prop['options'].get('extend_field', False):
|
|
158
|
+
return ':extend_field()'
|
|
159
|
+
return ''
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def deprecated(prop):
|
|
163
|
+
if prop['options'].get('deprecated', False):
|
|
164
|
+
return ':deprecated()'
|
|
165
|
+
return ''
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def critical(prop):
|
|
169
|
+
if prop['options'].get('critical', False):
|
|
170
|
+
return ':critical()'
|
|
171
|
+
return ''
|
|
172
|
+
|
|
173
|
+
def column_type(self, prop):
|
|
174
|
+
type_name = prop['type']
|
|
175
|
+
if type_name in self.TYPE_TO_DB_MAP:
|
|
176
|
+
if prop['repeated']:
|
|
177
|
+
return "JsonField()"
|
|
178
|
+
else:
|
|
179
|
+
return self.TYPE_TO_DB_MAP[type_name] + "()"
|
|
180
|
+
types = Utils(self.data, self.options).load_types(type_name)
|
|
181
|
+
if types and ('type' in types) and types['type'] == 'Enum':
|
|
182
|
+
return f'EnumField({types["package"]}.{types["name"]})'
|
|
183
|
+
return "JsonField()"
|
|
184
|
+
|
|
185
|
+
def max_len(self, prop):
|
|
186
|
+
num = self.column_max_len(prop)
|
|
187
|
+
if num == 0:
|
|
188
|
+
return ''
|
|
189
|
+
return f':max_length({num})'
|
|
190
|
+
|
|
191
|
+
def default(self, class_name, prop):
|
|
192
|
+
if 'default' not in prop['options']:
|
|
193
|
+
return ''
|
|
194
|
+
return f':default({self._convert_default_value(class_name, prop)})'
|
|
195
|
+
|
|
196
|
+
def _convert_default_value(self, class_name, prop):
|
|
197
|
+
d_val = prop['options']['default']
|
|
198
|
+
type_name = prop['type']
|
|
199
|
+
types = Utils(self.data, self.options).load_types(type_name)
|
|
200
|
+
if types and ('type' in types) and types['type'] == 'Enum':
|
|
201
|
+
if isinstance(d_val, list):
|
|
202
|
+
result = "{"
|
|
203
|
+
for val in d_val:
|
|
204
|
+
enum_type = Utils(self.data, self.options).enum_value_name(types["name"], val)
|
|
205
|
+
result += f'{types["package"]}.{types["name"]}.{enum_type},'
|
|
206
|
+
return result + "}"
|
|
207
|
+
value_name = Utils(self.data, self.options).enum_value_name(types["name"], d_val)
|
|
208
|
+
return f'{types["package"]}.{types["name"]}.{value_name}'
|
|
209
|
+
if Utils.get_lua_codegen_version() >= 10:
|
|
210
|
+
if prop.get('repeated') and not isinstance(d_val, list):
|
|
211
|
+
raise RuntimeError(f"model.json中类{class_name}的属性{prop['name']}默认值{d_val}类型与属性类型不一致")
|
|
212
|
+
if isinstance(d_val, list) or isinstance(d_val, dict):
|
|
213
|
+
json_str = json.dumps(d_val).replace("'", "''")
|
|
214
|
+
return f"[['{json_str}']]"
|
|
215
|
+
if type_name == "string" or type_name == 'bytes':
|
|
216
|
+
return f'"\'{d_val}\'"'
|
|
217
|
+
if type_name == "bool":
|
|
218
|
+
return str(bool(d_val)).lower()
|
|
219
|
+
return d_val
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
Factory().register("v1/templates/apps/db.lua.mako", ConsistencyDbLuaUtils)
|
|
223
|
+
Factory().register("v1/templates/apps/local_db.lua.mako", ConsistencyDbLuaUtils)
|
|
@@ -22,6 +22,10 @@ BASE_TYPE = "baseType"
|
|
|
22
22
|
ITEMS = "items"
|
|
23
23
|
NON_CONVERT_ITEMS = ["validator", "req_type", "rsp_type", "feature", "default_value", "read", "write"]
|
|
24
24
|
FILTERED_ITEMS = ["description", "$ref", "default", "items", "req", "rsp", "featureTag", "privilege"]
|
|
25
|
+
PERSIST_TYPES = {
|
|
26
|
+
"PermanentPer", "PoweroffPer", "ResetPer", "TemporaryPer", "PoweroffPerRetain",
|
|
27
|
+
"ResetPerRetain", "TemporaryPerRetain", "Memory"
|
|
28
|
+
}
|
|
25
29
|
OBJECT_PROPERTIES_INTERFACE = "bmc.kepler.Object.Properties"
|
|
26
30
|
|
|
27
31
|
|
|
@@ -67,6 +71,10 @@ class ConsistencyModelLuaUtils(Base, Utils):
|
|
|
67
71
|
def combine_privileges(privileges):
|
|
68
72
|
prefix = "privilege."
|
|
69
73
|
return prefix + (" | " + prefix).join(sorted(privileges))
|
|
74
|
+
|
|
75
|
+
@staticmethod
|
|
76
|
+
def prop_contains_persist_type(prop_config: dict):
|
|
77
|
+
return bool(set(prop_config.get("usage", [])) & PERSIST_TYPES)
|
|
70
78
|
|
|
71
79
|
def class_has_block_io(self, msg):
|
|
72
80
|
if self.has_path(msg):
|
|
@@ -175,6 +183,27 @@ class ConsistencyModelLuaUtils(Base, Utils):
|
|
|
175
183
|
return msg['path']
|
|
176
184
|
return msg['path'].replace(':parent/', self.get_path(root, root[msg['parent']]) + ':parent/')
|
|
177
185
|
|
|
186
|
+
def is_enable_orm(self, msg):
|
|
187
|
+
if "tableName" not in msg:
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
if "tableLocation" in msg and msg["tableLocation"] == "Local":
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
if "tableType" in msg:
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
for _, prop_config in msg.get('properties', {}).items():
|
|
197
|
+
if self.prop_contains_persist_type(prop_config):
|
|
198
|
+
return True
|
|
199
|
+
|
|
200
|
+
for intf_data in msg.get('interfaces', {}).values():
|
|
201
|
+
for _, prop_config in intf_data.get('properties', {}).items():
|
|
202
|
+
if self.prop_contains_persist_type(prop_config):
|
|
203
|
+
return True
|
|
204
|
+
|
|
205
|
+
return False
|
|
206
|
+
|
|
178
207
|
def convert_dynamic_params(self, msg):
|
|
179
208
|
match_obj = re.search("\$\{(.+?)\}", msg)
|
|
180
209
|
if match_obj is None:
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
## 生成所有rpc接口
|
|
2
|
+
<%def name="get_obj(rpc)">
|
|
3
|
+
% if rpc['path'] != '*': ## 非虚方法和收集类方法,直接远程调用
|
|
4
|
+
% if 'paths' in rpc and not rpc['virtual']:
|
|
5
|
+
%if not rpc['retry']:
|
|
6
|
+
mdb.get_object(self:get_bus(), ${render_utils.make_path_with_params(rpc['full_path'])}, '${rpc['interface']}')
|
|
7
|
+
%else:
|
|
8
|
+
mdb.try_get_object(self:get_bus(), ${render_utils.get_object_path(rpc['full_path'])}, '${rpc['interface']}')
|
|
9
|
+
%endif
|
|
10
|
+
% else:
|
|
11
|
+
self:Get${rpc['class']}${rpc['intf_class']}Object(${render_utils.get_path_arg(rpc["full_path"], False)})
|
|
12
|
+
% endif
|
|
13
|
+
% elif not rpc['virtual']:
|
|
14
|
+
mdb.get_object(self:get_bus(), ${render_utils.make_path_with_params(rpc['full_path'])}, "${rpc['interface']}")
|
|
15
|
+
% else :
|
|
16
|
+
self:Get${rpc['intf_class']}Object()
|
|
17
|
+
% endif
|
|
18
|
+
</%def>
|
|
19
|
+
${make_header('lua')}
|
|
20
|
+
<% has_signal = root['signals']%>
|
|
21
|
+
<% has_interface = root['interfaces']%>
|
|
22
|
+
<% has_definite_path = any((rpc['path'] != '*') for rpc in root['interfaces'])%>
|
|
23
|
+
<% has_virtual = any((rpc['path'] == '*' and rpc['virtual']) for rpc in root['interfaces'])%>
|
|
24
|
+
<% has_implement = any((rpc['implement'] != '') for rpc in root['interfaces'])%>
|
|
25
|
+
<% has_non_virtual = any(((rpc['path'] == '*' or ((render_utils.get_path_params(rpc["full_path"]) or 'paths' in rpc))) and not rpc['virtual'] and rpc['implement'] == '') for rpc in root['interfaces'])%>
|
|
26
|
+
% if has_definite_path or has_implement:
|
|
27
|
+
local mdb = require 'mc.mdb'
|
|
28
|
+
% endif
|
|
29
|
+
local class = require 'mc.class'
|
|
30
|
+
local app_base = require 'mc.client_app_base'
|
|
31
|
+
% if has_signal or has_non_virtual:
|
|
32
|
+
local mdb_service = require 'mc.mdb.mdb_service'
|
|
33
|
+
% endif
|
|
34
|
+
% if has_interface:
|
|
35
|
+
local subscribe_signal = require 'mc.mdb.subscribe_signal'
|
|
36
|
+
% endif
|
|
37
|
+
% if has_signal:
|
|
38
|
+
local org_freedesktop_dbus = require 'sd_bus.org_freedesktop_dbus'
|
|
39
|
+
% endif
|
|
40
|
+
|
|
41
|
+
% if has_signal:
|
|
42
|
+
local match_rule = org_freedesktop_dbus.MatchRule
|
|
43
|
+
% endif
|
|
44
|
+
% if has_virtual:
|
|
45
|
+
local get_virtual_interface_object = mdb_service.get_virtual_interface_object
|
|
46
|
+
% endif
|
|
47
|
+
% if has_non_virtual:
|
|
48
|
+
local get_non_virtual_interface_objects = mdb_service.get_non_virtual_interface_objects
|
|
49
|
+
local foreach_non_virtual_interface_objects = mdb_service.foreach_non_virtual_interface_objects
|
|
50
|
+
% endif
|
|
51
|
+
|
|
52
|
+
## 生成对接口的依赖
|
|
53
|
+
% for intf, intf_data in root['intf_imports'].items():
|
|
54
|
+
% if intf_data['interface'].startswith('bmc.dev.'):
|
|
55
|
+
local ${intf} = require '${project_name}.device_types.${intf}'
|
|
56
|
+
%else:
|
|
57
|
+
local ${intf} = require '${project_name}.json_types.${intf}'
|
|
58
|
+
% endif
|
|
59
|
+
% endfor
|
|
60
|
+
|
|
61
|
+
<%namespace name="default_intf" file="../../../templates/apps/utils/default_intf.lua.mako"/>
|
|
62
|
+
<%namespace name="imports" file="../../../templates/apps/utils/imports.mako"/>
|
|
63
|
+
${imports.render(root)}
|
|
64
|
+
|
|
65
|
+
<%
|
|
66
|
+
ClassName = root['package'] + '_client'
|
|
67
|
+
%>
|
|
68
|
+
---@class ${ClassName}: BasicClient
|
|
69
|
+
local ${ClassName} = class(app_base.Client)
|
|
70
|
+
|
|
71
|
+
% if has_implement:
|
|
72
|
+
${default_intf.add_subs(ClassName)}
|
|
73
|
+
% endif
|
|
74
|
+
## 收集复写类方法订阅接口
|
|
75
|
+
% for rpc in root['interfaces']:
|
|
76
|
+
% if rpc['path'] == '*' and rpc['virtual']:
|
|
77
|
+
|
|
78
|
+
function ${ClassName}:Get${rpc['intf_class']}Object()
|
|
79
|
+
return get_virtual_interface_object(self:get_bus(), '${rpc['interface']}')
|
|
80
|
+
end
|
|
81
|
+
% endif
|
|
82
|
+
%endfor
|
|
83
|
+
## 生成收集类client订阅接口
|
|
84
|
+
% for rpc in root['interfaces']:
|
|
85
|
+
%if rpc['path'] == '*' and not rpc['virtual'] and rpc['implement'] == '':
|
|
86
|
+
|
|
87
|
+
function ${ClassName}:Get${rpc['intf_class']}Objects()
|
|
88
|
+
return get_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', ${'true' if rpc['retry'] else 'false'})
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
function ${ClassName}:Foreach${rpc['intf_class']}Objects(cb)
|
|
92
|
+
return foreach_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', cb, ${'true' if rpc['retry'] else 'false'})
|
|
93
|
+
end
|
|
94
|
+
% endif
|
|
95
|
+
%endfor
|
|
96
|
+
|
|
97
|
+
## 生成默认对象的订阅和访问接口
|
|
98
|
+
% for rpc in root['interfaces']:
|
|
99
|
+
%if rpc['implement'] != '' :
|
|
100
|
+
<% default_path = ClassName +'.'+ rpc['intf_class'] +"_default" %>
|
|
101
|
+
${default_intf.render(default_path, ClassName, rpc['intf_class'], rpc['interface'])}
|
|
102
|
+
% endif
|
|
103
|
+
%endfor
|
|
104
|
+
|
|
105
|
+
% for rpc in root['interfaces']:
|
|
106
|
+
% if 'paths' in rpc and not rpc['virtual']:
|
|
107
|
+
function ${ClassName}:MutipleGet${rpc['intf_class']}Objects(${render_utils.get_path_arg(rpc["paths"], False)})
|
|
108
|
+
% for path in rpc["paths"]:
|
|
109
|
+
local ${render_utils.get_path_namespace_name(loop.index)} = ${render_utils.get_path_namespace(path)}
|
|
110
|
+
%endfor
|
|
111
|
+
return get_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', ${'true' if rpc['retry'] else 'false'}, ${render_utils.get_path_namespace_list(rpc["paths"])})
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
function ${ClassName}:MutipleForeach${rpc['intf_class']}Objects(cb${render_utils.get_path_arg(rpc["paths"])})
|
|
115
|
+
% for path in rpc["paths"]:
|
|
116
|
+
local ${render_utils.get_path_namespace_name(loop.index)} = ${render_utils.get_path_namespace(path)}
|
|
117
|
+
%endfor
|
|
118
|
+
return foreach_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', cb, ${'true' if rpc['retry'] else 'false'}, ${render_utils.get_path_namespace_list(rpc["paths"])})
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
% if rpc['dep_properties']:
|
|
122
|
+
function ${ClassName}:MutipleOn${rpc['intf_class']}PropertiesChanged(cb${render_utils.get_path_arg(rpc["paths"])})
|
|
123
|
+
% for path in rpc["paths"]:
|
|
124
|
+
local ${render_utils.get_path_namespace_name(loop.index)} = ${render_utils.get_path_namespace(path)}
|
|
125
|
+
%endfor
|
|
126
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), ${render_utils.get_path_namespace_list(rpc["paths"])}, cb, '${rpc['interface']}'${render_utils.get_dep_properties(rpc["dep_properties"])})
|
|
127
|
+
end
|
|
128
|
+
%endif
|
|
129
|
+
|
|
130
|
+
function ${ClassName}:MutipleOn${rpc['intf_class']}InterfacesAdded(cb${render_utils.get_path_arg(rpc["paths"])})
|
|
131
|
+
% for path in rpc["paths"]:
|
|
132
|
+
local ${render_utils.get_path_namespace_name(loop.index)} = ${render_utils.get_path_namespace(path)}
|
|
133
|
+
%endfor
|
|
134
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), ${render_utils.get_path_namespace_list(rpc["paths"])}, cb, '${rpc['interface']}')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
function ${ClassName}:MutipleOn${rpc['intf_class']}InterfacesRemoved(cb${render_utils.get_path_arg(rpc["paths"])})
|
|
138
|
+
% for path in rpc["paths"]:
|
|
139
|
+
local ${render_utils.get_path_namespace_name(loop.index)} = ${render_utils.get_path_namespace(path)}
|
|
140
|
+
%endfor
|
|
141
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), ${render_utils.get_path_namespace_list(rpc["paths"])}, cb, '${rpc['interface']}')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
<% continue %>
|
|
145
|
+
% endif
|
|
146
|
+
% if rpc['path'] != '*':
|
|
147
|
+
function ${ClassName}:Get${rpc['name']}Object(${render_utils.get_path_arg(rpc["full_path"], False)})
|
|
148
|
+
%if not rpc['retry']:
|
|
149
|
+
return mdb.get_object(self:get_bus(), ${render_utils.make_path_with_params(rpc['full_path'])}, '${rpc['interface']}')
|
|
150
|
+
%else:
|
|
151
|
+
return mdb.try_get_object(self:get_bus(), ${render_utils.get_object_path(rpc['full_path'])}, '${rpc['interface']}')
|
|
152
|
+
%endif
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
% if render_utils.get_path_params(rpc["full_path"]):
|
|
156
|
+
function ${ClassName}:Get${rpc['intf_class']}Objects()
|
|
157
|
+
return get_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', ${'true' if rpc['retry'] else 'false'}, ${render_utils.get_path_patterns([rpc["full_path"]])})
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
function ${ClassName}:Foreach${rpc['intf_class']}Objects(cb)
|
|
161
|
+
return foreach_non_virtual_interface_objects(self:get_bus(), '${rpc['interface']}', cb, ${'true' if rpc['retry'] else 'false'}, ${render_utils.get_path_patterns([rpc["full_path"]])})
|
|
162
|
+
end
|
|
163
|
+
%endif
|
|
164
|
+
|
|
165
|
+
% if rpc['dep_properties']:
|
|
166
|
+
function ${ClassName}:On${rpc['intf_class']}PropertiesChanged(cb${render_utils.get_path_arg(rpc["full_path"])})
|
|
167
|
+
local path_namespace = ${render_utils.get_path_namespace(rpc['full_path'])}
|
|
168
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), path_namespace, cb, '${rpc['interface']}'${render_utils.get_dep_properties(rpc["dep_properties"])})
|
|
169
|
+
end
|
|
170
|
+
%endif
|
|
171
|
+
|
|
172
|
+
function ${ClassName}:On${rpc['intf_class']}InterfacesAdded(cb${render_utils.get_path_arg(rpc["full_path"])})
|
|
173
|
+
local path_namespace = ${render_utils.get_path_namespace(rpc['full_path'])}
|
|
174
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb, '${rpc['interface']}')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
function ${ClassName}:On${rpc['intf_class']}InterfacesRemoved(cb${render_utils.get_path_arg(rpc["full_path"])})
|
|
178
|
+
local path_namespace = ${render_utils.get_path_namespace(rpc['full_path'])}
|
|
179
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace, cb, '${rpc['interface']}')
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
% else :
|
|
183
|
+
% if rpc['dep_properties']:
|
|
184
|
+
function ${ClassName}:On${rpc['intf_class']}PropertiesChanged(cb)
|
|
185
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb, '${rpc['interface']}'${render_utils.get_dep_properties(rpc["dep_properties"])})
|
|
186
|
+
end
|
|
187
|
+
%endif
|
|
188
|
+
|
|
189
|
+
function ${ClassName}:On${rpc['intf_class']}InterfacesAdded(cb)
|
|
190
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb, '${rpc['interface']}')
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
function ${ClassName}:On${rpc['intf_class']}InterfacesRemoved(cb)
|
|
194
|
+
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb, '${rpc['interface']}')
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
% endif
|
|
198
|
+
%endfor
|
|
199
|
+
% for rpc in root['methods']:
|
|
200
|
+
%if rpc['path'] == '*' and not rpc['virtual']:
|
|
201
|
+
<% continue %>
|
|
202
|
+
% endif
|
|
203
|
+
% for p in render_utils.props(rpc['req']): ## 生成参数注释
|
|
204
|
+
---@param ${p['name']} ${utils_py.do_type_to_lua(p['type'], p['repeated'])}
|
|
205
|
+
% endfor
|
|
206
|
+
% if render_utils.rsp_message(rpc) != 'nil': ## 生成返回值注释
|
|
207
|
+
---@return ${render_utils.rsp_message(rpc)}
|
|
208
|
+
% endif
|
|
209
|
+
% if len(render_utils.params(rpc['req'])) == 0: ## 区分参数个数生成参数, 没有参数的b
|
|
210
|
+
function ${ClassName}:${rpc['name']}(ctx${render_utils.get_path_arg(rpc["full_path"])})
|
|
211
|
+
local obj = ${get_obj(rpc)}
|
|
212
|
+
return ${render_utils.rsp_message(rpc)}.new(obj:${rpc['func_name']}(ctx))
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
function ${ClassName}:P${rpc['name']}(ctx${render_utils.get_path_arg(rpc["full_path"])})
|
|
216
|
+
return pcall(self.${rpc['name']}, self, ctx${render_utils.get_path_arg(rpc["full_path"])})
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
% else: ## 有参数的
|
|
220
|
+
function ${ClassName}:${rpc['name']}(ctx${render_utils.get_path_arg(rpc["full_path"])}, ${render_utils.params(rpc['req'])})
|
|
221
|
+
local req = ${render_utils.req_message(rpc)}.new(${render_utils.params(rpc['req'])}):validate()
|
|
222
|
+
local obj = ${get_obj(rpc)}return ${render_utils.rsp_message(rpc)}.new(obj:${rpc['func_name']}(ctx, req:unpack(true)))
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
function ${ClassName}:P${rpc['name']}(ctx${render_utils.get_path_arg(rpc["full_path"])}, ${render_utils.params(rpc['req'])})
|
|
226
|
+
return pcall(self.${rpc['name']}, self, ctx${render_utils.get_path_arg(rpc["full_path"])}, ${render_utils.params(rpc['req'])})
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
% endif
|
|
230
|
+
% endfor
|
|
231
|
+
## 生成信号订阅接口
|
|
232
|
+
% for signal in root['signals']:
|
|
233
|
+
function ${ClassName}:Subscribe${signal['name']}(cb)
|
|
234
|
+
local sig = match_rule.signal('${signal['signal_name']}', '${signal['interface']}')${'' if signal['path'] == '*' else (':with_path("' +signal['path']+'")')}
|
|
235
|
+
self.signal_slots[#self.signal_slots+1] = subscribe_signal.subscribe(self:get_bus(), sig, cb)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
% endfor
|
|
239
|
+
function ${ClassName}:ctor()
|
|
240
|
+
self.signal_slots = {}
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
---@type ${ClassName}
|
|
244
|
+
return ${ClassName}.new('${root['package']}')
|