feat: sap-cli skill v2.1.0 — self-contained distributable package
- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types) - references/: tool constraints + error handling (self-contained) - scripts/setup.py: one-click install/config/verify - SKILL.md: full command reference + dual-platform install guide - VERSION: 2.1.0 Built from D:/Codespace/sap-cli via scripts/pack_skill.py
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""sapcli 命令行解析与输出模块。"""
|
||||
@@ -0,0 +1,167 @@
|
||||
"""sap-cli 应用入口:解析参数、初始化连接、路由命令。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import requests
|
||||
|
||||
from sapcli.config import load_config
|
||||
from sapcli.client import ADTClient
|
||||
from sapcli.commands import (
|
||||
cmd_create,
|
||||
cmd_delete,
|
||||
cmd_download,
|
||||
cmd_info,
|
||||
cmd_init,
|
||||
cmd_refresh,
|
||||
cmd_sync,
|
||||
cmd_sync_all,
|
||||
cmd_config,
|
||||
cmd_list,
|
||||
cmd_whereused,
|
||||
cmd_search,
|
||||
cmd_transport,
|
||||
cmd_check,
|
||||
cmd_format,
|
||||
cmd_diff,
|
||||
cmd_package,
|
||||
cmd_cds,
|
||||
cmd_analyze,
|
||||
cmd_scaffold,
|
||||
cmd_show_table,
|
||||
cmd_read_table,
|
||||
cmd_run_program,
|
||||
cmd_activate,
|
||||
)
|
||||
from sapcli.auth import cmd_auth_login, cmd_auth_logout, cmd_auth_status
|
||||
from sapcli.exceptions import SapCliError, ConfigError
|
||||
from sapcli.cli.parser import build_parser
|
||||
|
||||
|
||||
def _setup_encoding() -> None:
|
||||
"""确保 stdout/stderr 使用 UTF-8 编码。"""
|
||||
if hasattr(sys.stdout, "buffer"):
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
|
||||
if hasattr(sys.stderr, "buffer"):
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")
|
||||
|
||||
|
||||
def _setup_logging() -> None:
|
||||
"""配置日志(写入文件,不影响 stdout)。"""
|
||||
log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "log")
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
log_file = os.path.join(log_dir, "adt_tools.log")
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s | %(levelname)-7s | %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler(log_file, encoding="utf-8", mode="a"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def _suppress_ssl_warnings() -> None:
|
||||
"""禁用 urllib3 的 InsecureRequestWarning。"""
|
||||
requests.packages.urllib3.disable_warnings(
|
||||
requests.packages.urllib3.exceptions.InsecureRequestWarning
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""sap-cli 主入口。"""
|
||||
_setup_encoding()
|
||||
_setup_logging()
|
||||
_suppress_ssl_warnings()
|
||||
|
||||
parser = build_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.command:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
# config 命令不需要 SAP 连接
|
||||
if args.command == "config":
|
||||
cmd_config(args)
|
||||
return
|
||||
|
||||
# auth 不需要 SAP 连接
|
||||
if args.command == "auth":
|
||||
auth_action = getattr(args, "auth_action", None)
|
||||
if auth_action == "login":
|
||||
cmd_auth_login(args)
|
||||
elif auth_action == "logout":
|
||||
cmd_auth_logout(args)
|
||||
else:
|
||||
cmd_auth_status(args)
|
||||
return
|
||||
|
||||
# 加载配置
|
||||
try:
|
||||
sap_cfg, loaded_from = load_config(args.config, profile=getattr(args, "profile", None))
|
||||
if loaded_from:
|
||||
logging.getLogger("sapcli").info("Config loaded from: %s", loaded_from)
|
||||
except ConfigError as e:
|
||||
print(f" ✗ {e}")
|
||||
print(f" 请创建配置文件 (config.ini) 或设置环境变量:")
|
||||
print(f" SAP_HOST, SAP_CLIENT, SAP_USER, SAP_PASSWORD")
|
||||
sys.exit(1)
|
||||
|
||||
# 建立 SAP 连接
|
||||
verify_ssl = getattr(args, "verify_ssl", False)
|
||||
client = ADTClient(sap_cfg.host, sap_cfg.client, sap_cfg.user, sap_cfg.password, verify_ssl=verify_ssl)
|
||||
|
||||
print("\n → 正在登录...")
|
||||
client.login()
|
||||
print(" ✓ 登录成功\n")
|
||||
|
||||
# 命令路由表
|
||||
command_map = {
|
||||
"download": cmd_download,
|
||||
"sync": cmd_sync_all if getattr(args, "all", False) else cmd_sync,
|
||||
"info": cmd_info,
|
||||
"delete": cmd_delete,
|
||||
"create": cmd_create,
|
||||
"init": cmd_init,
|
||||
"refresh": cmd_refresh,
|
||||
"list": cmd_list,
|
||||
"whereused": cmd_whereused,
|
||||
"search": cmd_search,
|
||||
"transport": cmd_transport,
|
||||
"check": cmd_check,
|
||||
"format": cmd_format,
|
||||
"activate": cmd_activate,
|
||||
"diff": cmd_diff,
|
||||
"package": cmd_package,
|
||||
"cds": cmd_cds,
|
||||
"analyze": cmd_analyze,
|
||||
"scaffold": cmd_scaffold,
|
||||
"show-table": cmd_show_table,
|
||||
"read-table": cmd_read_table,
|
||||
"run-program": cmd_run_program,
|
||||
}
|
||||
|
||||
# 批量 sync 参数校验
|
||||
if args.command == "sync" and getattr(args, "all", False):
|
||||
if args.name and args.type:
|
||||
print(" ✗ --all 模式下不需要 --name 和 --type 参数")
|
||||
sys.exit(1)
|
||||
elif args.command == "sync" and not getattr(args, "all", False):
|
||||
if not args.name or not args.type:
|
||||
print(" ✗ 单对象模式需要 --name 和 --type 参数")
|
||||
sys.exit(1)
|
||||
|
||||
# 执行命令
|
||||
handler = command_map.get(args.command)
|
||||
if handler is None:
|
||||
print(f" ✗ 未知命令: {args.command}")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
handler(args, client)
|
||||
except SapCliError as e:
|
||||
print(f"\n ✗ {e}")
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,50 @@
|
||||
"""格式化输出工具函数。"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def print_separator(char: str = "=", width: int = 60) -> None:
|
||||
"""打印分隔线。"""
|
||||
print(char * width)
|
||||
|
||||
|
||||
def print_header(title: str) -> None:
|
||||
"""打印带标题的分隔头部。"""
|
||||
print_separator()
|
||||
print(f" {title}")
|
||||
print_separator()
|
||||
|
||||
|
||||
def print_source_preview(source: str, max_lines: int = 20) -> None:
|
||||
"""打印源代码预览。"""
|
||||
lines = source.splitlines()
|
||||
print(f" ┌─── 源代码 (前 {max_lines} 行) ──────────────────────")
|
||||
for i, line in enumerate(lines[:max_lines], 1):
|
||||
print(f" │ {i:4d} | {line}")
|
||||
if len(lines) > max_lines:
|
||||
print(f" │ ... 省略剩余 {len(lines) - max_lines} 行 ...")
|
||||
print(f" └────────────────────────────────────────────")
|
||||
|
||||
|
||||
def print_success(msg: str) -> None:
|
||||
"""打印成功信息。"""
|
||||
print(f" ✓ {msg}")
|
||||
|
||||
|
||||
def print_error(msg: str) -> None:
|
||||
"""打印错误信息。"""
|
||||
print(f" ✗ {msg}")
|
||||
|
||||
|
||||
def print_info(msg: str) -> None:
|
||||
"""打印信息提示。"""
|
||||
print(f" ℹ {msg}")
|
||||
|
||||
|
||||
def print_warning(msg: str) -> None:
|
||||
"""打印警告信息。"""
|
||||
print(f" ⚠ {msg}")
|
||||
|
||||
|
||||
def print_step(msg: str) -> None:
|
||||
"""打印步骤信息。"""
|
||||
print(f" → {msg}")
|
||||
@@ -0,0 +1,251 @@
|
||||
"""argparse 命令行参数定义。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
from sapcli.types import all_type_keys
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
"""构建并返回主命令行解析器。"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="sap-cli — SAP ADT 源代码下载/同步激活/删除",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
python main.py download --name ZMY_REPORT --type report --path ./output
|
||||
python main.py sync --name ZMY_REPORT --type report --path ./zmy_report.abap
|
||||
python main.py delete --name ZMY_REPORT --type report
|
||||
python main.py info --name ZCL_MY_CLASS --type class
|
||||
python main.py create --name ZMY_REPORT --type report --description "我的报表"
|
||||
python main.py create --name ZMY_REPORT --type report --corr_nr DEVK901362
|
||||
python main.py --config ./my_config.ini download --name ZMY_REPORT --type report --path ./output
|
||||
|
||||
批量同步:
|
||||
python main.py init --path ./my_project
|
||||
python main.py sync --all --path ./my_project
|
||||
python main.py sync --all --path ./my_project --dry-run
|
||||
python main.py refresh --path ./my_project
|
||||
|
||||
搜索与浏览:
|
||||
python main.py list --type report --prefix Z*
|
||||
python main.py whereused --name ZMY_REPORT --type report
|
||||
python main.py search --query "CALL FUNCTION"
|
||||
|
||||
传输管理:
|
||||
python main.py transport list
|
||||
python main.py transport info --corr_nr DEVK901362
|
||||
python main.py transport release --corr_nr DEVK901362
|
||||
python main.py transport objects --corr_nr DEVK901362
|
||||
|
||||
代码质量:
|
||||
python main.py check --name ZMY_REPORT --type report
|
||||
python main.py format --name ZMY_REPORT --type report
|
||||
|
||||
代码差异:
|
||||
python main.py diff --name ZMY_REPORT --type report --path ./zmy_report.abap
|
||||
|
||||
包管理:
|
||||
python main.py package create --name ZMY_PACKAGE --description "我的包"
|
||||
python main.py package info --name ZMY_PACKAGE
|
||||
|
||||
CDS View:
|
||||
python main.py cds download --name ZMY_CDS_VIEW --path ./output
|
||||
python main.py cds create --name ZMY_CDS_VIEW --description "我的CDS视图"
|
||||
|
||||
依赖分析:
|
||||
python main.py analyze --path ./my_project
|
||||
|
||||
项目模板:
|
||||
python main.py scaffold --name ZMY_REPORT --template alv-report
|
||||
|
||||
配置:
|
||||
配置文件默认读取脚本同目录下的 config.ini。
|
||||
环境变量 SAP_HOST / SAP_CLIENT / SAP_USER / SAP_PASSWORD 可覆盖配置文件。
|
||||
""",
|
||||
)
|
||||
parser.add_argument("--config", default=None, help="配置文件路径 (默认: 脚本同目录/config.ini)")
|
||||
parser.add_argument(
|
||||
"--profile", "-p", default=None,
|
||||
help="配置 profile 名称 (config.ini 中的 section 名, 默认: SAP)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verify-ssl", action="store_true", default=False,
|
||||
help="启用 SSL 证书验证 (默认: 关闭,适用于 SAP 自签名证书环境)",
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", help="操作命令")
|
||||
type_choices = all_type_keys()
|
||||
|
||||
# ── download ──
|
||||
dl_parser = subparsers.add_parser("download", help="下载源代码到本地文件")
|
||||
dl_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
|
||||
dl_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
dl_parser.add_argument("--path", required=True, help="保存目录路径")
|
||||
|
||||
# ── sync ──
|
||||
sync_parser = subparsers.add_parser("sync", help="同步源代码到 SAP 并激活")
|
||||
sync_parser.add_argument("--name", default=None, help="对象名称 (--all 模式不需要)")
|
||||
sync_parser.add_argument("--type", default=None, choices=type_choices, help="对象类型 (--all 模式不需要)")
|
||||
sync_parser.add_argument("--path", required=True, help="本地源代码文件路径 (.abap) 或项目根目录 (--all 模式)")
|
||||
sync_parser.add_argument("--corr_nr", default=None, help="直接指定传输请求号 (跳过交互选择)")
|
||||
sync_parser.add_argument("--all", action="store_true", dest="all", help="批量模式:同步项目清单中的所有对象")
|
||||
sync_parser.add_argument("--dry-run", action="store_true", help="仅输出执行计划,不实际操作 (批量模式)")
|
||||
sync_parser.add_argument("--fail-fast", action="store_true", help="遇到失败立即停止 (批量模式)")
|
||||
|
||||
# ── delete ──
|
||||
del_parser = subparsers.add_parser("delete", help="从 SAP 系统删除对象")
|
||||
del_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
|
||||
del_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
del_parser.add_argument("--path", default=None, help="项目根目录 (可选,用于更新清单)")
|
||||
|
||||
# ── info ──
|
||||
info_parser = subparsers.add_parser("info", help="查询对象元数据信息")
|
||||
info_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
|
||||
info_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
|
||||
# ── create ──
|
||||
create_parser = subparsers.add_parser("create", help="在 SAP 系统创建开发对象")
|
||||
create_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
|
||||
create_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
create_parser.add_argument("--description", default=None, help="对象描述 (默认: 使用对象名称)")
|
||||
create_parser.add_argument("--source", default=None, help="源代码文件路径 (.abap),不指定则使用默认模板")
|
||||
create_parser.add_argument("--definition", default=None, help="DDIC 定义文件路径 (.json),用于 domain/dataelement/table/structure/tabletype")
|
||||
create_parser.add_argument("--corr_nr", default=None, help="直接指定传输请求号 (跳过交互选择)")
|
||||
create_parser.add_argument("--package", default="$TMP", help="SAP 包名 (默认: $TMP)")
|
||||
create_parser.add_argument("--path", default=None, help="项目根目录 (可选,用于写入清单)")
|
||||
|
||||
# ── init ──
|
||||
init_parser = subparsers.add_parser("init", help="初始化项目清单")
|
||||
init_parser.add_argument("--path", required=True, help="项目根目录")
|
||||
|
||||
# ── refresh ──
|
||||
refresh_parser = subparsers.add_parser("refresh", help="刷新清单中对象的 SAP 状态")
|
||||
refresh_parser.add_argument("--path", required=True, help="项目根目录")
|
||||
|
||||
# ── config ──
|
||||
config_parser = subparsers.add_parser("config", help="配置管理")
|
||||
config_sub = config_parser.add_subparsers(dest="config_action", help="配置操作")
|
||||
config_sub.add_parser("show", help="显示当前配置")
|
||||
config_sub.add_parser("list-profiles", help="列出所有 profile")
|
||||
config_set_parser = config_sub.add_parser("set", help="设置配置项")
|
||||
config_set_parser.add_argument("key", help="配置项名称 (host/client/user/password)")
|
||||
config_set_parser.add_argument("value", help="配置值")
|
||||
|
||||
# ── list (对象列表浏览) ──
|
||||
list_parser = subparsers.add_parser("list", help="列出 SAP 对象")
|
||||
list_parser.add_argument("--type", default=None, choices=type_choices, help="对象类型过滤")
|
||||
list_parser.add_argument("--package", default=None, help="包名过滤")
|
||||
list_parser.add_argument("--prefix", default=None, help="对象名前缀 (支持通配符 *)")
|
||||
|
||||
# ── whereused (Where-Used 引用查询) ──
|
||||
wu_parser = subparsers.add_parser("whereused", help="Where-Used 引用查询")
|
||||
wu_parser.add_argument("--name", required=True, help="对象名称")
|
||||
wu_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
|
||||
# ── search (源代码搜索) ──
|
||||
search_parser = subparsers.add_parser("search", help="源代码搜索")
|
||||
search_parser.add_argument("--query", required=True, help="搜索关键词")
|
||||
search_parser.add_argument("--type", default=None, choices=type_choices, help="限定对象类型")
|
||||
|
||||
# ── transport (传输请求管理) ──
|
||||
transport_parser = subparsers.add_parser("transport", help="传输请求管理")
|
||||
transport_sub = transport_parser.add_subparsers(dest="transport_action", help="传输操作")
|
||||
transport_sub.add_parser("list", help="列出可修改的传输请求")
|
||||
tr_info = transport_sub.add_parser("info", help="查看传输请求详情")
|
||||
tr_info.add_argument("--corr_nr", required=True, help="传输请求编号")
|
||||
tr_release = transport_sub.add_parser("release", help="释放传输请求")
|
||||
tr_release.add_argument("--corr_nr", required=True, help="传输请求编号")
|
||||
tr_objects = transport_sub.add_parser("objects", help="列出传输请求中的对象")
|
||||
tr_objects.add_argument("--corr_nr", required=True, help="传输请求编号")
|
||||
|
||||
# ── check (ATC 代码检查) ──
|
||||
check_parser = subparsers.add_parser("check", help="ATC 代码检查")
|
||||
check_parser.add_argument("--name", required=True, help="对象名称")
|
||||
check_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
check_parser.add_argument("--variant", default=None, help="ATC 检查变体 (可选)")
|
||||
|
||||
# ── format (代码格式化) ──
|
||||
fmt_parser = subparsers.add_parser("format", help="代码格式化 (ABAP Pretty Printer)")
|
||||
fmt_parser.add_argument("--name", required=True, help="对象名称")
|
||||
fmt_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
|
||||
# ── activate (单独激活) ──
|
||||
act_parser = subparsers.add_parser("activate", help="单独激活 SAP 对象(无需重新 sync)")
|
||||
act_parser.add_argument("--name", default=None, help="对象名称(单对象模式)")
|
||||
act_parser.add_argument("--type", default=None, choices=type_choices, help="对象类型(单对象模式)")
|
||||
act_parser.add_argument("--names", default=None, help="逗号分隔的多个对象名称(批量模式)")
|
||||
act_parser.add_argument("--types", default=None, help="逗号分隔的多个对象类型(批量模式,与 --names 一一对应)")
|
||||
act_parser.add_argument("--corr_nr", default=None, help="传输请求编号")
|
||||
|
||||
# ── diff (代码差异对比) ──
|
||||
diff_parser = subparsers.add_parser("diff", help="本地 vs SAP 代码差异对比")
|
||||
diff_parser.add_argument("--name", required=True, help="对象名称")
|
||||
diff_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
|
||||
diff_parser.add_argument("--path", default=None, help="本地文件路径 (.abap)")
|
||||
|
||||
# ── package (包管理) ──
|
||||
package_parser = subparsers.add_parser("package", help="ABAP 包操作")
|
||||
package_sub = package_parser.add_subparsers(dest="package_action", help="包操作")
|
||||
pkg_create = package_sub.add_parser("create", help="创建 ABAP 包")
|
||||
pkg_create.add_argument("--name", required=True, help="包名")
|
||||
pkg_create.add_argument("--description", default=None, help="包描述")
|
||||
pkg_create.add_argument("--superpackage", default=None, help="上级包名")
|
||||
pkg_info = package_sub.add_parser("info", help="查看包详情")
|
||||
pkg_info.add_argument("--name", required=True, help="包名")
|
||||
pkg_list = package_sub.add_parser("list", help="列出包中的对象")
|
||||
pkg_list.add_argument("--name", required=True, help="包名")
|
||||
|
||||
# ── cds (CDS View 操作) ──
|
||||
cds_parser = subparsers.add_parser("cds", help="CDS View 操作")
|
||||
cds_sub = cds_parser.add_subparsers(dest="cds_action", help="CDS 操作")
|
||||
cds_dl = cds_sub.add_parser("download", help="下载 CDS View DDL 源码")
|
||||
cds_dl.add_argument("--name", required=True, help="CDS View 名称")
|
||||
cds_dl.add_argument("--path", default=".", help="保存目录路径")
|
||||
cds_sync = cds_sub.add_parser("sync", help="同步本地 DDL 到 SAP")
|
||||
cds_sync.add_argument("--name", required=True, help="CDS View 名称")
|
||||
cds_sync.add_argument("--path", required=True, help="本地 DDL 文件路径")
|
||||
cds_create = cds_sub.add_parser("create", help="创建新的 CDS View")
|
||||
cds_create.add_argument("--name", required=True, help="CDS View 名称")
|
||||
cds_create.add_argument("--description", default=None, help="CDS View 描述")
|
||||
cds_create.add_argument("--ddl_path", default=None, help="DDL 文件路径 (可选)")
|
||||
cds_create.add_argument("--path", default=".", help="保存目录路径")
|
||||
|
||||
# ── analyze (依赖分析) ──
|
||||
analyze_parser = subparsers.add_parser("analyze", help="依赖自动分析")
|
||||
analyze_parser.add_argument("--path", required=True, help="项目目录路径")
|
||||
|
||||
# ── scaffold (项目模板) ──
|
||||
scaffold_parser = subparsers.add_parser("scaffold", help="项目模板创建")
|
||||
scaffold_parser.add_argument("--name", required=True, help="对象名称")
|
||||
scaffold_parser.add_argument(
|
||||
"--template", required=False,
|
||||
choices=["alv-report", "bapi-wrapper", "interface-class", "data-model"],
|
||||
help="模板类型 (不指定则列出可用模板)",
|
||||
)
|
||||
scaffold_parser.add_argument("--package", default="$TMP", help="SAP 包名 (默认: $TMP)")
|
||||
scaffold_parser.add_argument("--path", default=".", help="输出目录")
|
||||
|
||||
# ── auth (密钥管理) ──
|
||||
auth_parser = subparsers.add_parser("auth", help="密钥管理 (keyring)")
|
||||
auth_sub = auth_parser.add_subparsers(dest="auth_action", help="密钥操作")
|
||||
auth_sub.add_parser("login", help="保存密码到 keyring")
|
||||
auth_sub.add_parser("logout", help="从 keyring 删除密码")
|
||||
auth_sub.add_parser("status", help="显示 keyring 状态")
|
||||
|
||||
# ── show-table ──
|
||||
p_show_table = subparsers.add_parser("show-table", help="查看 DDIC 表字段结构 (SE11)")
|
||||
p_show_table.add_argument("--name", required=True, help="表名")
|
||||
|
||||
# ── read-table ──
|
||||
p_read_table = subparsers.add_parser("read-table", help="查询表数据 (SE16N)")
|
||||
p_read_table.add_argument("--name", required=True, help="表名")
|
||||
p_read_table.add_argument("--fields", help="查询字段列表,逗号分隔 (默认: *)")
|
||||
p_read_table.add_argument("--where", help="WHERE 条件 (如 \"status = 'error'\")")
|
||||
p_read_table.add_argument("--max-rows", type=int, default=200, help="最大行数 (默认: 200)")
|
||||
|
||||
# ── run-program ──
|
||||
p_run = subparsers.add_parser("run-program", help="远程执行 ABAP 程序 (SA38)")
|
||||
p_run.add_argument("--name", required=True, help="程序名")
|
||||
|
||||
return parser
|
||||
Reference in New Issue
Block a user