data-ops-cli 0.2.2__py3-none-any.whl → 0.2.4__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 (41) hide show
  1. {data_ops_cli-0.2.2.dist-info → data_ops_cli-0.2.4.dist-info}/METADATA +1 -1
  2. {data_ops_cli-0.2.2.dist-info → data_ops_cli-0.2.4.dist-info}/RECORD +41 -33
  3. dataops_cli/__init__.py +1 -1
  4. dataops_cli/cli/api.py +227 -0
  5. dataops_cli/cli/auth.py +8 -5
  6. dataops_cli/cli/data_table.py +5 -6
  7. dataops_cli/cli/dataset.py +8 -9
  8. dataops_cli/cli/datasource.py +101 -5
  9. dataops_cli/cli/dict_.py +96 -0
  10. dataops_cli/cli/factory.py +4 -0
  11. dataops_cli/cli/metrics.py +5 -5
  12. dataops_cli/cli/report.py +5 -5
  13. dataops_cli/cli/table.py +185 -30
  14. dataops_cli/cli/utils.py +12 -0
  15. dataops_cli/cli/widget.py +423 -19
  16. dataops_cli/cli/workflow.py +5 -5
  17. dataops_cli/constants.py +0 -1
  18. dataops_cli/runner/utils/dbConn_sync.py +16 -7
  19. dataops_cli/schems/__init__.py +12 -3
  20. dataops_cli/schems/api.py +37 -0
  21. dataops_cli/schems/data_table.py +3 -41
  22. dataops_cli/schems/datasource.py +15 -49
  23. dataops_cli/schems/dict_.py +13 -0
  24. dataops_cli/schems/enums.py +39 -0
  25. dataops_cli/schems/meta.py +21 -5
  26. dataops_cli/schems/table.py +60 -8
  27. dataops_cli/schems/widget.py +107 -11
  28. dataops_cli/sdk/__init__.py +15 -3
  29. dataops_cli/sdk/api.py +28 -0
  30. dataops_cli/sdk/auth.py +0 -8
  31. dataops_cli/sdk/data_table.py +5 -8
  32. dataops_cli/sdk/dataset.py +54 -0
  33. dataops_cli/sdk/datasource.py +13 -6
  34. dataops_cli/sdk/dict_.py +69 -0
  35. dataops_cli/sdk/meta.py +63 -38
  36. dataops_cli/sdk/table.py +124 -33
  37. dataops_cli/sdk/widget.py +99 -0
  38. dataops_cli/session.py +40 -1
  39. {data_ops_cli-0.2.2.dist-info → data_ops_cli-0.2.4.dist-info}/WHEEL +0 -0
  40. {data_ops_cli-0.2.2.dist-info → data_ops_cli-0.2.4.dist-info}/entry_points.txt +0 -0
  41. {data_ops_cli-0.2.2.dist-info → data_ops_cli-0.2.4.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: data-ops-cli
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Requires-Python: <3.14,>=3.11
5
5
  Requires-Dist: requests
6
6
  Requires-Dist: pydantic-core
@@ -1,21 +1,23 @@
1
- dataops_cli/__init__.py,sha256=m6kyaNpwBcP1XYcqrelX2oS3PJuOnElOcRdBa9pEb8c,22
2
- dataops_cli/constants.py,sha256=Nc0ZofLF_sX_wDyVDvvrZPKOj6c_jahEOXmhy5phvF8,293
1
+ dataops_cli/__init__.py,sha256=SBl2EPFW-ltPvQ7vbVWItyAsz3aKYIpjO7vcfr84GkU,22
2
+ dataops_cli/constants.py,sha256=qRRNMjH9_6fwL7e9fRZHpHnJG1ZqRHUEPPzPpfqGSKc,197
3
3
  dataops_cli/exceptions.py,sha256=GnNqDlMfgjMiL0Kp-H0KZMDJdRAckG6kd3V-NJiugFg,575
4
- dataops_cli/session.py,sha256=6agqEwJSL024vf2OHg8CiucmFGmQT1yEY4mao-NQp9E,5344
4
+ dataops_cli/session.py,sha256=TnI-4MAMQYBxsTu5yvaxwSqGoBEytV2xakvVIyADudU,6632
5
5
  dataops_cli/utils.py,sha256=-7iBbYjp9JM5LhuCkNhYoNITa26YJxyhd_oTYzPjERU,3740
6
6
  dataops_cli/cli/__init__.py,sha256=TvJw3xrE81YSwUrauHaJwQsRNf-YAlxLnadce1KYo4c,67
7
- dataops_cli/cli/auth.py,sha256=7kM0c0hjALZ-u7-RsNZhwRct5kshA2S5_zmqSlFVzc4,6381
8
- dataops_cli/cli/data_table.py,sha256=vzzC7naHBNKe5aYsxjkFUdTHkQrkgsVHY3w_SGi3tKo,9402
9
- dataops_cli/cli/dataset.py,sha256=9r3T7tlXUg2swALAjlpcyRm_N2XZ6ui7r6AJYtOg1zA,3387
10
- dataops_cli/cli/datasource.py,sha256=E3B_Uspo0lQ5iApptqex45nSBNkvHQnGD9XtuJImClY,3361
11
- dataops_cli/cli/factory.py,sha256=Miib8v8iTylw7pUfvp4NV19bTKwpEQGTg1l8Lhj4uGA,1553
12
- dataops_cli/cli/metrics.py,sha256=CioC_l2DHlg3s97_-kAfLihdz7tLgOwb9lo2AIngb5I,6195
7
+ dataops_cli/cli/api.py,sha256=EuTDeTgwF9Kx9XtdJ8t4ZSA_oFEK710F-AUWF74Y0_I,6979
8
+ dataops_cli/cli/auth.py,sha256=zYizqzIDSnLIvOk-Sev1sxyVPqNffTUfhh4XiSw9eaI,6369
9
+ dataops_cli/cli/data_table.py,sha256=buwO0PLk6xY-LeA0QCvAzRz1Y0xSQg5qsix1-CGFtE8,9345
10
+ dataops_cli/cli/dataset.py,sha256=zWV1GzQRlVmaeovMe3cmKukK0NxxVyWwK--uowA8VD8,3241
11
+ dataops_cli/cli/datasource.py,sha256=1V74KjgV8feIx4xHeysVPBd3fL3_VHyeH98q0_IejQA,7196
12
+ dataops_cli/cli/dict_.py,sha256=FEoZvStXvZhMLknuFbxAACqI4B0-xwQID3vz_tIF7aY,3054
13
+ dataops_cli/cli/factory.py,sha256=-iVbKLm5egSWOzXa9KraXhccnGaKhDjHMD7hq1BFRFA,1707
14
+ dataops_cli/cli/metrics.py,sha256=U8EfbpxIgZ8oZYf8mTdz9Ke-ZA1t7RqaaMJ7aonYWsA,6160
13
15
  dataops_cli/cli/ref.py,sha256=jfc5EhkXrhqUwu4IuftEjUepPB3d6SK4ZDhrh40YGOE,4765
14
- dataops_cli/cli/report.py,sha256=-qo5Nz31bCI_y8dvPoBnpn4-ggQ0Leo5mUsmiWBzNJ8,2437
15
- dataops_cli/cli/table.py,sha256=5EoDrV32FSCLuyvhNl3yz5LSorAFL6Rw1oWNBcx9Iwg,7495
16
- dataops_cli/cli/utils.py,sha256=Qi3BGmZgIapasHAGCYVdOS8deYz5GmZIqKd289HYgeE,529
17
- dataops_cli/cli/widget.py,sha256=7Kzie7GqNf1vLK2O9G1HVSJnzjUGRHJqGaypVCEkLsE,1745
18
- dataops_cli/cli/workflow.py,sha256=Do0bwV9kHSSOICW5RELLJoL34fLhf7tIcqcOSokKFLw,4804
16
+ dataops_cli/cli/report.py,sha256=Vrhz_U7qGiSmefZsq_rDarxrv6e4BG_R3yjudFsYuDE,2403
17
+ dataops_cli/cli/table.py,sha256=kctKGadjD5Dnrkp8fLbwpfcDSthJ7ojiHoj-FMdt3II,13405
18
+ dataops_cli/cli/utils.py,sha256=ZpCGbLj4eIBfdYiI0-XJWRnY9PSaX7xrjD2e_HWA4O8,884
19
+ dataops_cli/cli/widget.py,sha256=9vELuNpGCGVgyacjPK7b_evDdgOZ3wIiJboEqz5NwfI,15367
20
+ dataops_cli/cli/workflow.py,sha256=hfsDUtRbU4f-9sD0VH-Brx3xWbNNI8x8rv8-UAi9zPs,4756
19
21
  dataops_cli/runner/__init__.py,sha256=BursdHKoU_4Bq-BhrYxNCJ88SpUajeMzVrnLMpbC4fc,767
20
22
  dataops_cli/runner/schemas/nacos/__init__.py,sha256=yXsULXK8G5IiZz2c26yrVhtvflbDLwgTkajm74YAA10,146
21
23
  dataops_cli/runner/schemas/nacos/config.py,sha256=pHrwJRoDGQNuqMVoQnkmNF0ENqUqcmUvp-j3Q_YgTx0,1326
@@ -30,31 +32,37 @@ dataops_cli/runner/schemas/nacos/service.py,sha256=C-27WmWW-ziZuplMTp2-xcIIPONVm
30
32
  dataops_cli/runner/utils/__init__.py,sha256=C0e_iiM80fScn_FGL4-HIRwmsHADiyN5TQ08a75FgQk,880
31
33
  dataops_cli/runner/utils/common.py,sha256=fz7uUjVRluZUUUaIhw2b9OXvs5k9M_W0l4TH6oxGilg,6282
32
34
  dataops_cli/runner/utils/dbConn_base.py,sha256=3reXPJ9uAcOVhl3sRNe4MPplYpKfG5DTfW0ETaqXeEo,8239
33
- dataops_cli/runner/utils/dbConn_sync.py,sha256=QG9_9ExNGeTWGkXmf6r16nSbu3YXLBchKU5STo3s08c,12938
35
+ dataops_cli/runner/utils/dbConn_sync.py,sha256=qi010MbZvtPmSeDJe1tlbklWXVaqiCEN_7IhnBdKIPA,13293
34
36
  dataops_cli/runner/utils/duckdb_manager.py,sha256=xIREgkx6hcAbt6cYSTEHfGPGu7QgZsCwQrU4u2Vb1ng,6902
35
37
  dataops_cli/runner/utils/log.py,sha256=EwctSAohPIP1wo2FtUTjv5kswyoGHK70-2CFlyQ9yN4,1438
36
38
  dataops_cli/runner/utils/nacos.py,sha256=HSJyjswRk1ohzzUEjn4yRDtWKPjgsU_yYoS1nh5TWss,2994
37
39
  dataops_cli/runner/utils/neo4j_sync.py,sha256=cbpb4K5QUHcD1DuJg7_KeoBi8N1DLwru2sbiDMq779M,6603
38
- dataops_cli/schems/__init__.py,sha256=xK0fa3LMvpQLIzVt-9GY-DC7C1z1c0xf5ZRlvicePKM,600
39
- dataops_cli/schems/data_table.py,sha256=SV_OR_pAzagVGZybgF5VjuqnHErAJO0lMBbbghWD_Jw,17292
40
- dataops_cli/schems/datasource.py,sha256=2b0dUf0xdO0J9fV5V1eCEM9Hj6ERButULuChl34i0Ik,2287
41
- dataops_cli/schems/enums.py,sha256=3lCxF5E4Jo1LUw9ZbA2-PiIbSGaYLBmrwQdlwdcmh-k,1438
40
+ dataops_cli/schems/__init__.py,sha256=Kln_wipkevaaFp24lYcrdwogok7Jsnz3YEO60WK68kk,837
41
+ dataops_cli/schems/api.py,sha256=x522Vf2leZnn8-bfllGoldy59zrS4a-c06B0uGQhfhw,1477
42
+ dataops_cli/schems/data_table.py,sha256=tLCOcaTMIoM5KySHYE97YSqBly95cjlbmyZcUZL1Lv0,16516
43
+ dataops_cli/schems/datasource.py,sha256=gSFoQm5ZNhn3PxcrM24WLpvJcT_QHOhNp_2J3cbIT6A,854
44
+ dataops_cli/schems/dict_.py,sha256=Y0ebyXYCw4vBhBgHyPXCz_4yVALAxMkQQlxSQsjJNs0,394
45
+ dataops_cli/schems/enums.py,sha256=9gB08DPwAr2gthzuxew0pI91e8byaVH34I03eu4kDhc,2111
42
46
  dataops_cli/schems/group.py,sha256=TvH0nsrGz1DpftrLAPpHqQuhMNgu0e5gu_Og3PiVnBc,1306
43
- dataops_cli/schems/meta.py,sha256=lHkk97cn2-lzIYgqGdIfE_KQvL8Os-bKl2jKhh4MK5Q,5938
47
+ dataops_cli/schems/meta.py,sha256=2CVkxZyo04fhPagdt_QziCxwyIT1IICo04NNy8IvnsY,6500
44
48
  dataops_cli/schems/query.py,sha256=AWH0P51lkBQEKhotIOoqJaOEIEoaWaiT_r7hSXlzK2Q,6455
45
49
  dataops_cli/schems/report.py,sha256=Eklh1gMaRoPDvgrWZIBrLkQXhB0KuuAteJUzOzZngb8,493
46
- dataops_cli/schems/table.py,sha256=Y0ebyXYCw4vBhBgHyPXCz_4yVALAxMkQQlxSQsjJNs0,394
50
+ dataops_cli/schems/table.py,sha256=qJuxgMD7AGiNoDi6QrlIihuHJDAVx637VDdb2y9TtN4,2527
47
51
  dataops_cli/schems/user.py,sha256=mAPgLCCKeoC7qvOj6TOSC2xI3OrL7P5eNOGy4R3RVyw,2522
48
- dataops_cli/schems/widget.py,sha256=q1zsVv9g0bS_Fev_IRzHaH86T3cQfwzS5fcm5VhVMrM,21691
52
+ dataops_cli/schems/widget.py,sha256=0LMXf5JitH4bLy1ciyTh337QRxoekh4tsUyoCgFMxHU,25420
49
53
  dataops_cli/schems/workflow.py,sha256=opRkEwYXntTO-BCOLcZJK2joA32qELpdnN6pI2LS_2Y,1805
50
- dataops_cli/sdk/__init__.py,sha256=7aGMRkNbuHPj4e4_Lz537Dy0M64A2CiVsfUL_a_zuuw,961
51
- dataops_cli/sdk/auth.py,sha256=75dyLs_cmgDm2vSjkiS8WhO_y3DW3lKHBXsOMmYut74,3978
52
- dataops_cli/sdk/data_table.py,sha256=eQ1VmmyOo5zITWIl4QvebcnYyajudV_-xSA16saKrTw,6940
53
- dataops_cli/sdk/datasource.py,sha256=BqeKEQKRhhLxSGM0wKBsGvh48NW7a5SlqRjLRSfh9AM,2043
54
- dataops_cli/sdk/meta.py,sha256=oBjefAKCd1o10NxM0tQOmQyAHOJZfqv_DESX5_FcVpA,16443
54
+ dataops_cli/sdk/__init__.py,sha256=My6AHo7SSRGLDTLBHJMHBudcTabZuRKmqWJNlPOmld0,1362
55
+ dataops_cli/sdk/api.py,sha256=dq5toBJQ26m40GB3dygU8gcZCt9p8i-fpUs82o-4v6s,787
56
+ dataops_cli/sdk/auth.py,sha256=xA3x99lv5x1vgcy66pGvdh8Dw2OQc82Npku9iNOcXXs,3729
57
+ dataops_cli/sdk/data_table.py,sha256=7focA6HBv-4nwbIrBdZ4-S7ull-EjP3MuG4tYWghK6U,6827
58
+ dataops_cli/sdk/dataset.py,sha256=2qb52OVGhU6XAxeVjJoTjdazLNAmT9L9yxgIlphd7-4,1268
59
+ dataops_cli/sdk/datasource.py,sha256=EWnCx3enBScNYsdKuez18B4Eg0yYXoHa10Uc9DP5R6A,2371
60
+ dataops_cli/sdk/dict_.py,sha256=RLsvlrC-ARYXPudLczGOySmFp-z3p8yjw6QujL59Qc0,1790
61
+ dataops_cli/sdk/meta.py,sha256=JooSMEsCL3okXN1B6GWweUZ5XAULi-l1X7J0PpRqw74,17289
55
62
  dataops_cli/sdk/ref.py,sha256=BPttMiqaW7z1nuCvgY0nV6d-u1O1i_EbEJ7ZrL0KhFY,1925
56
63
  dataops_cli/sdk/report.py,sha256=uBmfgPCzqRMJQk8yS3kqSMLgOKijKEDRNOWamhjC6mw,376
57
- dataops_cli/sdk/table.py,sha256=zNaoqZMIC2Ot-gIsy-smf6eBlw0LVH6-s0ycfzlO6Dw,6646
64
+ dataops_cli/sdk/table.py,sha256=0zwgeTtSVwTV9KHab_ARIV0ao2Q9NLdvodMe6u3iHpA,9699
65
+ dataops_cli/sdk/widget.py,sha256=q4T7rEAANIgnJINNVweY99IBjhUeICz8fNCcje0jMbA,2828
58
66
  dataops_cli/sdk/workflow.py,sha256=go39E4Cc96bEuNW0pGeDvZZwonkKQ5njMaFTwLW-3jE,472
59
67
  dataops_cli/tiptap/__init__.py,sha256=UaHc1Q0T6OtmN02WNxTY1tp1-Iw8wzZjIyZE6rlMBgQ,612
60
68
  dataops_cli/tiptap/builder.py,sha256=w8lzbCcRo-AOFRvOoN3b_JV4hNLch_iSPbcYIcSqelk,2245
@@ -64,8 +72,8 @@ dataops_cli/tiptap/parse_utils.py,sha256=iJ4_gean-tkPXks4UShXuyPAkUwwFh41WL6cS7G
64
72
  dataops_cli/tiptap/render_utils.py,sha256=f5CDNLm0Y3uPXD0oPEjq4cKw1hDvWviY3IVlfS05vzE,21021
65
73
  dataops_cli/tiptap/renderers.py,sha256=qHAeYZeJf1Wip0svKtmy-28uFSeoTELzh3iE8bAQwaw,1235
66
74
  dataops_cli/tiptap/tool.py,sha256=7Uxoq-Kv_3XzU5ZW0k16wzwz79nhQf8D6qq7ygxERLw,27902
67
- data_ops_cli-0.2.2.dist-info/METADATA,sha256=T_6XcM0uKaqxt2yeEsc6Yzy97JwvC8ez-PFaFCfZbgc,503
68
- data_ops_cli-0.2.2.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
69
- data_ops_cli-0.2.2.dist-info/entry_points.txt,sha256=vc_2b5byVdLofaQ2ppuPM484AcaZnGsaHdcMKmtcSkU,53
70
- data_ops_cli-0.2.2.dist-info/top_level.txt,sha256=KFHplpKxwE9_wWypzVLESa4eLkOBsk-iUD_Qbld2IcY,12
71
- data_ops_cli-0.2.2.dist-info/RECORD,,
75
+ data_ops_cli-0.2.4.dist-info/METADATA,sha256=zOQE2Vq0i_SkMYNktLwS0vgfq7WXSC7Y46vZKUPcxT4,503
76
+ data_ops_cli-0.2.4.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
77
+ data_ops_cli-0.2.4.dist-info/entry_points.txt,sha256=vc_2b5byVdLofaQ2ppuPM484AcaZnGsaHdcMKmtcSkU,53
78
+ data_ops_cli-0.2.4.dist-info/top_level.txt,sha256=KFHplpKxwE9_wWypzVLESa4eLkOBsk-iUD_Qbld2IcY,12
79
+ data_ops_cli-0.2.4.dist-info/RECORD,,
dataops_cli/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.2"
1
+ __version__ = "0.2.4"
dataops_cli/cli/api.py ADDED
@@ -0,0 +1,227 @@
1
+ """API 接口管理模块.
2
+
3
+ 提供 API 接口的列表查询和详情功能。
4
+
5
+ - 服务层函数 (service_*):纯 Python 接口,返回原始数据
6
+ - CLI 命令:基于服务层的薄包装,负责格式化输出
7
+ """
8
+
9
+ import shutil
10
+ from typing import Annotated
11
+
12
+ import typer
13
+
14
+ from dataops_cli.exceptions import DataOpsError
15
+ from dataops_cli.schems import MetaType
16
+ from dataops_cli.sdk.api import service_get_api_by_code
17
+ from dataops_cli.sdk.meta import release_list_list
18
+ from dataops_cli.utils import filter_nodes_by_pattern
19
+
20
+ # ---------------------------------------------------------------------------
21
+ # 常量
22
+ # ---------------------------------------------------------------------------
23
+
24
+ _STATUS_MAP: dict[str, str] = {
25
+ "dev": "开发中",
26
+ "test": "测试中",
27
+ "prod": "已发布",
28
+ "deprecated": "将弃用",
29
+ }
30
+
31
+ _SCOPE_MAP: dict[str, str] = {
32
+ "public": "公开接口",
33
+ "internal": "内部接口",
34
+ "external": "外部接口",
35
+ }
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # CLI 命令
39
+ # ---------------------------------------------------------------------------
40
+
41
+ api_typer = typer.Typer(
42
+ name="api",
43
+ help="Manage APIs",
44
+ no_args_is_help=True,
45
+ )
46
+
47
+
48
+ def _first_line(text: str) -> str:
49
+ """取文本的第一行."""
50
+ return text.split("\n")[0]
51
+
52
+
53
+ @api_typer.command("list", rich_help_panel="API 查询")
54
+ def list_apis(
55
+ query: Annotated[
56
+ str | None, typer.Option("-q", "--query", help="按名称/标题/备注正则过滤")
57
+ ] = None,
58
+ ) -> None:
59
+ """列出所有 API 接口.
60
+
61
+ 从元数据服务获取 API 接口列表,支持通过正则表达式按名称、标题或备注进行过滤。
62
+
63
+ 示例:
64
+ 列出所有 API 接口
65
+ >>> data-ops-cli api list
66
+
67
+ 按名称/标题/备注过滤
68
+ >>> data-ops-cli api list --query ".*用户.*"
69
+ >>> data-ops-cli api list -q "用户"
70
+ """
71
+ try:
72
+ group_nodes = release_list_list(MetaType.API)
73
+ except DataOpsError as e:
74
+ typer.echo(f"错误: {e.message}")
75
+ raise typer.Exit(code=1) from None
76
+
77
+ if query:
78
+ group_nodes = filter_nodes_by_pattern(group_nodes, query)
79
+
80
+ if not group_nodes:
81
+ print("(无结果)")
82
+ return
83
+
84
+ print("code title remark")
85
+
86
+ for node in group_nodes:
87
+ code = node.CODE
88
+ title = node.TITLE
89
+ remark_raw = node.REMARK or ""
90
+ remark = _first_line(remark_raw.strip())
91
+ print(code, title, remark)
92
+
93
+
94
+ @api_typer.command("detail", rich_help_panel="API 查询", no_args_is_help=True)
95
+ def get_api_detail(
96
+ code: Annotated[str, typer.Argument(help="API 接口编码")],
97
+ simplify: Annotated[
98
+ bool,
99
+ typer.Option("-s", "--simplify", help="仅显示基本信息,不展示请求/响应参数"),
100
+ ] = False,
101
+ ) -> None:
102
+ """获取 API 接口详情.
103
+
104
+ 根据 API 接口编码获取详细信息,包括请求方法、路径、状态、请求参数和响应参数。
105
+
106
+ 示例:
107
+ 获取 API 接口完整信息
108
+ >>> data-ops-cli api detail user_login
109
+
110
+ 仅显示基本信息
111
+ >>> data-ops-cli api detail user_login --simplify
112
+ >>> data-ops-cli api detail user_login -s
113
+ """
114
+ try:
115
+ meta = service_get_api_by_code(code)
116
+ except DataOpsError as e:
117
+ typer.echo(f"错误: {e.message}")
118
+ raise typer.Exit(code=1) from None
119
+
120
+ d = meta.data
121
+ method = d.method
122
+ status_label = _STATUS_MAP.get(d.status, d.status)
123
+ scope_label = _SCOPE_MAP.get(d.scope, d.scope)
124
+
125
+ # 基本信息
126
+ print(f"方法: {method}")
127
+ print(f"路径: {d.endpoint}")
128
+ print(f"状态: {status_label}")
129
+ print(f"范围: {scope_label}")
130
+ if d.charger:
131
+ print(f"负责人: {d.charger}")
132
+ if d.env_code:
133
+ print(f"API 环境: {d.env_code}")
134
+ if d.description:
135
+ print(f"\n说明:\n{d.description}")
136
+
137
+ if simplify:
138
+ return
139
+
140
+ # 请求参数
141
+ rp = d.requestParam
142
+ print("\n--- 请求参数 ---")
143
+
144
+ # 认证
145
+ auth = rp.get("authParam", {})
146
+ if auth:
147
+ auth_type = auth.get("type", "none")
148
+ print(f" 认证: {auth_type}")
149
+
150
+ # Headers
151
+ headers = rp.get("headers", [])
152
+ if headers:
153
+ print(f" 请求头 ({len(headers)}):")
154
+ for h in headers:
155
+ required = " *" if h.get("required") else ""
156
+ print(f" - {h.get('name', '?')}: {h.get('title', '')}{required}")
157
+
158
+ # Path params
159
+ path_params = rp.get("pathParams", [])
160
+ if path_params:
161
+ print(f" 路径参数 ({len(path_params)}):")
162
+ for p in path_params:
163
+ required = " *" if p.get("required") else ""
164
+ print(
165
+ f" - {p.get('name', '?')}: {p.get('title', '')} ({p.get('type', '?')}){required}"
166
+ )
167
+
168
+ # Query params
169
+ query_params = rp.get("queryParams", [])
170
+ if query_params:
171
+ print(f" Query 参数 ({len(query_params)}):")
172
+ for q in query_params:
173
+ required = " *" if q.get("required") else ""
174
+ print(
175
+ f" - {q.get('name', '?')}: {q.get('title', '')} ({q.get('type', '?')}){required}"
176
+ )
177
+
178
+ # Body
179
+ body = rp.get("bodyParams", {})
180
+ if body:
181
+ mine_type = body.get("mineType", "none")
182
+ if mine_type != "none":
183
+ structure = body.get("structure", [])
184
+ print(f" 请求体: {mine_type}")
185
+ if structure:
186
+ _print_params_tree(structure, indent=4)
187
+
188
+ # Cookies
189
+ cookies = rp.get("cookies", [])
190
+ if cookies:
191
+ print(f" Cookie ({len(cookies)}):")
192
+ for c in cookies:
193
+ print(f" - {c.get('name', '?')}: {c.get('title', '')}")
194
+
195
+ # 响应参数
196
+ response_params = d.responseParams
197
+ if response_params:
198
+ print("\n--- 响应参数 ---")
199
+ for rp_item in response_params:
200
+ status_code = rp_item.get("status_code", "?")
201
+ title = rp_item.get("title", "")
202
+ mine_type = rp_item.get("mineType", "")
203
+ structure = rp_item.get("structure", [])
204
+ print(f" [{status_code}] {title} ({mine_type})")
205
+ if structure:
206
+ _print_params_tree(structure, indent=4)
207
+
208
+
209
+ def _print_params_tree(params: list[dict], indent: int = 0, prefix: str = "") -> None:
210
+ """递归打印参数树结构."""
211
+ for p in params:
212
+ ptype = p.get("type", "?")
213
+ name = p.get("name", "?")
214
+ title = p.get("title", "")
215
+ required = " *" if p.get("required") else ""
216
+ desc = p.get("description", "")
217
+ line = f"{' ' * indent}- {prefix}{name}: {title} ({ptype}){required}"
218
+ if desc:
219
+ line += f" # {desc}"
220
+ print(line)
221
+ if ptype in ("object", "array"):
222
+ children = p.get("children", [])
223
+ if children:
224
+ if ptype == "array":
225
+ _print_params_tree(children, indent + 2)
226
+ else:
227
+ _print_params_tree(children, indent + 2)
dataops_cli/cli/auth.py CHANGED
@@ -12,6 +12,7 @@ import typer
12
12
  from rich.console import Console
13
13
  from rich.table import Table
14
14
 
15
+ from dataops_cli.cli.utils import print_list
15
16
  from dataops_cli.constants import USER_INFO_FILE
16
17
  from dataops_cli.exceptions import AuthenticationError
17
18
  from dataops_cli.schems import UserInfo
@@ -135,11 +136,13 @@ def application_list(query: Annotated[str | None, typer.Argument(help="关键字
135
136
  typer.echo(f"错误: {e}")
136
137
  raise typer.Exit(code=1) from None
137
138
 
138
- table = Table("code", "title", "remark", title="应用列表")
139
- for application in applications:
140
- table.add_row(application.CODE, application.LABEL_CN, application.REMARK or "")
141
- console = Console(no_color=True)
142
- console.print(table)
139
+ print_list(
140
+ ["code", "title", "remark"],
141
+ [
142
+ [application.CODE, application.LABEL_CN, application.REMARK]
143
+ for application in applications
144
+ ],
145
+ )
143
146
 
144
147
 
145
148
  @application_typer.command("set")
@@ -11,7 +11,7 @@ import typer
11
11
  from rich.console import Console
12
12
  from rich.table import Table
13
13
 
14
- from dataops_cli.cli.utils import render_table
14
+ from dataops_cli.cli.utils import print_list, render_table
15
15
  from dataops_cli.exceptions import DataOpsError
16
16
  from dataops_cli.schems import MetaType, PageParam, SqlQueryParam
17
17
  from dataops_cli.sdk import (
@@ -63,11 +63,10 @@ def list_datatable(
63
63
  if query:
64
64
  group_nodes = filter_nodes_by_pattern(group_nodes, query, include_digest=True)
65
65
 
66
- table = Table("code", "title", "remark")
67
- console = Console(no_color=True)
68
- for column in group_nodes:
69
- table.add_row(column.CODE, column.TITLE, column.REMARK or "")
70
- console.print(table)
66
+ print_list(
67
+ ["code", "title", "remark"],
68
+ [[column.CODE, column.TITLE, column.REMARK] for column in group_nodes],
69
+ )
71
70
 
72
71
 
73
72
  @data_table_typer.command("detail", no_args_is_help=True)
@@ -4,9 +4,9 @@ import typer
4
4
  from rich.console import Console
5
5
  from rich.table import Table
6
6
 
7
+ from dataops_cli.cli.utils import print_list
7
8
  from dataops_cli.exceptions import DataOpsError
8
- from dataops_cli.schems import DataSourceDDL, MetaType
9
- from dataops_cli.sdk.meta import release_list_get_by_code, release_list_list
9
+ from dataops_cli.sdk import service_get_dataset_detail_by_code, service_list_datasets
10
10
  from dataops_cli.utils import filter_nodes_by_pattern
11
11
 
12
12
  dataset_typer = typer.Typer(name="dataset", help="Manage dataset.", no_args_is_help=True)
@@ -28,7 +28,7 @@ def list_dataset(
28
28
  >>> data-ops-cli dataset list "HHI.*"
29
29
  """
30
30
  try:
31
- group_nodes = release_list_list(MetaType.DATASET.value)
31
+ group_nodes = service_list_datasets()
32
32
  except DataOpsError as e:
33
33
  typer.echo(f"错误: {e.message}")
34
34
  raise typer.Exit(code=1) from None
@@ -36,11 +36,10 @@ def list_dataset(
36
36
  if query:
37
37
  group_nodes = filter_nodes_by_pattern(group_nodes, query, include_digest=True)
38
38
 
39
- table = Table("code", "name", "alias", "remark", title="dataset list")
40
- console = Console(no_color=True)
41
- for column in group_nodes:
42
- table.add_row(column.CODE, column.NAME, column.TITLE, column.REMARK or "")
43
- console.print(table)
39
+ print_list(
40
+ ["code", "name", "alias", "remark"],
41
+ [[column.CODE, column.NAME, column.TITLE, column.REMARK] for column in group_nodes],
42
+ )
44
43
 
45
44
 
46
45
  @dataset_typer.command("detail", no_args_is_help=True)
@@ -61,7 +60,7 @@ def get_dataset_detail_by_code(
61
60
  >>> data-ops-cli dataset detail my_dataset_code --full
62
61
  """
63
62
  try:
64
- meta = release_list_get_by_code(MetaType.DATASET.value, code, _class=DataSourceDDL)
63
+ meta = service_get_dataset_detail_by_code(code)
65
64
  except DataOpsError as e:
66
65
  typer.echo(f"错误: {e.message}")
67
66
  raise typer.Exit(code=1) from None
@@ -16,12 +16,20 @@ from rich.table import Table
16
16
 
17
17
  from dataops_cli.exceptions import DataOpsError
18
18
  from dataops_cli.schems import (
19
+ DataDataSource,
19
20
  InnerMetaType,
21
+ MetaCreate,
20
22
  )
21
- from dataops_cli.sdk.datasource import get_application_datasource_config, get_datasource
22
- from dataops_cli.sdk.meta import release_list_list
23
- from dataops_cli.sdk.table import (
24
- service_get_table_data_by_name,
23
+ from dataops_cli.schems.enums import DataSourceType
24
+ from dataops_cli.sdk.datasource import (
25
+ get_application_datasource_config,
26
+ service_get_datasource_by_name,
27
+ )
28
+ from dataops_cli.sdk.meta import (
29
+ release_list_create,
30
+ release_list_get_by_name,
31
+ release_list_list,
32
+ release_list_update,
25
33
  )
26
34
  from dataops_cli.session import get_application
27
35
  from dataops_cli.utils import filter_nodes_by_pattern
@@ -95,5 +103,93 @@ def list_datasource(
95
103
  console.print(table)
96
104
 
97
105
 
106
+ @datasource_typer.command("detail")
107
+ def get_datasource_detail(
108
+ name: Annotated[str, typer.Argument(help="数据源名称")],
109
+ ) -> None:
110
+ """获取指定数据源的详细信息.
111
+
112
+ Args:
113
+ name: 数据源名称
114
+ """
115
+ meta = service_get_datasource_by_name(name)
116
+ table = Table("field", "value", show_header=False)
117
+ table.add_row("name", meta.name)
118
+ table.add_row("title", meta.title)
119
+ table.add_row("分组", meta.groupCode)
120
+ table.add_row("数据库类型", meta.data.type.value)
121
+ table.add_row("地址", meta.data.ip)
122
+ table.add_row("端口", str(meta.data.port))
123
+ table.add_row("数据库账户", meta.data.username)
124
+ table.add_row("说明", meta.remark or "")
125
+ console = Console(no_color=True)
126
+ console.print(table)
127
+
128
+
129
+ @datasource_typer.command("create", no_args_is_help=True)
130
+ def create_datasource(
131
+ name: Annotated[str, typer.Option(help="数据源名称")],
132
+ title: Annotated[str, typer.Option(help="数据源中文名称")],
133
+ type: Annotated[DataSourceType, typer.Option("-t", "--type", help="数据源类型")],
134
+ ip: Annotated[str, typer.Option(help="数据源 IP 地址")],
135
+ port: Annotated[int, typer.Option("-p", "--port", help="数据源端口号")],
136
+ username: Annotated[str, typer.Option("-u", "--username", help="数据源用户名")],
137
+ password: Annotated[str, typer.Option(help="数据源密码", hide_input=True)],
138
+ database: Annotated[str, typer.Option("-db", "--database", help="数据库名称")],
139
+ remark: Annotated[str | None, typer.Option(help="数据源备注")] = None,
140
+ ) -> None:
141
+ """创建新的数据源."""
142
+ meta_create = MetaCreate[DataDataSource](
143
+ type="datasource",
144
+ subType=f"database__{type.value}",
145
+ name=name,
146
+ title=title,
147
+ remark=remark,
148
+ groupCode="inner",
149
+ data=DataDataSource(
150
+ type=type, ip=ip, port=port, username=username, password=password, database=database
151
+ ),
152
+ )
153
+ result = release_list_create(meta_create, _class=DataDataSource)
154
+ typer.echo(f"数据源 {result.name} 创建成功")
155
+
156
+
157
+ @datasource_typer.command("update", no_args_is_help=True)
158
+ def update_datasource(
159
+ name: Annotated[str, typer.Argument(help="数据源名称")],
160
+ title: Annotated[str | None, typer.Option(help="数据源中文名称")] = None,
161
+ type: Annotated[DataSourceType | None, typer.Option("-t", "--type", help="数据源类型")] = None,
162
+ ip: Annotated[str | None, typer.Option(help="数据源 IP 地址")] = None,
163
+ port: Annotated[int | None, typer.Option("-p", "--port", help="数据源端口号")] = None,
164
+ username: Annotated[str | None, typer.Option("-u", "--username", help="数据源用户名")] = None,
165
+ password: Annotated[str | None, typer.Option(help="数据源密码", hide_input=True)] = None,
166
+ database: Annotated[str | None, typer.Option("-db", "--database", help="数据库名称")] = None,
167
+ remark: Annotated[str | None, typer.Option(help="数据源备注")] = None,
168
+ ) -> None:
169
+ """更新已有的数据源."""
170
+ meta = release_list_get_by_name(InnerMetaType.DATASOURCE.value, name, _class=DataDataSource)
171
+ if type:
172
+ meta.data.type = type
173
+ meta.subType = f"database__{type.value}"
174
+ if title:
175
+ meta.title = title
176
+ if ip:
177
+ meta.data.ip = ip
178
+ if port:
179
+ meta.data.port = port
180
+ if username:
181
+ meta.data.username = username
182
+ if password:
183
+ meta.data.password = password
184
+ if database:
185
+ meta.data.database = database
186
+ if remark:
187
+ meta.remark = remark
188
+
189
+ result = release_list_update(meta, _class=DataDataSource)
190
+ typer.echo(f"数据源 {result.name} 更新成功")
191
+
192
+
98
193
  if __name__ == "__main__":
99
- service_get_table_data_by_name("doris", "t_trans_ne")
194
+ print(DataDataSource.model_json_schema())
195
+ # list_datasource("doris")
@@ -0,0 +1,96 @@
1
+ from typing import Annotated, Optional
2
+
3
+ import typer
4
+ from rich.console import Console
5
+ from rich.table import Table
6
+
7
+ from dataops_cli.cli.utils import print_list
8
+ from dataops_cli.exceptions import DataOpsError
9
+ from dataops_cli.sdk.dict_ import (
10
+ service_get_dict_detail_by_code,
11
+ service_get_dict_detail_by_name,
12
+ service_list_dicts,
13
+ )
14
+ from dataops_cli.utils import filter_nodes_by_pattern
15
+
16
+ dict_typer = typer.Typer(name="dict", help="Manage dict.", no_args_is_help=True)
17
+
18
+
19
+ @dict_typer.command("list")
20
+ def list_dict(
21
+ datasource: Annotated[str, typer.Argument(help="数据源")],
22
+ query: Annotated[str | None, typer.Argument(help="字典名称关键字")] = None,
23
+ ) -> None:
24
+ """列出数据源中的字典列表.
25
+
26
+ 支持通过关键字过滤字典名称,并支持正则表达式匹配。
27
+
28
+ 示例:
29
+ # 列出指定数据源的所有字典
30
+ >>> data-ops-cli dict list <datasource>
31
+
32
+ # 列出数据源中名称包含 "user" 的字典
33
+ >>> data-ops-cli dict list <datasource> user
34
+
35
+ # 使用正则过滤字典名
36
+ >>> data-ops-cli dict list <datasource> "^user_.*"
37
+ """
38
+ try:
39
+ group_nodes = service_list_dicts(datasource)
40
+ except DataOpsError as e:
41
+ typer.echo(f"错误: {e.message}")
42
+ raise typer.Exit(code=1) from None
43
+
44
+ if not group_nodes:
45
+ print("未查询到匹配字典")
46
+ return
47
+
48
+ if query:
49
+ group_nodes = filter_nodes_by_pattern(group_nodes, query)
50
+
51
+ print_list(
52
+ ["code", "name", "alias"],
53
+ [[column.CODE, column.NAME, column.TITLE] for column in group_nodes],
54
+ )
55
+
56
+
57
+ @dict_typer.command("detail", no_args_is_help=True)
58
+ def get_dict_detail(
59
+ arg1: Annotated[str, typer.Argument(help="编码或数据源")],
60
+ name: Annotated[Optional[str], typer.Argument(help="字典名称")] = None,
61
+ full: Annotated[bool, typer.Option("--full", help="是否显示完整信息")] = False,
62
+ ) -> None:
63
+ """获取字典详情信息.
64
+
65
+ 支持两种查询方式:
66
+ 1. 通过字典编码(CODE)直接查询
67
+ 2. 通过数据源名称和字典名称组合查询
68
+
69
+ 默认只显示字典选项的基本信息(label/value)。
70
+ 使用 --full 选项可显示完整信息。
71
+
72
+ 示例:
73
+ # 通过字典编码查询字典结构
74
+ >>> data-ops-cli dict detail dict_code_123
75
+
76
+ # 通过数据源和字典名查询
77
+ >>> data-ops-cli dict detail <datasource> my_dict
78
+
79
+ # 显示完整的字典信息
80
+ >>> data-ops-cli dict detail <datasource> my_dict --full
81
+ """
82
+ try:
83
+ meta = (
84
+ service_get_dict_detail_by_name(arg1, name)
85
+ if name
86
+ else service_get_dict_detail_by_code(arg1)
87
+ )
88
+ except DataOpsError as e:
89
+ typer.echo(f"错误: {e.message}")
90
+ raise typer.Exit(code=1) from None
91
+
92
+ console = Console(no_color=True)
93
+ table = Table("value", "label", title=f"{arg1} {meta.name} dict")
94
+ for option in meta.data.options:
95
+ table.add_row(str(option.value), option.label)
96
+ console.print(table)