openubmc-bingo 0.5.240__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 +12 -0
- bmcgo/bmcgo.py +22 -0
- bmcgo/bmcgo_config.py +176 -0
- bmcgo/cli/__init__.py +10 -0
- bmcgo/cli/cli.py +584 -0
- bmcgo/codegen/__init__.py +14 -0
- bmcgo/codegen/c/__init__.py +9 -0
- bmcgo/codegen/c/annotation.py +52 -0
- bmcgo/codegen/c/argument.py +42 -0
- bmcgo/codegen/c/codegen.py +153 -0
- bmcgo/codegen/c/comment.py +22 -0
- bmcgo/codegen/c/ctype_defination.py +353 -0
- bmcgo/codegen/c/helper.py +87 -0
- bmcgo/codegen/c/interface.py +63 -0
- bmcgo/codegen/c/method.py +82 -0
- bmcgo/codegen/c/property.py +180 -0
- bmcgo/codegen/c/renderer.py +21 -0
- bmcgo/codegen/c/signal.py +64 -0
- bmcgo/codegen/c/template/client.c.mako +145 -0
- bmcgo/codegen/c/template/client.h.mako +36 -0
- bmcgo/codegen/c/template/interface.c.mako +0 -0
- bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
- bmcgo/codegen/c/template/micro_component.c.mako +32 -0
- bmcgo/codegen/c/template/public.c.mako +228 -0
- bmcgo/codegen/c/template/public.h.mako +128 -0
- bmcgo/codegen/c/template/server.c.mako +104 -0
- bmcgo/codegen/c/template/server.h.mako +36 -0
- bmcgo/codegen/lua/.lua-format +7 -0
- bmcgo/codegen/lua/Makefile +101 -0
- bmcgo/codegen/lua/__init__.py +9 -0
- bmcgo/codegen/lua/codegen.py +171 -0
- bmcgo/codegen/lua/proto/Makefile +87 -0
- bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
- bmcgo/codegen/lua/proto/types.proto +52 -0
- bmcgo/codegen/lua/script/check_intfs.py +161 -0
- bmcgo/codegen/lua/script/dto/__init__.py +11 -0
- bmcgo/codegen/lua/script/dto/exception.py +53 -0
- bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
- bmcgo/codegen/lua/script/dto/options.py +33 -0
- bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
- bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
- bmcgo/codegen/lua/script/dto/url_route.py +195 -0
- bmcgo/codegen/lua/script/gen_db_json.py +444 -0
- bmcgo/codegen/lua/script/gen_depends.py +89 -0
- bmcgo/codegen/lua/script/gen_entry.py +263 -0
- bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
- bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
- bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
- bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
- bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
- bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
- bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
- bmcgo/codegen/lua/script/gen_schema.py +302 -0
- bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
- bmcgo/codegen/lua/script/loader/__init__.py +11 -0
- bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
- bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
- bmcgo/codegen/lua/script/lua_format.py +62 -0
- bmcgo/codegen/lua/script/mds_util.py +385 -0
- bmcgo/codegen/lua/script/merge_model.py +330 -0
- bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
- bmcgo/codegen/lua/script/proto_loader.py +47 -0
- bmcgo/codegen/lua/script/proto_plugin.py +140 -0
- bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
- bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
- bmcgo/codegen/lua/script/render_utils/base.py +25 -0
- bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
- bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
- bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
- bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
- bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
- bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
- bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
- bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
- bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
- bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
- bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
- bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
- bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
- bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
- bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
- bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
- bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
- bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
- bmcgo/codegen/lua/script/template.py +166 -0
- bmcgo/codegen/lua/script/types_pb2.py +516 -0
- bmcgo/codegen/lua/script/utils.py +663 -0
- bmcgo/codegen/lua/script/validate.py +80 -0
- bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
- bmcgo/codegen/lua/templates/Makefile +114 -0
- bmcgo/codegen/lua/templates/apps/Makefile +261 -0
- bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
- bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
- bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
- bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
- bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
- bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
- bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
- bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
- bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
- bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
- bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
- bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
- bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
- bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
- bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
- bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
- bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
- bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
- bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
- bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
- bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
- bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
- bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
- bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
- bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
- bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
- bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
- bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
- bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
- bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
- bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
- bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
- bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
- bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
- bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
- bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
- bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
- bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
- bmcgo/component/__init__.py +10 -0
- bmcgo/component/analysis/analysis.py +183 -0
- bmcgo/component/analysis/build_deps.py +165 -0
- bmcgo/component/analysis/data_deps.py +333 -0
- bmcgo/component/analysis/dep-rules.json +912 -0
- bmcgo/component/analysis/dep_node.py +110 -0
- bmcgo/component/analysis/intf_deps.py +163 -0
- bmcgo/component/analysis/intf_validation.py +254 -0
- bmcgo/component/analysis/rule.py +211 -0
- bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
- bmcgo/component/analysis/sr_validation.py +391 -0
- bmcgo/component/build.py +222 -0
- bmcgo/component/component_dt_version_parse.py +348 -0
- bmcgo/component/component_helper.py +114 -0
- bmcgo/component/coverage/__init__.py +11 -0
- bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
- bmcgo/component/coverage/incremental_cov.py +464 -0
- bmcgo/component/deploy.py +110 -0
- bmcgo/component/gen.py +169 -0
- bmcgo/component/package_info.py +236 -0
- bmcgo/component/template/conanbase.py.mako +278 -0
- bmcgo/component/template/conanfile.deploy.py.mako +40 -0
- bmcgo/component/test.py +947 -0
- bmcgo/errors.py +119 -0
- bmcgo/frame.py +217 -0
- bmcgo/functional/__init__.py +10 -0
- bmcgo/functional/analysis.py +96 -0
- bmcgo/functional/bmc_studio_action.py +98 -0
- bmcgo/functional/check.py +185 -0
- bmcgo/functional/conan_index_build.py +251 -0
- bmcgo/functional/config.py +332 -0
- bmcgo/functional/csr_build.py +724 -0
- bmcgo/functional/deploy.py +263 -0
- bmcgo/functional/diff.py +235 -0
- bmcgo/functional/fetch.py +235 -0
- bmcgo/functional/full_component.py +391 -0
- bmcgo/functional/maintain.py +381 -0
- bmcgo/functional/new.py +166 -0
- bmcgo/functional/schema_valid.py +111 -0
- bmcgo/functional/simple_sign.py +104 -0
- bmcgo/functional/upgrade.py +78 -0
- bmcgo/ipmigen/__init__.py +13 -0
- bmcgo/ipmigen/ctype_defination.py +82 -0
- bmcgo/ipmigen/ipmigen.py +309 -0
- bmcgo/ipmigen/template/cmd.c.mako +366 -0
- bmcgo/ipmigen/template/ipmi.c.mako +25 -0
- bmcgo/ipmigen/template/ipmi.h.mako +51 -0
- bmcgo/logger.py +176 -0
- bmcgo/misc.py +117 -0
- bmcgo/target/app.yml +17 -0
- bmcgo/target/install_sdk.yml +15 -0
- bmcgo/target/personal.yml +53 -0
- bmcgo/target/publish.yml +45 -0
- bmcgo/tasks/__init__.py +11 -0
- bmcgo/tasks/download_buildtools_hm.py +124 -0
- bmcgo/tasks/misc.py +15 -0
- bmcgo/tasks/task.py +354 -0
- bmcgo/tasks/task_build_conan.py +714 -0
- bmcgo/tasks/task_build_rootfs_img.py +595 -0
- bmcgo/tasks/task_buildgppbin.py +88 -0
- bmcgo/tasks/task_buildhpm_ext4.py +82 -0
- bmcgo/tasks/task_create_interface_config.py +122 -0
- bmcgo/tasks/task_download_buildtools.py +99 -0
- bmcgo/tasks/task_download_dependency.py +72 -0
- bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
- bmcgo/tasks/task_packet_to_supporte.py +87 -0
- bmcgo/tasks/task_prepare.py +105 -0
- bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
- bmcgo/utils/__init__.py +10 -0
- bmcgo/utils/buffer.py +128 -0
- bmcgo/utils/combine_json_schemas.py +170 -0
- bmcgo/utils/component_post.py +54 -0
- bmcgo/utils/component_version_check.py +86 -0
- bmcgo/utils/config.py +1067 -0
- bmcgo/utils/fetch_component_code.py +232 -0
- bmcgo/utils/install_manager.py +61 -0
- bmcgo/utils/installations/__init__.py +10 -0
- bmcgo/utils/installations/base_installer.py +70 -0
- bmcgo/utils/installations/install_consts.py +30 -0
- bmcgo/utils/installations/install_plans/bingo.yml +11 -0
- bmcgo/utils/installations/install_workflow.py +50 -0
- bmcgo/utils/installations/installers/apt_installer.py +177 -0
- bmcgo/utils/installations/installers/pip_installer.py +46 -0
- bmcgo/utils/installations/version_util.py +100 -0
- bmcgo/utils/mapping_config_patch.py +443 -0
- bmcgo/utils/perf_analysis.py +114 -0
- bmcgo/utils/tools.py +704 -0
- bmcgo/worker.py +417 -0
- openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
- openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
- openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
- openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
- openubmc_bingo-0.5.240.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,485 @@
|
|
|
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
|
+
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
import getopt
|
|
19
|
+
import sys
|
|
20
|
+
import os
|
|
21
|
+
import stat
|
|
22
|
+
import mds_util as utils
|
|
23
|
+
from utils import Utils
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
MAX = "Max"
|
|
27
|
+
DEFAULT = "Default"
|
|
28
|
+
USER = "User"
|
|
29
|
+
OPERATOR = "Operator"
|
|
30
|
+
CALLBACK = "Callback"
|
|
31
|
+
UNSPECIFIED = "Unspecified"
|
|
32
|
+
BASETYPE = ["U8", "U16", "U32", "U64", "S8", "S16", "S32", "S64", "U8[]", "String"]
|
|
33
|
+
PRIORITY = ["Default", "OEM", "ODM", "OBM", "EndUser"]
|
|
34
|
+
ROLE = ["User", "Administrator", "Operator", "Unspecified", "Callback", "OEM"]
|
|
35
|
+
PRIVILEGE = ["UserMgmt", "BasicSetting", "KVMMgmt", "VMMMgmt", "SecurityMgmt",
|
|
36
|
+
"PowerMgmt", "DiagnoseMgmt", "ReadOnly", "ConfigureSelf"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# 请求/响应体参数校验
|
|
40
|
+
def check_message(message_index, message_data, message_len, command_name):
|
|
41
|
+
name = message_data["data"]
|
|
42
|
+
|
|
43
|
+
if message_data.get("baseType") is None:
|
|
44
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}缺少base_type字段配置")
|
|
45
|
+
base_type = message_data["baseType"]
|
|
46
|
+
if base_type not in BASETYPE:
|
|
47
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}配置的baseType参数{base_type}超出取值范围")
|
|
48
|
+
|
|
49
|
+
length = message_data["len"]
|
|
50
|
+
len_num = length[:-1]
|
|
51
|
+
base_type_num = base_type[1:]
|
|
52
|
+
if len_num.lstrip('-').isdigit() and int(len_num) <= 0:
|
|
53
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}配置的len参数{length}有误(须为大于0的整数)")
|
|
54
|
+
if base_type in ["U8", "U16", "U32", "U64", "S8", "S16", "S32", "S64"]:
|
|
55
|
+
if length[-1] == 'B' and int(len_num) * 8 > int(base_type_num):
|
|
56
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}配置的len参数{length}与basetype参数{base_type}不匹配")
|
|
57
|
+
elif length[-1] == 'b' and int(len_num) > int(base_type_num):
|
|
58
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}配置的len参数{length}与basetype参数{base_type}不匹配")
|
|
59
|
+
elif base_type in ["String", "U8[]"]:
|
|
60
|
+
if length == "*" and message_index != message_len - 1:
|
|
61
|
+
raise Exception(f"{command_name}命令请求/响应体中{name}配置的len参数{length}有误(仅当配置参数为请求/响应体中最后一个参数,len才可配置为*)")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def make_properties(package, message, imports, command_name):
|
|
65
|
+
properties = []
|
|
66
|
+
name_check = set()
|
|
67
|
+
length = len(message)
|
|
68
|
+
has_manufacture = False
|
|
69
|
+
manufacturer_index = -1
|
|
70
|
+
for index, prop_data in enumerate(message):
|
|
71
|
+
check_message(index, prop_data, length, command_name)
|
|
72
|
+
|
|
73
|
+
name = prop_data["data"]
|
|
74
|
+
if len(name) > 64:
|
|
75
|
+
raise Exception(f"{command_name}命令中请求/响应体配置的data参数{name}过长")
|
|
76
|
+
if name in name_check:
|
|
77
|
+
raise Exception(f"{command_name}命令中请求/响应体配置的data参数存在重复配置{name}")
|
|
78
|
+
name_check.add(name)
|
|
79
|
+
|
|
80
|
+
manufacturer = False
|
|
81
|
+
if prop_data.get("customizedRule", "") == "Manufacturer":
|
|
82
|
+
if has_manufacture:
|
|
83
|
+
raise Exception(f"{command_name}命令的请求/响应中只允许一个参数配置Manufacturer")
|
|
84
|
+
has_manufacture = True
|
|
85
|
+
manufacturer = True
|
|
86
|
+
manufacturer_index = index
|
|
87
|
+
|
|
88
|
+
if "value" in prop_data:
|
|
89
|
+
int_len = int(prop_data["len"][0])
|
|
90
|
+
value = prop_data["value"]
|
|
91
|
+
if prop_data["len"][-1] == 'B' and \
|
|
92
|
+
re.match('^0x[0-9A-Fa-f]{' + str(int_len * 2) + '}$', value, re.IGNORECASE) is None:
|
|
93
|
+
raise Exception(f"{command_name}命令中参数{name}的value配置值{value}有误(须为16进制且长度与配置的len一致)")
|
|
94
|
+
elif prop_data["len"][-1] == 'b' and len(bin(int(value, 16))) - 2 > int_len:
|
|
95
|
+
raise Exception(f"{command_name}命令中参数{name}的value配置值{value}有误(须为16进制且长度与配置的len一致)")
|
|
96
|
+
if manufacturer:
|
|
97
|
+
raise Exception(f"{command_name}命令中配置了value字段的参数{name}不允许配置Manufacturer")
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
t_property = utils.get_property(name, prop_data, 0)
|
|
101
|
+
t_property["options"]["manufacturer"] = manufacturer
|
|
102
|
+
if "type" in t_property and t_property["type"] not in utils.ALLOW_BASIC_TYPES.values():
|
|
103
|
+
t_property["type"] = t_property["type"].replace("defs_", "")
|
|
104
|
+
if t_property["type"].startswith("def_types."):
|
|
105
|
+
imports.add("model_types/def_types.proto")
|
|
106
|
+
elif not t_property["type"].startswith("defs."):
|
|
107
|
+
imports.add("server/" + t_property.get("interface", "") + ".proto")
|
|
108
|
+
else:
|
|
109
|
+
t_property["type"] = t_property["type"].replace("defs.", package + ".")
|
|
110
|
+
properties.append(t_property)
|
|
111
|
+
|
|
112
|
+
return properties, manufacturer_index
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def make_nested_types(data_value, package, imports, data_name):
|
|
116
|
+
req_properties, req_manufacturer_index = make_properties(package, data_value["req"], imports, data_name)
|
|
117
|
+
req = {
|
|
118
|
+
"package": package,
|
|
119
|
+
"name": "Req",
|
|
120
|
+
"options": {},
|
|
121
|
+
"type": "Message",
|
|
122
|
+
"manufacturer": req_manufacturer_index,
|
|
123
|
+
"properties": req_properties,
|
|
124
|
+
"nested_type": [],
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
rsp_properties, rsp_manufacturer_index = make_properties(package, data_value["rsp"], imports, data_name)
|
|
128
|
+
rsp = {
|
|
129
|
+
"package": package,
|
|
130
|
+
"name": "Rsp",
|
|
131
|
+
"options": {},
|
|
132
|
+
"type": "Message",
|
|
133
|
+
"manufacturer": rsp_manufacturer_index,
|
|
134
|
+
"properties": rsp_properties,
|
|
135
|
+
"nested_type": [],
|
|
136
|
+
}
|
|
137
|
+
return [req, rsp]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_byte_count(data_len):
|
|
141
|
+
if data_len.endswith("B"):
|
|
142
|
+
return int(data_len.split("B")[0]), 0
|
|
143
|
+
if data_len.endswith("b"):
|
|
144
|
+
return 0, int(data_len.split("b")[0])
|
|
145
|
+
return 0, 0
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def get_hex_values(prop_data):
|
|
149
|
+
values = []
|
|
150
|
+
real_hex = prop_data["value"].replace("0x", "")
|
|
151
|
+
if prop_data["len"].endswith("B"):
|
|
152
|
+
str_len = int(prop_data["len"].split("B")[0]) * 2
|
|
153
|
+
if len(real_hex) < str_len:
|
|
154
|
+
real_hex = "0" * (str_len - len(real_hex)) + real_hex
|
|
155
|
+
|
|
156
|
+
values = re.findall(r".{2}", real_hex)
|
|
157
|
+
values.reverse()
|
|
158
|
+
return values
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def make_filters(message):
|
|
162
|
+
filters = []
|
|
163
|
+
temp_filters = []
|
|
164
|
+
bit_count = 0
|
|
165
|
+
for prop_data in message:
|
|
166
|
+
if "value" in prop_data:
|
|
167
|
+
temp_filters += get_hex_values(prop_data)
|
|
168
|
+
filters = filters + temp_filters
|
|
169
|
+
temp_filters = []
|
|
170
|
+
else:
|
|
171
|
+
byte_count, temp_bit_count = get_byte_count(prop_data["len"])
|
|
172
|
+
bit_count += temp_bit_count
|
|
173
|
+
if bit_count >= 8:
|
|
174
|
+
byte_count += 1
|
|
175
|
+
bit_count -= 8
|
|
176
|
+
temp_filters += ["*"] * byte_count
|
|
177
|
+
out = ",".join(filters)
|
|
178
|
+
return out
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def get_type(data_type, data_len, message):
|
|
182
|
+
out_type = ""
|
|
183
|
+
out_unit = "string"
|
|
184
|
+
if data_len in message:
|
|
185
|
+
out_type += ":" + data_len
|
|
186
|
+
else:
|
|
187
|
+
if data_len != "*":
|
|
188
|
+
if not data_len[:-1].isdigit():
|
|
189
|
+
raise Exception(f"命令请求/响应体中参数len配置值{data_len}有误(须为固定长度、'*'或前面出现的参数名称)")
|
|
190
|
+
params = re.compile(r"([0-9]+)([Bb])").findall(data_len)
|
|
191
|
+
out_type += ":" + params[0][0]
|
|
192
|
+
types = {"B": "unit:8", "b": "unit:1"}
|
|
193
|
+
out_unit = types.get(params[0][1], "")
|
|
194
|
+
if data_type == "String":
|
|
195
|
+
out_unit = "string"
|
|
196
|
+
|
|
197
|
+
out_type += "/" + out_unit
|
|
198
|
+
|
|
199
|
+
return out_type
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def make_code(message, data_name):
|
|
203
|
+
code = []
|
|
204
|
+
var_list = []
|
|
205
|
+
for prop_data in message:
|
|
206
|
+
if prop_data.get("data") is None:
|
|
207
|
+
raise Exception(f"{data_name}命令请求/响应体中存在参数缺少data字段配置")
|
|
208
|
+
var_list.append(prop_data["data"])
|
|
209
|
+
|
|
210
|
+
var_name = prop_data["value"] if "value" in prop_data else prop_data["data"]
|
|
211
|
+
name = prop_data["data"]
|
|
212
|
+
if prop_data.get("len") is None:
|
|
213
|
+
raise Exception(f"{data_name}命令请求/响应体中{name}缺少len字段配置")
|
|
214
|
+
code.append(
|
|
215
|
+
var_name + get_type(prop_data["baseType"] if "baseType" in prop_data else None, prop_data["len"], var_list)
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if len(code) == 0:
|
|
219
|
+
return ""
|
|
220
|
+
return "<<" + ", ".join(code) + ">>"
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def trans_priority_map(origin, version):
|
|
224
|
+
if int(version) >= 5:
|
|
225
|
+
priority_map = {
|
|
226
|
+
DEFAULT: True,
|
|
227
|
+
"OEM": True,
|
|
228
|
+
"ODM": True,
|
|
229
|
+
"OBM": True,
|
|
230
|
+
"EndUser": True,
|
|
231
|
+
MAX: True,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return origin if origin in priority_map else DEFAULT
|
|
235
|
+
|
|
236
|
+
priority_map = {
|
|
237
|
+
DEFAULT: "BmcBase",
|
|
238
|
+
"OEM": "OemBase",
|
|
239
|
+
"ODM": "OdmBase",
|
|
240
|
+
"OBM": "OdmBase",
|
|
241
|
+
"EndUser": "CustomBase",
|
|
242
|
+
MAX: MAX,
|
|
243
|
+
}
|
|
244
|
+
if origin not in priority_map:
|
|
245
|
+
origin = DEFAULT
|
|
246
|
+
return priority_map[origin]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def get_sys_locked_policy(policy, name):
|
|
250
|
+
if policy is None:
|
|
251
|
+
return "Allowed"
|
|
252
|
+
policies = {"Allowed", "Forbidden"}
|
|
253
|
+
if policy not in policies:
|
|
254
|
+
raise Exception(f"命令{name}的sysLockedPolicy配置值{policy}不在取值范围内")
|
|
255
|
+
return policy
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def trans_role_map(origin, version):
|
|
259
|
+
if int(version) >= 5:
|
|
260
|
+
role_map = {
|
|
261
|
+
UNSPECIFIED: True,
|
|
262
|
+
CALLBACK: True,
|
|
263
|
+
USER: True,
|
|
264
|
+
OPERATOR: True,
|
|
265
|
+
"Administrator": True,
|
|
266
|
+
"OEM": True,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return origin if origin in role_map else UNSPECIFIED
|
|
270
|
+
|
|
271
|
+
role_map = {
|
|
272
|
+
UNSPECIFIED: "None",
|
|
273
|
+
CALLBACK: CALLBACK,
|
|
274
|
+
USER: USER,
|
|
275
|
+
OPERATOR: OPERATOR,
|
|
276
|
+
"Administrator": "Admin",
|
|
277
|
+
"OEM": "Oem",
|
|
278
|
+
}
|
|
279
|
+
if origin not in role_map:
|
|
280
|
+
origin = UNSPECIFIED
|
|
281
|
+
return role_map[origin]
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def check_duplicate_msg(messages, method_name):
|
|
285
|
+
for method in messages:
|
|
286
|
+
if method["name"] == method_name:
|
|
287
|
+
return True
|
|
288
|
+
return False
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# 为结构体生成message
|
|
292
|
+
def gen_defs(defs, msg_package, packages):
|
|
293
|
+
if msg_package not in packages:
|
|
294
|
+
packages[msg_package] = {"messages": []}
|
|
295
|
+
|
|
296
|
+
package = packages[msg_package]
|
|
297
|
+
for struct_name, struct_data in defs.items():
|
|
298
|
+
msg_name = struct_name
|
|
299
|
+
if not check_duplicate_msg(package["messages"], msg_name):
|
|
300
|
+
update_package(package, msg_name, struct_data, msg_package)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def get_message(msg_name, msg_data, msg_pack):
|
|
304
|
+
has_struct = False
|
|
305
|
+
depends = []
|
|
306
|
+
message = {}
|
|
307
|
+
message_type = utils.get_message_type(msg_data)
|
|
308
|
+
if message_type == 'struct':
|
|
309
|
+
message = utils.get_struct_message(msg_pack, msg_name, msg_data)
|
|
310
|
+
for prop in message.get("properties", []):
|
|
311
|
+
if prop["type"] not in utils.ALLOW_BASIC_TYPES.values():
|
|
312
|
+
prop["type"] = prop["type"].replace("defs.", msg_pack + ".")
|
|
313
|
+
depends.append(prop["type"])
|
|
314
|
+
has_struct = True
|
|
315
|
+
if "options" in message:
|
|
316
|
+
message["options"]["has_struct"] = has_struct
|
|
317
|
+
elif message_type == 'enum':
|
|
318
|
+
message = utils.get_enum_message(msg_pack, msg_name, msg_data)
|
|
319
|
+
else:
|
|
320
|
+
message = utils.get_dict_message(msg_pack, msg_name, msg_data)
|
|
321
|
+
|
|
322
|
+
return message, depends
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def get_depend_message_pos(depend, old_messages):
|
|
326
|
+
index = 1
|
|
327
|
+
for var in old_messages:
|
|
328
|
+
if (var["package"] + "." + var["name"]) == depend:
|
|
329
|
+
return index
|
|
330
|
+
index = index + 1
|
|
331
|
+
|
|
332
|
+
return -1
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# 由于当前模板的限制,依赖必须是顺序的,因此要计算插入的位置
|
|
336
|
+
def update_package(package, msg_name, struct_data, msg_package):
|
|
337
|
+
new_message, depends = get_message(msg_name, struct_data, msg_package)
|
|
338
|
+
last_pos = 0
|
|
339
|
+
for depend in depends:
|
|
340
|
+
pos = get_depend_message_pos(depend, package["messages"])
|
|
341
|
+
if pos != -1:
|
|
342
|
+
last_pos = max(last_pos, pos)
|
|
343
|
+
|
|
344
|
+
package["messages"].insert(last_pos, new_message)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
# cmds参数校验
|
|
348
|
+
def check_cmds_data(name, value):
|
|
349
|
+
if len(name) > 64:
|
|
350
|
+
raise Exception(f"命令{name}的名称过长")
|
|
351
|
+
|
|
352
|
+
netfn = value["netfn"]
|
|
353
|
+
if re.match('^0x[0-9A-Fa-f]{1,2}$', netfn, re.IGNORECASE) is None:
|
|
354
|
+
raise Exception(f"命令{name}中netfn的配置值{netfn}不满足16进制、1字节的格式要求")
|
|
355
|
+
|
|
356
|
+
cmd = value["cmd"]
|
|
357
|
+
if re.match('^0x[0-9A-Fa-f]{1,2}$', cmd, re.IGNORECASE) is None:
|
|
358
|
+
raise Exception(f"命令{name}中cmd的配置值{cmd}不满足16进制、1字节的格式要求")
|
|
359
|
+
|
|
360
|
+
priority = value["priority"]
|
|
361
|
+
if priority not in PRIORITY and Utils.get_lua_codegen_version() >= 5:
|
|
362
|
+
raise Exception(f"命令{name}中priority的配置值{priority}不在取值范围内")
|
|
363
|
+
|
|
364
|
+
role = value.get("role")
|
|
365
|
+
if role is not None and role not in ROLE:
|
|
366
|
+
raise Exception(f"命令{name}中role的配置值{role}不在取值范围内")
|
|
367
|
+
|
|
368
|
+
privilege = value["privilege"] if isinstance(value["privilege"], list) else []
|
|
369
|
+
for item in privilege:
|
|
370
|
+
if item not in PRIVILEGE and Utils.get_lua_codegen_version() >= 5:
|
|
371
|
+
raise Exception(f"命令{name}中privilege的配置值{item}不在取值范围内")
|
|
372
|
+
|
|
373
|
+
sensitive = value.get("sensitive")
|
|
374
|
+
if sensitive is not None and not isinstance(sensitive, bool):
|
|
375
|
+
raise Exception(f"命令{name}中sensitive的配置值{sensitive}不在取值范围内(只可配置为true或false)")
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def make_datas(load_dict, imports, version):
|
|
379
|
+
datas = []
|
|
380
|
+
if load_dict.get("package") is None:
|
|
381
|
+
raise Exception(f"ipmi命令文件中缺少package字段配置")
|
|
382
|
+
if load_dict.get("cmds") is None:
|
|
383
|
+
raise Exception(f"ipmi命令文件中缺少cmds字段配置")
|
|
384
|
+
|
|
385
|
+
for data_name, data_value in load_dict["cmds"].items():
|
|
386
|
+
role = data_value.get("role", data_value["privilege"])
|
|
387
|
+
privilege = data_value["privilege"] if isinstance(data_value["privilege"], list) else []
|
|
388
|
+
|
|
389
|
+
check_cmds_data(data_name, data_value)
|
|
390
|
+
|
|
391
|
+
datas.append(
|
|
392
|
+
{
|
|
393
|
+
"package": load_dict["package"],
|
|
394
|
+
"name": data_name,
|
|
395
|
+
"options": {
|
|
396
|
+
"netfn": int(data_value["netfn"], 16),
|
|
397
|
+
"cmd": int(data_value["cmd"], 16),
|
|
398
|
+
"priority": trans_priority_map(data_value["priority"], version),
|
|
399
|
+
"role": trans_role_map(role, version),
|
|
400
|
+
"privilege": privilege,
|
|
401
|
+
"sensitive": data_value.get("sensitive", False),
|
|
402
|
+
"restricted_channels": data_value.get("restricted_channels", []),
|
|
403
|
+
"decode": make_code(data_value["req"], data_name),
|
|
404
|
+
"encode": make_code(data_value["rsp"], data_name),
|
|
405
|
+
"filters": make_filters(data_value["req"]),
|
|
406
|
+
"sysLockedPolicy": get_sys_locked_policy(data_value.get("sysLockedPolicy", None), data_name)
|
|
407
|
+
},
|
|
408
|
+
"type": "Message",
|
|
409
|
+
"properties": [],
|
|
410
|
+
"nested_type": make_nested_types(data_value, load_dict["package"], imports, data_name),
|
|
411
|
+
}
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
messages = {}
|
|
415
|
+
if "defs" in load_dict:
|
|
416
|
+
gen_defs(load_dict["defs"], load_dict["package"], messages)
|
|
417
|
+
|
|
418
|
+
for pkg_data in messages.values():
|
|
419
|
+
datas.extend(pkg_data["messages"])
|
|
420
|
+
|
|
421
|
+
return datas
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def generate(if_name, of_name, version):
|
|
425
|
+
if not os.path.exists(if_name):
|
|
426
|
+
return
|
|
427
|
+
|
|
428
|
+
load_f = os.fdopen(os.open(if_name, os.O_RDONLY, stat.S_IRUSR), "r")
|
|
429
|
+
|
|
430
|
+
load_dict = json.load(load_f)
|
|
431
|
+
extra_imports = set()
|
|
432
|
+
datas = make_datas(load_dict, extra_imports, version)
|
|
433
|
+
imports = [
|
|
434
|
+
"google/protobuf/descriptor.proto",
|
|
435
|
+
"ipmi_types.proto",
|
|
436
|
+
"types.proto"
|
|
437
|
+
]
|
|
438
|
+
imports.extend(extra_imports)
|
|
439
|
+
dependency = ["types.proto", "ipmi_types.proto"]
|
|
440
|
+
dependency.extend(extra_imports)
|
|
441
|
+
out_dict = {
|
|
442
|
+
"imports": imports,
|
|
443
|
+
"dependency": dependency,
|
|
444
|
+
"data": datas,
|
|
445
|
+
"service": [],
|
|
446
|
+
"filename": "ipmi/ipmi.proto",
|
|
447
|
+
"package": load_dict["package"],
|
|
448
|
+
"options": {},
|
|
449
|
+
}
|
|
450
|
+
utils.save_proto_json(of_name, out_dict)
|
|
451
|
+
load_f.close()
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def usage():
|
|
455
|
+
logging.info("gen_ipmi_json.py -i <inputfile> -o <file>")
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def main(argv):
|
|
459
|
+
m_input = ""
|
|
460
|
+
output = ""
|
|
461
|
+
try:
|
|
462
|
+
opts, _ = getopt.getopt(argv, "hi:o:d:v:", ["help", "input=", "out=", "version="])
|
|
463
|
+
except getopt.GetoptError:
|
|
464
|
+
help()
|
|
465
|
+
return
|
|
466
|
+
for opt, arg in opts:
|
|
467
|
+
if opt in ("-h", "--help"):
|
|
468
|
+
usage()
|
|
469
|
+
return
|
|
470
|
+
elif opt in ("-i", "--input"):
|
|
471
|
+
m_input = arg
|
|
472
|
+
elif opt in ("-o", "--out"):
|
|
473
|
+
output = arg
|
|
474
|
+
elif opt in ("-v", "--version"):
|
|
475
|
+
version = arg
|
|
476
|
+
else:
|
|
477
|
+
raise RuntimeError("不支持的选项: {}".format(opt))
|
|
478
|
+
if not m_input or not output:
|
|
479
|
+
usage()
|
|
480
|
+
return
|
|
481
|
+
generate(m_input, output, version)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
if __name__ == "__main__":
|
|
485
|
+
main(sys.argv[1:])
|
|
@@ -0,0 +1,117 @@
|
|
|
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
|
+
import logging
|
|
15
|
+
import getopt
|
|
16
|
+
import sys
|
|
17
|
+
import mds_util as utils
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def translate_path(path):
|
|
21
|
+
path = path.replace("${", ":")
|
|
22
|
+
return path.replace("}", "")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_package(class_name, class_data):
|
|
26
|
+
if "package" in class_data:
|
|
27
|
+
return class_data["package"]
|
|
28
|
+
else:
|
|
29
|
+
return class_name
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_data_by_class(class_name, class_data):
|
|
33
|
+
properties = []
|
|
34
|
+
index = 1
|
|
35
|
+
datas = []
|
|
36
|
+
for intf in class_data["interfaces"]:
|
|
37
|
+
intfs = intf.split(".")
|
|
38
|
+
properties.append(
|
|
39
|
+
{
|
|
40
|
+
"name": intfs[-1],
|
|
41
|
+
"type": intfs[-1],
|
|
42
|
+
"options": {"interface": intf},
|
|
43
|
+
"id": index,
|
|
44
|
+
"repeated": False,
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
index = index + 1
|
|
48
|
+
datas.append(
|
|
49
|
+
{
|
|
50
|
+
"package": get_package(class_name, class_data),
|
|
51
|
+
"name": class_name,
|
|
52
|
+
"options": {"path": translate_path(class_data["path"])},
|
|
53
|
+
"type": "Message",
|
|
54
|
+
"properties": properties,
|
|
55
|
+
"nested_type": [],
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
return datas, get_package(class_name, class_data)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def generate(if_name, of_name):
|
|
62
|
+
load_f = utils.open_file(if_name)
|
|
63
|
+
|
|
64
|
+
load_dict = json.load(load_f)
|
|
65
|
+
classes = []
|
|
66
|
+
|
|
67
|
+
for class_name, class_data in load_dict.items():
|
|
68
|
+
classes, package = get_data_by_class(class_name, class_data)
|
|
69
|
+
|
|
70
|
+
data = {
|
|
71
|
+
"imports": [
|
|
72
|
+
"google/protobuf/descriptor.proto",
|
|
73
|
+
"ipmi_types.proto",
|
|
74
|
+
"types.proto",
|
|
75
|
+
],
|
|
76
|
+
"dependency": ["types.proto"],
|
|
77
|
+
"data": classes,
|
|
78
|
+
"service": [],
|
|
79
|
+
"package": package,
|
|
80
|
+
"options": {},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
utils.save_proto_json(of_name, data)
|
|
84
|
+
|
|
85
|
+
load_f.close()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def usage():
|
|
89
|
+
logging.info("gen_mdb_json.py -i <inputfile> -o <outfile>")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def main(argv):
|
|
93
|
+
m_input = ""
|
|
94
|
+
output = ""
|
|
95
|
+
try:
|
|
96
|
+
opts, _ = getopt.getopt(argv, "hi:o:d:", ["help", "input=", "out="])
|
|
97
|
+
except getopt.GetoptError:
|
|
98
|
+
help()
|
|
99
|
+
return
|
|
100
|
+
for opt, arg in opts:
|
|
101
|
+
if opt in ("-h", "--help"):
|
|
102
|
+
usage()
|
|
103
|
+
return
|
|
104
|
+
elif opt in ("-i", "--input"):
|
|
105
|
+
m_input = arg
|
|
106
|
+
elif opt in ("-o", "--out"):
|
|
107
|
+
output = arg
|
|
108
|
+
else:
|
|
109
|
+
raise RuntimeError("不支持的选项: {}".format(opt))
|
|
110
|
+
if not m_input or not output:
|
|
111
|
+
usage()
|
|
112
|
+
return
|
|
113
|
+
generate(m_input, output)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == "__main__":
|
|
117
|
+
main(sys.argv[1:])
|