Files
sap-cli-skill/assets/sapcli/cli/parser.py
T
吴让宇 e786742bcb chore: 同步至源码 2.5.1 — SKILL.md 改为构建产物 + 工具代码刷新
SKILL.md(唯一来源 = sap-cli/skill-src/SKILL.md.tmpl):
- 本仓 SKILL.md 自此为构建产物,勿手工编辑;手改后再构建会被漂移护栏拦下
- 并入模板独有内容:调用方式节 + 补齐 parser 真实命令(clone/enhancement/
  history/unit-test/unlock/transport create,原表只 9 个,实际 31 个)
- 版本号改为 {{VERSION}} 注入(原字面量停在 v2.2.1/v2.3.0,与工具实际版本脱节)
- 修 1 处违反铁律 5 的示例(--path ./src → ./src/TMP/class/)

assets/(工具代码,此前严重过时):
- 9 个文件与源码不一致,scanner.py 尤甚:3818B → 6664B
- 修复前从本仓装出的工具**不支持三层 src 结构**,铁律 5 实际跑不通
- transport.py 反向漂移(分发版多 transport create,源码无)已随源码回迁对齐

VERSION 2.5.1;references/ 三份规则与源码一致(无差异)
2026-09-11 00:22:05 +08:00

295 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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="项目根目录 (可选,用于更新清单)")
# ── unlock ──
unlock_parser = subparsers.add_parser("unlock", help="释放对象残留 enqueue 锁(delete 后锁未释放时用)")
unlock_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
unlock_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
unlock_parser.add_argument("--lock-handle", required=True, help="LOCK 响应返回的 lockHandle(见 log/adt_tools.log")
# ── 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="传输请求编号")
tr_create = transport_sub.add_parser("create", help="新建传输请求")
tr_create.add_argument("--description", 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="传输请求编号")
# ── upload (仅上传源码,不检查不激活) ──
upload_parser = subparsers.add_parser("upload", help="上传源代码到 SAP(不检查不激活)")
upload_parser.add_argument("--name", required=True, help="对象名称 (function 类型用'组名/模块名')")
upload_parser.add_argument("--type", required=True, choices=type_choices, help="对象类型")
upload_parser.add_argument("--path", required=True, help="本地源代码文件路径 (.abap)")
upload_parser.add_argument("--corr_nr", default=None, help="传输请求编号")
# ── syntax-check (远程对象语法检查,不上传不激活) ──
sc_parser = subparsers.add_parser("syntax-check", help="语法检查(远程对象,不上传不激活)")
sc_parser.add_argument("--name", required=True, help="对象名称")
sc_parser.add_argument("--type", required=True, choices=type_choices, 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="程序名")
# ── unit-test ──
sp_unit = subparsers.add_parser("unit-test", help="运行 ABAP Unit 测试")
sp_unit.add_argument("--name", required=True, help="对象名称")
sp_unit.add_argument("--type", required=True, help="对象类型")
# ── history ──
sp_history = subparsers.add_parser("history", help="查看对象版本历史")
sp_history.add_argument("--name", required=True, help="对象名称")
sp_history.add_argument("--type", required=True, help="对象类型")
# ── clone ──
sp_clone = subparsers.add_parser("clone", help="跨系统克隆对象")
sp_clone.add_argument("--name", required=True, help="对象名称")
sp_clone.add_argument("--type", required=True, help="对象类型")
sp_clone.add_argument("--from", dest="from_profile", required=True, help="源系统 profile")
sp_clone.add_argument("--to", dest="to_profile", required=True, help="目标系统 profile")
sp_clone.add_argument("--corr_nr", default=None, help="目标系统的传输请求号")
# ── enhancement ──
sp_enh = subparsers.add_parser("enhancement", help="查询对象的增强实现")
sp_enh.add_argument("--name", required=True, help="对象名称")
sp_enh.add_argument("--type", required=True, help="对象类型")
return parser