"""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