openubmc-bingo 0.6.45__py3-none-any.whl → 0.6.99__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.
Files changed (96) hide show
  1. bmcgo/__init__.py +1 -1
  2. bmcgo/bmcgo.py +9 -3
  3. bmcgo/bmcgo_config.py +16 -0
  4. bmcgo/cli/cli.py +72 -21
  5. bmcgo/codegen/__init__.py +1 -1
  6. bmcgo/codegen/lua/codegen.py +2 -2
  7. bmcgo/codegen/lua/script/check_intfs.py +1 -0
  8. bmcgo/codegen/lua/script/dto/options.py +1 -0
  9. bmcgo/codegen/lua/script/gen_db_json.py +4 -3
  10. bmcgo/codegen/lua/script/gen_rpc_msg_json.py +78 -11
  11. bmcgo/codegen/lua/script/model_consistency_check.py +1 -1
  12. bmcgo/codegen/lua/script/render_utils/db_lua.py +5 -6
  13. bmcgo/codegen/lua/script/render_utils/model_lua.py +5 -1
  14. bmcgo/codegen/lua/script/template.py +5 -0
  15. bmcgo/codegen/lua/script/utils.py +50 -8
  16. bmcgo/codegen/lua/templates/apps/Makefile +2 -2
  17. bmcgo/codegen/lua/templates/apps/client.lua.mako +1 -1
  18. bmcgo/codegen/lua/templates/apps/model.lua.mako +4 -3
  19. bmcgo/codegen/lua/templates/apps/service.lua.mako +1 -1
  20. bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +4 -0
  21. bmcgo/codegen/lua/templates/new_app_v2/CMakeLists.txt.mako +26 -0
  22. bmcgo/codegen/lua/templates/new_app_v2/conanfile.py.mako +9 -0
  23. bmcgo/codegen/lua/v1/script/render_utils/db_lua.py +5 -6
  24. bmcgo/codegen/lua/v1/script/render_utils/model_lua.py +13 -1
  25. bmcgo/codegen/lua/v1/templates/apps/client.lua.mako +1 -1
  26. bmcgo/codegen/lua/v1/templates/apps/local_db.lua.mako +0 -4
  27. bmcgo/codegen/lua/v1/templates/apps/message.lua.mako +3 -0
  28. bmcgo/codegen/lua/v1/templates/apps/model.lua.mako +3 -0
  29. bmcgo/codegen/lua/v1/templates/apps/utils/mdb_intf.lua.mako +6 -4
  30. bmcgo/component/analysis/analysis.py +9 -4
  31. bmcgo/component/analysis/dep-rules.json +20 -8
  32. bmcgo/component/analysis/dep_node.py +2 -0
  33. bmcgo/component/analysis/intf_validation.py +8 -7
  34. bmcgo/component/analysis/sr_validation.py +5 -4
  35. bmcgo/component/busctl_log_parse/busctl_log_parser.py +809 -0
  36. bmcgo/component/busctl_log_parse/mock_data_save.py +170 -0
  37. bmcgo/component/busctl_log_parse/test_data_save.py +49 -0
  38. bmcgo/component/component_helper.py +29 -0
  39. bmcgo/component/coverage/incremental_cov.py +5 -0
  40. bmcgo/component/fixture/__init__.py +29 -0
  41. bmcgo/component/fixture/auto_case_generator.py +490 -0
  42. bmcgo/component/fixture/busctl_type_converter.py +1081 -0
  43. bmcgo/component/fixture/common_config.py +15 -0
  44. bmcgo/component/fixture/dbus_gateway.py +669 -0
  45. bmcgo/component/fixture/dbus_library.py +250 -0
  46. bmcgo/component/fixture/dbus_mock_utils.py +514 -0
  47. bmcgo/component/fixture/dbus_response_handler.py +138 -0
  48. bmcgo/component/fixture/dbus_signature.py +110 -0
  49. bmcgo/component/template_v2/conanbase.py.mako +1 -5
  50. bmcgo/component/test.py +69 -10
  51. bmcgo/error_analyzer/__init__.py +0 -0
  52. bmcgo/error_analyzer/case_matcher.py +114 -0
  53. bmcgo/error_analyzer/log_parser.py +128 -0
  54. bmcgo/error_analyzer/unified_error_analyzer.py +359 -0
  55. bmcgo/error_cases/cases.yml +59 -0
  56. bmcgo/error_cases/cases_template_valid.json +71 -0
  57. bmcgo/error_cases/conanfile.py +58 -0
  58. bmcgo/frame.py +0 -4
  59. bmcgo/functional/analysis.py +18 -12
  60. bmcgo/functional/bmc_studio_action.py +21 -10
  61. bmcgo/functional/check.py +86 -42
  62. bmcgo/functional/conan_index_build.py +1 -1
  63. bmcgo/functional/config.py +22 -18
  64. bmcgo/functional/csr_build.py +63 -34
  65. bmcgo/functional/deploy.py +4 -3
  66. bmcgo/functional/diff.py +51 -34
  67. bmcgo/functional/full_component.py +16 -5
  68. bmcgo/functional/hpm_signer.py +484 -0
  69. bmcgo/functional/new.py +8 -2
  70. bmcgo/functional/schema_valid.py +111 -15
  71. bmcgo/functional/upgrade.py +6 -6
  72. bmcgo/misc.py +1 -0
  73. bmcgo/tasks/task_build_conan.py +27 -6
  74. bmcgo/tasks/task_build_rootfs_img.py +120 -83
  75. bmcgo/tasks/task_buildgppbin.py +30 -13
  76. bmcgo/tasks/task_buildhpm_ext4.py +5 -3
  77. bmcgo/tasks/task_download_buildtools.py +20 -11
  78. bmcgo/tasks/task_download_dependency.py +29 -20
  79. bmcgo/tasks/task_hpm_envir_prepare.py +32 -53
  80. bmcgo/tasks/task_packet_to_supporte.py +12 -4
  81. bmcgo/tasks/task_prepare.py +1 -1
  82. bmcgo/tasks/task_sign_and_pack_hpm.py +15 -7
  83. bmcgo/utils/component_version_check.py +4 -4
  84. bmcgo/utils/config.py +3 -0
  85. bmcgo/utils/fetch_component_code.py +148 -17
  86. bmcgo/utils/install_manager.py +2 -2
  87. bmcgo/utils/installations/base_installer.py +10 -27
  88. bmcgo/utils/installations/install_plans/studio.yml +3 -0
  89. bmcgo/utils/mapping_config_patch.py +5 -4
  90. bmcgo/utils/tools.py +49 -7
  91. {openubmc_bingo-0.6.45.dist-info → openubmc_bingo-0.6.99.dist-info}/METADATA +1 -1
  92. {openubmc_bingo-0.6.45.dist-info → openubmc_bingo-0.6.99.dist-info}/RECORD +95 -74
  93. bmcgo/tasks/download_buildtools_hm.py +0 -124
  94. {openubmc_bingo-0.6.45.dist-info → openubmc_bingo-0.6.99.dist-info}/WHEEL +0 -0
  95. {openubmc_bingo-0.6.45.dist-info → openubmc_bingo-0.6.99.dist-info}/entry_points.txt +0 -0
  96. {openubmc_bingo-0.6.45.dist-info → openubmc_bingo-0.6.99.dist-info}/top_level.txt +0 -0
bmcgo/__init__.py CHANGED
@@ -9,4 +9,4 @@
9
9
  # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
10
  # See the Mulan PSL v2 for more details.
11
11
 
12
- __version__ = '0.6.45'
12
+ __version__ = '0.6.99'
bmcgo/bmcgo.py CHANGED
@@ -10,13 +10,19 @@
10
10
  # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
11
  # See the Mulan PSL v2 for more details.
12
12
  import sys
13
-
14
- from bmcgo.cli.cli import main
13
+ import shutil
14
+ import os
15
15
 
16
16
 
17
17
  def run():
18
+ from bmcgo import misc
19
+
20
+ shutil.rmtree(misc.CACHE_DIR, ignore_errors=True)
21
+ os.makedirs(misc.CACHE_DIR)
22
+ from bmcgo.cli.cli import main
23
+
18
24
  sys.exit(main(sys.argv[1:]))
19
25
 
20
26
 
21
- if __name__ == '__main__':
27
+ if __name__ == "__main__":
22
28
  run()
bmcgo/bmcgo_config.py CHANGED
@@ -140,6 +140,7 @@ class BmcgoConfig(object):
140
140
 
141
141
  def _bmcgo_config_init(self):
142
142
  """配置初始化"""
143
+ self.bingo_version_range = None
143
144
  cwd = self.cwd
144
145
  if os.path.isfile("frame.py"):
145
146
  self.manifest = BmcgoManifest(os.path.realpath(os.path.join(cwd, "..")), None)
@@ -185,6 +186,9 @@ class BmcgoConfig(object):
185
186
  self.component = BmcgoComp(folder, conf)
186
187
  except (NoSectionError, NoOptionError):
187
188
  log.debug("不是一个合法的组件仓,尝试查找mds/service.json")
189
+
190
+ #检查是否需要升级
191
+ self._bingo_version_check(conf)
188
192
 
189
193
  self._bmcgo_signature_config_load(conf)
190
194
 
@@ -194,6 +198,18 @@ class BmcgoConfig(object):
194
198
  return
195
199
 
196
200
  cwd = os.path.dirname(cwd)
201
+
202
+ def _bingo_version_check(self, conf: configparser.ConfigParser):
203
+ try:
204
+ version_range = conf.get("bingo", "version")
205
+ except Exception as e:
206
+ version_range = ""
207
+ version_range_str = version_range.strip("[").rstrip("]")
208
+ import semver
209
+ if semver.satisfies(__version__, version_range_str):
210
+ return
211
+ else:
212
+ self.bingo_version_range = version_range_str.replace(" ", ",")
197
213
 
198
214
  def _bmcgo_config_load(self):
199
215
  """读取配置"""
bmcgo/cli/cli.py CHANGED
@@ -12,7 +12,6 @@
12
12
  import argparse
13
13
  import inspect
14
14
  import os
15
- import signal
16
15
  import sys
17
16
  import textwrap
18
17
  import importlib
@@ -39,6 +38,8 @@ from bmcgo.frame import Frame
39
38
  from bmcgo.bmcgo_config import BmcgoConfig
40
39
  from bmcgo.utils.tools import Tools
41
40
  from bmcgo.utils.config import Config
41
+ from ..error_analyzer.unified_error_analyzer import UnifiedErrorAnalyzer
42
+
42
43
 
43
44
  cwd = os.getcwd()
44
45
  tools = Tools()
@@ -265,6 +266,12 @@ class Command(object):
265
266
  if command in ["-h", "--help"]:
266
267
  self._show_help()
267
268
  return 0
269
+ # 检查是否需要升级
270
+ if self.bconfig.bingo_version_range:
271
+ result_code = self.bingo_upgrade()
272
+ if result_code == 0:
273
+ log.info("自动升级完成,请重新运行命令")
274
+ return result_code
268
275
  valid_command = self._find_real_command(command)
269
276
  # 命令参数
270
277
  command_args = args[0][1:]
@@ -315,7 +322,14 @@ class Command(object):
315
322
  studio_version = self._bmc_studio_version()
316
323
  if studio_version:
317
324
  log.info("bmc-studio 版本为: %s", studio_version)
318
-
325
+
326
+ def bingo_upgrade(self):
327
+ version_range = self.bconfig.bingo_version_range.replace(",", " ")
328
+ log.info(f"检测到当前版本:{client_version}与约束版本{version_range}不匹配,将自动升级,完成后请重新运行")
329
+ from bmcgo.functional.upgrade import BmcgoCommand as upcommand
330
+ cmd = upcommand(self.bconfig, (["-v", f"bingo{self.bconfig.bingo_version_range}", "-f"]))
331
+ return cmd.run()
332
+
319
333
  def conan_init(self):
320
334
  if misc.conan_v2():
321
335
  tools.run_command("conan profile detect --force")
@@ -374,12 +388,6 @@ class Command(object):
374
388
  if not match:
375
389
  continue
376
390
  import semver
377
- # 临时兼容性措施,强制使用conan1构建
378
- # 背景:开源组件初期未获取平台conan2.0支持,只能构建出conan1的包,但为了上库conan2.0的构建脚本
379
- # 需要提供一个标记用于临时指示强制使用conan1构建
380
- # 待平台版本正式上线后,删除1.60.0判断
381
- if semver.satisfies("1.60.0", match[1]):
382
- break
383
391
  if semver.satisfies("2.13.0", match[1]):
384
392
  need_conan_v2 = True
385
393
  break
@@ -457,14 +465,6 @@ class Command(object):
457
465
  """检查当前环境中正在使用的bmc studio版本,
458
466
  优先通过pip获取,获取不到通过bmc_studio/mds/server获取
459
467
  """
460
- package_info = tools.run_command('pip3 show hw_ibmc_bmc_studio', sudo=True,
461
- command_echo=False, ignore_error=True, capture_output=True)
462
- version = ""
463
- if package_info:
464
- version = package_info.stdout.replace("\n", " ")
465
- match = re.match(r".*([0-9]+\.[0-9]+\.[0-9]+)", version)
466
- if match:
467
- return match.group(1)
468
468
  studio_path = tools.get_studio_path()
469
469
  bmc_studio_conf = os.path.join(f"{studio_path}/mds/service.json")
470
470
  if not os.path.isfile(bmc_studio_conf):
@@ -480,9 +480,9 @@ class Command(object):
480
480
  def _gen_command_group(self):
481
481
  self._command_group = []
482
482
  self._command_group.append((misc.GRP_INTE, self.inte_cmds))
483
- self._command_group.append((misc.GRP_COMP, self.comp_cmds))
484
- self._command_group.append((misc.GRP_CONAN_IDX, self.conan_idx_cmds))
485
483
  self._command_group.append((misc.GRP_IBMC_SDK, self.ibmc_sdk_cmds))
484
+ self._command_group.append((misc.GRP_CONAN_IDX, self.conan_idx_cmds))
485
+ self._command_group.append((misc.GRP_COMP, self.comp_cmds))
486
486
  self._command_group.append((misc.GRP_MISC, self.misc_cmds))
487
487
  self._command_group.append((misc.GRP_STUDIO, self.studio_cmds))
488
488
  return self._command_group
@@ -640,6 +640,12 @@ class Command(object):
640
640
  return False, None
641
641
 
642
642
 
643
+ class ExtraCases:
644
+ def __init__(self, cases_file, cases_name):
645
+ self.cases_file = cases_file
646
+ self.cases_name = cases_name
647
+
648
+
643
649
  def prepare_conan():
644
650
  if misc.conan_v2():
645
651
  return
@@ -666,13 +672,11 @@ def prepare_conan():
666
672
  file_handler.write(yaml.safe_dump(config_data, indent=2, sort_keys=False))
667
673
 
668
674
 
669
- def run(args, command: Command = None):
675
+ def run(args, command: Command = None, extra_cases: ExtraCases = None):
670
676
  """
671
677
  main entry point of the bmcgo application, using a Command to
672
678
  parse parameters
673
679
  """
674
- os.makedirs(misc.CACHE_DIR, exist_ok=True)
675
-
676
680
  try:
677
681
  tools.run_command("whoami", show_log=True)
678
682
  prepare_conan()
@@ -688,8 +692,55 @@ def run(args, command: Command = None):
688
692
  msg = str(exc)
689
693
  log.error(msg)
690
694
  error = -1
695
+
696
+ if error == -1:
697
+ error_analyzer(extra_cases)
698
+
691
699
  return error
692
700
 
693
701
 
702
+ def error_analyzer(extra_cases: ExtraCases):
703
+ base_cases_file = os.path.join(os.path.dirname(__file__), "..", "error_cases", "cases.yml")
704
+ base_cases = merge_local_remote_cases(base_cases_file, "bingo_cases")
705
+ if extra_cases:
706
+ extra_cases = merge_local_remote_cases(extra_cases.cases_file, extra_cases.cases_name)
707
+ base_cases.extend(extra_cases)
708
+ # 使用统一错误分析器
709
+ analyzer = UnifiedErrorAnalyzer(base_cases)
710
+ # 定义要分析的日志源(支持多种格式)
711
+ log_sources = [
712
+ misc.CACHE_DIR, # 整个文件夹
713
+ os.path.join(cwd, "temp", "log"), # 整个文件夹
714
+ ]
715
+ # 分析日志文件和命令失败信息
716
+ analyzer.analyze_errors(
717
+ log_sources=log_sources
718
+ )
719
+
720
+
721
+ def merge_local_remote_cases(local_case_file, remote_case_name):
722
+ with open(local_case_file, "r") as local_case:
723
+ local_case_data = yaml.safe_load(local_case)
724
+ local_version = local_case_data.get("version")
725
+ local_cases = local_case_data.get("cases")
726
+ cases = local_cases
727
+ cmd = f"conan install --requires='{remote_case_name}/[>=1.0.0]@openubmc/stable' -u \
728
+ --deployer-folder=temp -of temp -d direct_deploy"
729
+ _ = tools.run_command(cmd, ignore_error=True)
730
+ remote_case_file = os.path.join(cwd, "temp", "direct_deploy", remote_case_name, "case.yml")
731
+ if os.path.exists(remote_case_file):
732
+ with open(remote_case_file, "r") as remote_case:
733
+ remote_case_data = yaml.safe_load(remote_case)
734
+ remote_version = remote_case_data.get("version")
735
+ remote_cases = remote_case_data.get("cases")
736
+ from packaging import version
737
+ remote_v = version.parse(remote_version)
738
+ local_v = version.parse(local_version)
739
+ if remote_v > local_v:
740
+ for k, v in remote_cases.items():
741
+ cases[k] = v
742
+ return list(cases.values())
743
+
744
+
694
745
  def main(args):
695
746
  return run(args)
bmcgo/codegen/__init__.py CHANGED
@@ -11,4 +11,4 @@
11
11
 
12
12
  # 非常重要,修改bmcgo后如果自动生成代码有变更的,必须变更__version__字段
13
13
  # 该版本号会传入mako渲染,在自动生成变更时需要做到向下兼容,确保代码自动生成功能OK
14
- __version__ = 18
14
+ __version__ = 20
@@ -134,7 +134,7 @@ class CodeGen(object):
134
134
  package = self.get_mdb_interface_package()
135
135
  cmd = ["conan", "install", f"--requires={package}", f"-of={temp_dir}", "--build=missing", "-d", "direct_deploy",
136
136
  f"--deployer-folder={temp_dir}"]
137
- cmd += ["-pr=profile.dt.ini"]
137
+ cmd += ["-pr=profile.dt.ini", "-pr:b=profile.dt.ini"]
138
138
  if self.remote:
139
139
  cmd += ["-r", self.remote]
140
140
  subprocess.call(cmd)
@@ -153,7 +153,7 @@ class CodeGen(object):
153
153
 
154
154
  cmd = ["conan", "install", f"--requires={package}", f"-of={temp_dir}", "--build=missing", "-d", "direct_deploy",
155
155
  "--update", f"--deployer-folder={temp_dir}"]
156
- cmd += ["-pr=profile.dt.ini"]
156
+ cmd += ["-pr=profile.dt.ini", "-pr:b=profile.dt.ini"]
157
157
  if self.remote:
158
158
  cmd += ["-r", self.remote]
159
159
 
@@ -33,6 +33,7 @@ class IntfPool:
33
33
  self.add_from_service(os.path.join(root, file))
34
34
  if file == "model.json":
35
35
  self.add_from_model(os.path.join(root, file))
36
+ self.pool["Properties"].add("bmc.kepler.Object.Properties")
36
37
 
37
38
  if project_name == 'hwproxy':
38
39
  for root, _, files in os.walk(os.path.join(mdb_path, "intf/mdb/bmc/dev")):
@@ -18,6 +18,7 @@ class Options:
18
18
  self.source_file_path: str = options.source_file_path
19
19
  self.template_name: str = options.template_name
20
20
  self.output_file_path: str = options.output_file_path
21
+ self.ignore_empty_input: bool = options.ignore_empty_input
21
22
  self.enable_auto_merge: bool = options.enable_auto_merge
22
23
  self.project_name = options.project_name
23
24
  self.version = options.version
@@ -380,7 +380,7 @@ def rectify_local_db(historical_local_db_file, out_dict):
380
380
  table_info["properties"] = new_props
381
381
 
382
382
 
383
- def save_json_file(is_local, load_dict, historical_local_db_file, of_name, disable_gen=False):
383
+ def save_json_file(is_local, load_dict, historical_local_db_file, of_name, disable_gen):
384
384
  package = of_name.split("/")[-2]
385
385
  extra_imports = set()
386
386
  datas = make_datas(load_dict, package, extra_imports, is_local)
@@ -420,8 +420,9 @@ def generate(if_name, historical_local_db_file, of_name):
420
420
  load_dict = json.load(load_f)
421
421
  load_f.close()
422
422
  disable_mem_db_gen = Utils.get_lua_codegen_version() >= 7 and not Utils.check_model_need_mem_db(load_dict)
423
- save_json_file(False, load_dict, historical_local_db_file, of_name, disable_gen=disable_mem_db_gen) # 保存普通持久化的表
424
- save_json_file(True, load_dict, historical_local_db_file, of_name) # 保存本地持久化的表
423
+ save_json_file(False, load_dict, historical_local_db_file, of_name, disable_mem_db_gen) # 保存普通持久化的表
424
+ disable_local_db_gen = Utils.get_lua_codegen_version() >= 19 and not Utils.check_model_need_local_db(load_dict)
425
+ save_json_file(True, load_dict, historical_local_db_file, of_name, disable_local_db_gen) # 保存本地持久化的表
425
426
 
426
427
 
427
428
  def usage():
@@ -16,6 +16,7 @@ import getopt
16
16
  import sys
17
17
  import os
18
18
  import stat
19
+ from collections import defaultdict
19
20
  import mds_util as utils
20
21
  from utils import Utils
21
22
 
@@ -43,6 +44,15 @@ PROPERTY_FLAGS = {
43
44
  OPTIONS = 'options'
44
45
 
45
46
 
47
+ def modify_common_interface_messages(messages):
48
+ intf_map = Utils.get_unique_intf_map()
49
+ for intf_name, require_path in Utils.get_common_interface_require_paths().items():
50
+ unique_intf_name = intf_map.get(intf_name)
51
+ if unique_intf_name and unique_intf_name in messages:
52
+ messages[unique_intf_name]['require_path'] = require_path
53
+ messages[unique_intf_name]['disable_gen'] = True
54
+
55
+
46
56
  def is_struct(prop_data):
47
57
  if 'baseType' not in prop_data:
48
58
  return True
@@ -166,8 +176,9 @@ def save_msg(intfs, out_dir, project_name):
166
176
  "package": pkg_name,
167
177
  "options": {},
168
178
  "filename": file_name,
169
- "require_path": f"{project_name}.{require_dir}.{pkg_name}",
179
+ "require_path": pkg_data.get("require_path", f"{project_name}.{require_dir}.{pkg_name}"),
170
180
  "intf": pkg_data["data"] if "data" in pkg_data else {},
181
+ "disable_gen": pkg_data.get("disable_gen", False)
171
182
  }
172
183
  utils.save_proto_json(f"{new_out_dir}/{file_name}.json", datas)
173
184
 
@@ -219,7 +230,7 @@ def update_package(package, msg_name, struct_data, msg_package, imports):
219
230
 
220
231
 
221
232
  # 为结构体生成message
222
- def gen_defs(defs, msg_package, packages, imports=None):
233
+ def gen_defs(defs, msg_package, packages, imports=None, package_filter=None):
223
234
  if imports is None:
224
235
  imports = {}
225
236
 
@@ -228,6 +239,8 @@ def gen_defs(defs, msg_package, packages, imports=None):
228
239
 
229
240
  package = packages[msg_package]
230
241
  for struct_name, struct_data in defs.items():
242
+ if package_filter and not package_filter.get("defs", {}).get(struct_name, True):
243
+ continue
231
244
  msg_name = struct_name
232
245
  if not check_duplicate_msg(package["messages"], msg_name):
233
246
  update_package(package, msg_name, struct_data, msg_package, imports)
@@ -265,7 +278,7 @@ def convert_property_options(intf, property_name: str, options_data: dict):
265
278
  return flags
266
279
 
267
280
 
268
- def generate_message(intf_data, intf, packages, imports):
281
+ def generate_message(intf_data, intf, packages, imports, package_filter=None):
269
282
  msg_package = Utils.get_unique_intf_name(intf)
270
283
 
271
284
  if msg_package not in packages:
@@ -273,7 +286,7 @@ def generate_message(intf_data, intf, packages, imports):
273
286
  package = packages[msg_package]
274
287
  package["data"] = {"name": intf, "data": intf_data}
275
288
 
276
- if "methods" in intf_data:
289
+ if "methods" in intf_data and (not package_filter or package_filter.get("methods")):
277
290
  for method_name, method_data in intf_data["methods"].items():
278
291
  req_name = method_name + "Req"
279
292
  rsp_name = method_name + "Rsp"
@@ -285,14 +298,14 @@ def generate_message(intf_data, intf, packages, imports):
285
298
  update_package(package, rsp_name, get_rsp(
286
299
  method_data), msg_package, imports)
287
300
 
288
- if "signals" in intf_data:
301
+ if "signals" in intf_data and (not package_filter or package_filter.get("signals")):
289
302
  for signal_name, signal_data in intf_data["signals"].items():
290
303
  signature_name = signal_name + "Signature"
291
304
  if not check_duplicate_msg(package["messages"], signature_name):
292
305
  update_package(package, signature_name,
293
306
  signal_data, msg_package, imports)
294
307
 
295
- if "properties" in intf_data:
308
+ if "properties" in intf_data and (not package_filter or package_filter.get("properties")):
296
309
  for property_name, property_data in intf_data["properties"].items():
297
310
  if not check_duplicate_msg(package["messages"], property_name):
298
311
  update_package(package, property_name,
@@ -365,6 +378,7 @@ def gen_service_msg(model_merged_file, of_name, mdb_path, project_name):
365
378
  messages = {}
366
379
  imports = {}
367
380
  get_service_messages(mdb_path, load_dict, messages, imports)
381
+ modify_common_interface_messages(messages)
368
382
  save_msg(messages, of_name, project_name)
369
383
  load_f.close()
370
384
 
@@ -387,15 +401,57 @@ def gen_model_msg(model_merged_file, of_name):
387
401
  load_f.close()
388
402
 
389
403
 
390
- def gen_client_msg_intf(intf_json, intf, messages):
404
+ def gen_client_msg_intf(intf_json, intf, messages, package_filter=None):
391
405
  imports = {}
392
406
  for intf_name, intf_data in intf_json.items():
393
407
  if intf_name == "defs":
394
- gen_defs(intf_data, Utils.get_unique_intf_name(intf), messages)
408
+ gen_defs(intf_data, Utils.get_unique_intf_name(intf), messages, None, package_filter)
395
409
  else:
396
410
  prepare_intf_data(intf_json, intf_name)
397
411
  prepare_virutal(intf_data)
398
- generate_message(intf_data, intf_name, messages, imports)
412
+ generate_message(intf_data, intf_name, messages, imports, package_filter)
413
+
414
+
415
+ def parse_ref_items(input_data, refs):
416
+ for key, value in input_data.items():
417
+ if key != "$ref":
418
+ if isinstance(value, dict):
419
+ parse_ref_items(value, refs)
420
+ continue
421
+ if isinstance(value, str) and value.startswith("#/defs/"):
422
+ refs[value.replace("#/defs/", "")] = input_data.get("baseType") == "Enum"
423
+
424
+
425
+ def set_def_enbale_gen(input_data, defs_enable_gen, enabled):
426
+ refs = dict()
427
+ parse_ref_items(input_data, refs)
428
+ for ref, is_enum in refs.items():
429
+ if ref in defs_enable_gen:
430
+ defs_enable_gen[ref] = enabled or is_enum
431
+
432
+
433
+ def parse_interface_defs(intf_json, package_filter):
434
+ defs_data = intf_json.get("defs", {})
435
+ if not defs_data:
436
+ return {}
437
+ defs_enable_gen = {def_name: False for def_name in defs_data.keys()}
438
+ for intf_name, intf_data in intf_json.items():
439
+ if intf_name == "defs":
440
+ continue
441
+ for category, enable_gen in package_filter.items():
442
+ for item_data in intf_data.get(category, {}).values():
443
+ # 属性、方法、信号如果需要生成校验器,它们引用的自定义类型也需要生成校验器
444
+ # 枚举类型可能被用于属性默认值,也需要生成
445
+ set_def_enbale_gen(item_data, defs_enable_gen, enable_gen)
446
+
447
+ for def_name, def_data in defs_data.items():
448
+ if defs_enable_gen.get(def_name):
449
+ # 自定义类型如果需要生成校验器,它们引用的其它自定义类型也需要生成校验器
450
+ set_def_enbale_gen(def_data, defs_enable_gen, True)
451
+ # 没有被资源协作接口引用的枚举类型,不应该生成代码。但部分组件存在使用json_types文件的枚举定义,这里先做兼容处理
452
+ if utils.get_message_type(def_data) == 'enum':
453
+ defs_enable_gen[def_name] = True
454
+ return defs_enable_gen
399
455
 
400
456
 
401
457
  def gen_client_msg(service_file, output, mdb_path, project_name):
@@ -412,8 +468,19 @@ def gen_client_msg(service_file, output, mdb_path, project_name):
412
468
  intf_json = utils.get_intf(intf, mdb_path)
413
469
  if "implement" in intf_json[intf]:
414
470
  intf_json = utils.generate_default(intf_json, mdb_path)
415
- gen_client_msg_intf(intf_json, intf, messages)
416
-
471
+ package_filter = None
472
+ if Utils.get_lua_codegen_version() >= 19:
473
+ # 客户端用到的接口,不需要生成属性校验器、信号参数校验器,只需要生成方法参数校验器
474
+ # package_filter里面True表示需要生成,False表示不需要生成
475
+ package_filter = {
476
+ "properties": False,
477
+ "methods": True,
478
+ "signals": False
479
+ }
480
+ package_filter["defs"] = parse_interface_defs(intf_json, package_filter)
481
+ gen_client_msg_intf(intf_json, intf, messages, package_filter)
482
+
483
+ modify_common_interface_messages(messages)
417
484
  save_msg(messages, output, project_name)
418
485
  load_f.close()
419
486
 
@@ -154,10 +154,10 @@ def check_intf_consistency(mdb_intf, complete_intf, class_name, intf_name):
154
154
 
155
155
  def check_model_consistency(class_name, complete_model, mdb_obj, mdb_path):
156
156
  intf_complete = set(complete_model["interfaces"].keys())
157
+ intf_complete.discard(OBJECT_PROPERTIES_INTERFACE)
157
158
  intf_mdb = set(mdb_obj[class_name]["interfaces"])
158
159
  if intf_complete != intf_mdb:
159
160
  intf_only_in_mds = intf_complete - intf_mdb
160
- intf_only_in_mds.discard(OBJECT_PROPERTIES_INTERFACE)
161
161
  if intf_only_in_mds:
162
162
  raise RuntimeError(f"组件模型中类{class_name}的接口{intf_only_in_mds}未在mdb_interface中定义"
163
163
  f",请检查model.json与mdb_interface定义"
@@ -206,12 +206,11 @@ class DbLuaUtils(Base, Utils):
206
206
  return result + "}"
207
207
  value_name = Utils(self.data, self.options).enum_value_name(types["name"], d_val)
208
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}']]"
209
+ if prop.get('repeated') and not isinstance(d_val, list):
210
+ raise RuntimeError(f"model.json中类{class_name}的属性{prop['name']}默认值{d_val}类型与属性类型不一致")
211
+ if isinstance(d_val, list) or isinstance(d_val, dict):
212
+ json_str = json.dumps(d_val).replace("'", "''")
213
+ return f"[['{json_str}']]"
215
214
  if type_name == "string" or type_name == 'bytes':
216
215
  return f'"\'{d_val}\'"'
217
216
  if type_name == "bool":
@@ -215,6 +215,9 @@ class ModelLuaUtils(Base, Utils):
215
215
  def get_mdb_prop_configs(self, msg):
216
216
  string = '{'
217
217
  for (interface, intf_msg) in msg['interfaces'].items():
218
+ if Utils.get_lua_codegen_version() == 19 and interface == 'bmc.kepler.Object.Properties':
219
+ string += f"['{interface}'] = mdb.OBJECT_PROPERTIES_INTERFACE_PROP_CONFIGS,"
220
+ continue
218
221
  if not self.has_properties(intf_msg):
219
222
  continue
220
223
  intf_name = self.get_intf_name(interface, intf_msg)
@@ -455,7 +458,8 @@ class ModelLuaUtils(Base, Utils):
455
458
  for (interface, intf_msg) in msg.get('interfaces', {}).items():
456
459
  intf_name = self.get_intf_name(interface, intf_msg)
457
460
  intf_type = self.get_intf_type(intf_name)
458
- types[intf_type] = f"local {intf_type} = require '{project_name}.json_types.{intf_name}'\n"
461
+ path = Utils.get_interface_require_path(interface, project_name, intf_name)
462
+ types[intf_type] = f"local {intf_type} = require '{path}'\n"
459
463
  return types
460
464
 
461
465
  def render_types(self, project_name, root):
@@ -52,6 +52,9 @@ def parse_input_args() -> Options:
52
52
  parser.add_argument("-v", "--version", dest="version",
53
53
  help="version",
54
54
  default=-1)
55
+ parser.add_argument("--ignore_empty_input", dest="ignore_empty_input",
56
+ help="Whether to stop generating result file when input is empty",
57
+ action=misc.STORE_TRUE, default=False)
55
58
  parser.add_argument("--enable_auto_merge", dest="enable_auto_merge",
56
59
  help="Whether result files are automatically combined when customized.",
57
60
  action=misc.STORE_TRUE, default=False)
@@ -130,6 +133,8 @@ def generate(options: Options):
130
133
  if os.path.exists(options.output_file_path):
131
134
  os.remove(options.output_file_path)
132
135
  load_imports(data, options)
136
+ if not data and options.ignore_empty_input and utils.Utils.get_lua_codegen_version() >= 19:
137
+ return
133
138
  os.makedirs(os.path.dirname(options.output_file_path), exist_ok=True)
134
139
  output_file = os.fdopen(os.open(options.output_file_path,
135
140
  os.O_WRONLY | os.O_CREAT | os.O_TRUNC, stat.S_IWUSR | stat.S_IRUSR), 'w')
@@ -86,7 +86,26 @@ class Utils:
86
86
  'general_hardware',
87
87
  'lsw',
88
88
  'manufacture',
89
- 'account'
89
+ 'account',
90
+ 'spdm'
91
+ }
92
+
93
+ COMMON_INTERFACE_REQUIRE_PATHS = {
94
+ 'bmc.kepler.MicroComponent': 'mdb.bmc.kepler.MicroComponentInterface',
95
+ 'bmc.kepler.MicroComponent.ConfigManage': 'mdb.bmc.kepler.MicroComponent.ConfigManageInterface',
96
+ 'bmc.kepler.MicroComponent.Debug': 'mdb.bmc.kepler.MicroComponent.DebugInterface',
97
+ 'bmc.kepler.MicroComponent.Performance': 'mdb.bmc.kepler.MicroComponent.PerformanceInterface',
98
+ 'bmc.kepler.MicroComponent.Reboot': 'mdb.bmc.kepler.MicroComponent.RebootInterface',
99
+ 'bmc.kepler.MicroComponent.Reset': 'mdb.bmc.kepler.MicroComponent.ResetInterface',
100
+ 'bmc.kepler.Object.Properties': 'mdb.bmc.kepler.Object.PropertiesInterface',
101
+ 'bmc.kepler.Release.Maintenance': 'mdb.bmc.kepler.Release.MaintenanceInterface',
102
+ 'bmc.kepler.TaskService.Task': 'mdb.bmc.kepler.TaskService.TaskInterface'
103
+ }
104
+
105
+ # 不依赖新版本lua框架的公共接口
106
+ COMMON_INTERFACE_REQUIRE_PATHS_LIMITED = {
107
+ 'bmc.kepler.Object.Properties': 'mdb.bmc.kepler.Object.PropertiesInterface',
108
+ 'bmc.kepler.TaskService.Task': 'mdb.bmc.kepler.TaskService.TaskInterface'
90
109
  }
91
110
 
92
111
  def __init__(self, data: dict, options: Options):
@@ -253,7 +272,7 @@ class Utils:
253
272
  {6}'''
254
273
  project_name = os.getenv('PROJECT_NAME')
255
274
  if Utils.get_lua_codegen_version() >= 8 and project_name in Utils.OPEN_PROJECTS:
256
- header = '''{5}Copyright (c) 2024 Huawei Technologies Co., Ltd.
275
+ header = '''{5}Copyright (c) {0} Huawei Technologies Co., Ltd.
257
276
  {4}openUBMC is licensed under Mulan PSL v2.
258
277
  {4}You can use this software according to the terms and conditions of the Mulan PSL v2.
259
278
  {4}You may obtain a copy of Mulan PSL v2 at:
@@ -281,7 +300,14 @@ class Utils:
281
300
  if "tableName" in class_data and class_data.get("tableLocation") != "Local":
282
301
  return True
283
302
  return False
284
-
303
+
304
+ @staticmethod
305
+ def check_model_need_local_db(model_json: dict):
306
+ for class_data in model_json.values():
307
+ if "tableName" in class_data and class_data.get("tableLocation") == "Local":
308
+ return True
309
+ return False
310
+
285
311
  @staticmethod
286
312
  def has_db(root: dict):
287
313
  return Utils.check_need_mem_db(root) or Utils.check_local_poweroff_db(root) or \
@@ -348,15 +374,31 @@ class Utils:
348
374
  return Utils.get_unique_intf_name(full_intf_name) + "." + slices[-1]
349
375
 
350
376
  @staticmethod
351
- def get_unique_intf_name(intf):
352
- check_intfs = Path(__file__).parent.parent.joinpath("temp").joinpath("check_intfs.json")
377
+ def get_unique_intf_map():
378
+ check_intfs = Path(__file__).parent.parent.joinpath('temp').joinpath('check_intfs.json')
353
379
  with open(check_intfs, 'r') as check_intfs_fp:
354
- intf_map = json.load(check_intfs_fp)
380
+ return json.load(check_intfs_fp)
355
381
 
382
+ @staticmethod
383
+ def get_unique_intf_name(intf):
356
384
  slices = intf.split('.')
357
- if slices[-1] == "Default":
385
+ if slices[-1] == 'Default':
358
386
  return slices[-2] + slices[-1]
359
- return intf_map.get(intf, slices[-1])
387
+ return Utils.get_unique_intf_map().get(intf, slices[-1])
388
+
389
+ @staticmethod
390
+ def get_common_interface_require_paths():
391
+ gen_version = Utils.get_lua_codegen_version()
392
+ if gen_version < 19:
393
+ return {}
394
+ if gen_version == 19:
395
+ return Utils.COMMON_INTERFACE_REQUIRE_PATHS
396
+ return Utils.COMMON_INTERFACE_REQUIRE_PATHS_LIMITED
397
+
398
+ @staticmethod
399
+ def get_interface_require_path(intf_name, project_name, unique_intf_name):
400
+ fallback = f'{project_name}.json_types.{unique_intf_name}'
401
+ return Utils.get_common_interface_require_paths().get(intf_name, fallback)
360
402
 
361
403
  @staticmethod
362
404
  def get_files(path):
@@ -80,7 +80,7 @@ message: $(foreach v, $(MESSAGE_FILES), $(GEN_OUT_DIR)/$(v).lua)
80
80
  define MAKE_DATAS
81
81
  $$(GEN_OUT_DIR)/$(1).lua: ${PROTO_OUT_DIR}/$(1).json $${TEMPLATE_BIN} datas.lua.mako
82
82
  @mkdir -p $$(dir $$@)
83
- python3 $${TEMPLATE_BIN} -d ${PROTO_DIR} -j ${PROTO_OUT_DIR} -n ${PROJECT_NAME} -i ${PROTO_OUT_DIR}/$(1).json -f ${LUA_FORMATER} -t datas.lua.mako -o $$@
83
+ python3 $${TEMPLATE_BIN} -d ${PROTO_DIR} -j ${PROTO_OUT_DIR} -n ${PROJECT_NAME} -i ${PROTO_OUT_DIR}/$(1).json -f ${LUA_FORMATER} -t datas.lua.mako --ignore_empty_input -o $$@
84
84
  endef
85
85
  $(foreach v, $(YAML_FILES), $(eval $(call MAKE_DATAS,$(v))))
86
86
  datas: $(foreach v, $(YAML_FILES), $(GEN_OUT_DIR)/$(v).lua)
@@ -89,7 +89,7 @@ define MAKE_CONF_DATAS
89
89
  $$(GEN_OUT_DIR)/$(1).lua: ${CONF_DIR}/$(1).yaml $${TEMPLATE_BIN} datas.lua.mako
90
90
  @mkdir -p $$(dir $$@)
91
91
  python3 ${YAML_TO_JSON_BIN} -i ${CONF_DIR}/$(1).yaml -b ${CONF_DIR} -o ${PROTO_OUT_DIR}/$(1).json
92
- python3 $${TEMPLATE_BIN} -d ${CONF_DIR} -j ${PROTO_OUT_DIR} -n ${PROJECT_NAME} -i ${PROTO_OUT_DIR}/$(1).json -f ${LUA_FORMATER} -t datas.lua.mako -o $$@
92
+ python3 $${TEMPLATE_BIN} -d ${CONF_DIR} -j ${PROTO_OUT_DIR} -n ${PROJECT_NAME} -i ${PROTO_OUT_DIR}/$(1).json -f ${LUA_FORMATER} -t datas.lua.mako --ignore_empty_input -o $$@
93
93
  endef
94
94
  $(foreach v, $(YAML_FILES_CONF), $(eval $(call MAKE_CONF_DATAS,$(v))))
95
95
  datas_conf: $(foreach v, $(YAML_FILES_CONF), $(GEN_OUT_DIR)/$(v).lua)