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.

Files changed (28) hide show
  1. bmcgo/__init__.py +1 -1
  2. bmcgo/codegen/lua/codegen.py +23 -0
  3. bmcgo/codegen/lua/script/model_consistency_check.py +242 -0
  4. bmcgo/codegen/lua/script/render_utils/__init__.py +7 -4
  5. bmcgo/codegen/lua/script/render_utils/client_lua.py +1 -1
  6. bmcgo/codegen/lua/script/render_utils/message_lua.py +2 -1
  7. bmcgo/codegen/lua/script/render_utils/service_lua.py +1 -1
  8. bmcgo/codegen/lua/script/utils.py +30 -3
  9. bmcgo/codegen/lua/templates/apps/Makefile +70 -2
  10. bmcgo/codegen/lua/v1/script/render_utils/client_lua.py +108 -0
  11. bmcgo/codegen/lua/v1/script/render_utils/db_lua.py +223 -0
  12. bmcgo/codegen/lua/v1/script/render_utils/model_lua.py +29 -0
  13. bmcgo/codegen/lua/v1/templates/apps/client.lua.mako +244 -0
  14. bmcgo/codegen/lua/v1/templates/apps/db.lua.mako +62 -0
  15. bmcgo/codegen/lua/v1/templates/apps/local_db.lua.mako +184 -0
  16. bmcgo/codegen/lua/v1/templates/apps/message.lua.mako +35 -0
  17. bmcgo/codegen/lua/v1/templates/apps/model.lua.mako +3 -0
  18. bmcgo/codegen/lua/v1/templates/apps/service.lua.mako +8 -47
  19. bmcgo/codegen/lua/v1/templates/apps/utils/mdb_intf.lua.mako +27 -0
  20. bmcgo/codegen/lua/v1/templates/apps/utils/mdb_obj.lua.mako +14 -0
  21. bmcgo/component/coverage/incremental_cov.py +4 -4
  22. bmcgo/tasks/task_build_rootfs_img.py +2 -2
  23. {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/METADATA +1 -1
  24. {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/RECORD +28 -19
  25. /bmcgo/codegen/lua/script/{render_utils/mdb_register.py → mdb_register.py} +0 -0
  26. {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/WHEEL +0 -0
  27. {openubmc_bingo-0.5.254.dist-info → openubmc_bingo-0.5.261.dist-info}/entry_points.txt +0 -0
  28. {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']}')