data-ops-cli 0.2.3__tar.gz → 0.2.4__tar.gz
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.
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/PKG-INFO +1 -1
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/PKG-INFO +1 -1
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/SOURCES.txt +4 -0
- data_ops_cli-0.2.4/src/dataops_cli/__init__.py +1 -0
- data_ops_cli-0.2.4/src/dataops_cli/cli/api.py +227 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/auth.py +8 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/data_table.py +5 -6
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/dataset.py +5 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/datasource.py +5 -6
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/dict_.py +5 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/factory.py +2 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/metrics.py +5 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/report.py +5 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/table.py +103 -31
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/utils.py +12 -0
- data_ops_cli-0.2.4/src/dataops_cli/cli/widget.py +464 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/workflow.py +5 -5
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/constants.py +0 -1
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/dbConn_sync.py +16 -7
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/__init__.py +4 -2
- data_ops_cli-0.2.4/src/dataops_cli/schems/api.py +37 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/meta.py +6 -1
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/table.py +14 -14
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/widget.py +107 -11
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/__init__.py +7 -0
- data_ops_cli-0.2.4/src/dataops_cli/sdk/api.py +28 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/datasource.py +7 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/meta.py +37 -28
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/table.py +128 -0
- data_ops_cli-0.2.4/src/dataops_cli/sdk/widget.py +99 -0
- data_ops_cli-0.2.3/src/dataops_cli/__init__.py +0 -1
- data_ops_cli-0.2.3/src/dataops_cli/cli/widget.py +0 -60
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/README.md +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/pyproject.toml +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/setup.cfg +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/dependency_links.txt +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/entry_points.txt +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/requires.txt +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/data_ops_cli.egg-info/top_level.txt +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/__init__.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/cli/ref.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/exceptions.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/__init__.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/__init__.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/config.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/constants.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/instance.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/nacos_exception.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/naming_param.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/naming_request.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/naming_response.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/preserved_metadata_key.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/schemas/nacos/service.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/__init__.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/common.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/dbConn_base.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/duckdb_manager.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/log.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/nacos.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/runner/utils/neo4j_sync.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/data_table.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/datasource.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/dict_.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/enums.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/group.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/query.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/report.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/user.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/schems/workflow.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/auth.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/data_table.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/dataset.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/dict_.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/ref.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/report.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/sdk/workflow.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/session.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/__init__.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/builder.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/constants.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/models.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/parse_utils.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/render_utils.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/renderers.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/tiptap/tool.py +0 -0
- {data_ops_cli-0.2.3 → data_ops_cli-0.2.4}/src/dataops_cli/utils.py +0 -0
|
@@ -12,6 +12,7 @@ src/dataops_cli/exceptions.py
|
|
|
12
12
|
src/dataops_cli/session.py
|
|
13
13
|
src/dataops_cli/utils.py
|
|
14
14
|
src/dataops_cli/cli/__init__.py
|
|
15
|
+
src/dataops_cli/cli/api.py
|
|
15
16
|
src/dataops_cli/cli/auth.py
|
|
16
17
|
src/dataops_cli/cli/data_table.py
|
|
17
18
|
src/dataops_cli/cli/dataset.py
|
|
@@ -45,6 +46,7 @@ src/dataops_cli/runner/utils/log.py
|
|
|
45
46
|
src/dataops_cli/runner/utils/nacos.py
|
|
46
47
|
src/dataops_cli/runner/utils/neo4j_sync.py
|
|
47
48
|
src/dataops_cli/schems/__init__.py
|
|
49
|
+
src/dataops_cli/schems/api.py
|
|
48
50
|
src/dataops_cli/schems/data_table.py
|
|
49
51
|
src/dataops_cli/schems/datasource.py
|
|
50
52
|
src/dataops_cli/schems/dict_.py
|
|
@@ -58,6 +60,7 @@ src/dataops_cli/schems/user.py
|
|
|
58
60
|
src/dataops_cli/schems/widget.py
|
|
59
61
|
src/dataops_cli/schems/workflow.py
|
|
60
62
|
src/dataops_cli/sdk/__init__.py
|
|
63
|
+
src/dataops_cli/sdk/api.py
|
|
61
64
|
src/dataops_cli/sdk/auth.py
|
|
62
65
|
src/dataops_cli/sdk/data_table.py
|
|
63
66
|
src/dataops_cli/sdk/dataset.py
|
|
@@ -67,6 +70,7 @@ src/dataops_cli/sdk/meta.py
|
|
|
67
70
|
src/dataops_cli/sdk/ref.py
|
|
68
71
|
src/dataops_cli/sdk/report.py
|
|
69
72
|
src/dataops_cli/sdk/table.py
|
|
73
|
+
src/dataops_cli/sdk/widget.py
|
|
70
74
|
src/dataops_cli/sdk/workflow.py
|
|
71
75
|
src/dataops_cli/tiptap/__init__.py
|
|
72
76
|
src/dataops_cli/tiptap/builder.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.4"
|
|
@@ -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)
|
|
@@ -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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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,6 +4,7 @@ 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
9
|
from dataops_cli.sdk import service_get_dataset_detail_by_code, service_list_datasets
|
|
9
10
|
from dataops_cli.utils import filter_nodes_by_pattern
|
|
@@ -35,11 +36,10 @@ def list_dataset(
|
|
|
35
36
|
if query:
|
|
36
37
|
group_nodes = filter_nodes_by_pattern(group_nodes, query, include_digest=True)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
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
|
+
)
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
@dataset_typer.command("detail", no_args_is_help=True)
|
|
@@ -19,19 +19,18 @@ from dataops_cli.schems import (
|
|
|
19
19
|
DataDataSource,
|
|
20
20
|
InnerMetaType,
|
|
21
21
|
MetaCreate,
|
|
22
|
-
MetaUpdate,
|
|
23
22
|
)
|
|
24
23
|
from dataops_cli.schems.enums import DataSourceType
|
|
25
|
-
from dataops_cli.sdk.datasource import
|
|
24
|
+
from dataops_cli.sdk.datasource import (
|
|
25
|
+
get_application_datasource_config,
|
|
26
|
+
service_get_datasource_by_name,
|
|
27
|
+
)
|
|
26
28
|
from dataops_cli.sdk.meta import (
|
|
27
29
|
release_list_create,
|
|
28
30
|
release_list_get_by_name,
|
|
29
31
|
release_list_list,
|
|
30
32
|
release_list_update,
|
|
31
33
|
)
|
|
32
|
-
from dataops_cli.sdk.table import (
|
|
33
|
-
service_get_table_data_by_name,
|
|
34
|
-
)
|
|
35
34
|
from dataops_cli.session import get_application
|
|
36
35
|
from dataops_cli.utils import filter_nodes_by_pattern
|
|
37
36
|
|
|
@@ -113,7 +112,7 @@ def get_datasource_detail(
|
|
|
113
112
|
Args:
|
|
114
113
|
name: 数据源名称
|
|
115
114
|
"""
|
|
116
|
-
meta =
|
|
115
|
+
meta = service_get_datasource_by_name(name)
|
|
117
116
|
table = Table("field", "value", show_header=False)
|
|
118
117
|
table.add_row("name", meta.name)
|
|
119
118
|
table.add_row("title", meta.title)
|
|
@@ -4,6 +4,7 @@ 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
9
|
from dataops_cli.sdk.dict_ import (
|
|
9
10
|
service_get_dict_detail_by_code,
|
|
@@ -47,11 +48,10 @@ def list_dict(
|
|
|
47
48
|
if query:
|
|
48
49
|
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
console.print(table)
|
|
51
|
+
print_list(
|
|
52
|
+
["code", "name", "alias"],
|
|
53
|
+
[[column.CODE, column.NAME, column.TITLE] for column in group_nodes],
|
|
54
|
+
)
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
@dict_typer.command("detail", no_args_is_help=True)
|
|
@@ -25,6 +25,7 @@ def main(
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def create_app():
|
|
28
|
+
from dataops_cli.cli.api import api_typer
|
|
28
29
|
from dataops_cli.cli.auth import auth_typer
|
|
29
30
|
from dataops_cli.cli.data_table import data_table_typer
|
|
30
31
|
from dataops_cli.cli.dataset import dataset_typer
|
|
@@ -44,6 +45,7 @@ def create_app():
|
|
|
44
45
|
short_help=True,
|
|
45
46
|
)
|
|
46
47
|
app.add_typer(auth_typer)
|
|
48
|
+
app.add_typer(api_typer)
|
|
47
49
|
app.add_typer(datasource_typer)
|
|
48
50
|
app.add_typer(dataset_typer)
|
|
49
51
|
app.add_typer(table_typer)
|
|
@@ -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.schems.enums import MetaType
|
|
16
17
|
from dataops_cli.schems.query import SqlQueryParam
|
|
17
18
|
from dataops_cli.sdk.meta import (
|
|
@@ -56,11 +57,10 @@ def list_metrics(
|
|
|
56
57
|
|
|
57
58
|
if query:
|
|
58
59
|
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.print(table)
|
|
60
|
+
print_list(
|
|
61
|
+
["code", "title", "subType"],
|
|
62
|
+
[[column.CODE, column.TITLE, column.SUB_TYPE or "atomic"] for column in group_nodes],
|
|
63
|
+
)
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
@metrics_typer.command("detail", no_args_is_help=True)
|
|
@@ -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.exceptions import DataOpsError
|
|
16
17
|
from dataops_cli.schems import MetaType
|
|
17
18
|
from dataops_cli.sdk.meta import (
|
|
@@ -51,11 +52,10 @@ def list_reports(
|
|
|
51
52
|
if query:
|
|
52
53
|
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
console.print(table)
|
|
55
|
+
print_list(
|
|
56
|
+
["code", "title", "subType"],
|
|
57
|
+
[[column.CODE, column.TITLE, column.SUB_TYPE or "doc"] for column in group_nodes],
|
|
58
|
+
)
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@report_typer.command("detail", rich_help_panel="报告查询")
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
from typing import Annotated, Optional
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
|
-
from
|
|
5
|
-
from rich.table import Table
|
|
4
|
+
from pydantic import BaseModel
|
|
6
5
|
|
|
7
|
-
from dataops_cli.cli.utils import render_table
|
|
6
|
+
from dataops_cli.cli.utils import print_list, render_table
|
|
8
7
|
from dataops_cli.exceptions import DataOpsError
|
|
9
8
|
from dataops_cli.schems import (
|
|
9
|
+
DataBaseColumnDictExternal,
|
|
10
10
|
DataBaseColumnReference,
|
|
11
11
|
DataBaseColumnReferenceValue,
|
|
12
|
-
|
|
12
|
+
DataBaseColumnTableExternal,
|
|
13
13
|
PageParam,
|
|
14
14
|
SqlQueryParam,
|
|
15
15
|
)
|
|
16
|
+
from dataops_cli.schems.table import ColumnItem
|
|
16
17
|
from dataops_cli.sdk import (
|
|
17
18
|
release_list_update,
|
|
18
19
|
service_count_table_by_code,
|
|
@@ -24,6 +25,7 @@ from dataops_cli.sdk import (
|
|
|
24
25
|
service_get_table_detail_by_name,
|
|
25
26
|
service_list_tables,
|
|
26
27
|
)
|
|
28
|
+
from dataops_cli.sdk.table import service_exec_sql_by_datasource
|
|
27
29
|
from dataops_cli.utils import filter_nodes_by_pattern
|
|
28
30
|
|
|
29
31
|
table_typer = typer.Typer(name="table", help="Manage table.", no_args_is_help=True)
|
|
@@ -64,19 +66,17 @@ def list_table(
|
|
|
64
66
|
|
|
65
67
|
if query:
|
|
66
68
|
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
table.add_row(column.CODE, column.NAME, column.TITLE, column.REMARK or "")
|
|
72
|
-
console.print(table)
|
|
69
|
+
print_list(
|
|
70
|
+
["code", "name", "alias", "remark"],
|
|
71
|
+
[[column.CODE, column.NAME, column.TITLE, column.REMARK] for column in group_nodes],
|
|
72
|
+
)
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
@table_typer.command("detail", no_args_is_help=True)
|
|
76
76
|
def get_table_detail(
|
|
77
77
|
arg1: Annotated[str, typer.Argument(help="编码或数据源")],
|
|
78
78
|
name: Annotated[Optional[str], typer.Argument(help="表名")] = None,
|
|
79
|
-
full: Annotated[bool, typer.Option(help="
|
|
79
|
+
full: Annotated[bool, typer.Option("--full", help="显示完整DDL信息")] = False,
|
|
80
80
|
) -> None:
|
|
81
81
|
"""获取表详情(DDL)信息.
|
|
82
82
|
|
|
@@ -109,26 +109,58 @@ def get_table_detail(
|
|
|
109
109
|
|
|
110
110
|
datasource = meta.subSystem
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
112
|
+
print(datasource, meta.name)
|
|
113
|
+
|
|
114
|
+
def show_column(column: ColumnItem):
|
|
115
|
+
if column.pk and column.labelKey:
|
|
116
|
+
return f"{column.name}(√,√)"
|
|
117
|
+
elif column.pk:
|
|
118
|
+
return f"{column.name}(√,x)"
|
|
119
|
+
elif column.labelKey:
|
|
120
|
+
return f"{column.name}(x,√)"
|
|
121
|
+
else:
|
|
122
|
+
return column.name
|
|
123
|
+
|
|
124
|
+
def show_extend(column: ColumnItem):
|
|
125
|
+
output = []
|
|
126
|
+
if column.decimalPlace:
|
|
127
|
+
output.append(f"{column.decimalPlace}dp")
|
|
128
|
+
if column.nullable:
|
|
129
|
+
output.append("nullable")
|
|
130
|
+
else:
|
|
131
|
+
output.append("not-null")
|
|
132
|
+
return ",".join(output)
|
|
133
|
+
|
|
134
|
+
if not full:
|
|
135
|
+
print("column(pk,labelKey)", "alias", "dbType(length)")
|
|
136
|
+
print(
|
|
137
|
+
"\n".join(
|
|
138
|
+
(
|
|
139
|
+
f"{show_column(column)} {column.title} {column.dbType}({column.length})"
|
|
140
|
+
if column.pk
|
|
141
|
+
else ""
|
|
142
|
+
for column in meta.data.columns
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
)
|
|
127
146
|
else:
|
|
128
|
-
|
|
147
|
+
print("columns info\ncolumn(pk,labelKey)", "alias", "dbType(length)", "extend", "relation")
|
|
129
148
|
for column in meta.data.columns:
|
|
130
|
-
|
|
131
|
-
|
|
149
|
+
relation = None
|
|
150
|
+
if isinstance(column.typeExt, BaseModel):
|
|
151
|
+
relation = column.typeExt.model_dump_json()
|
|
152
|
+
print(
|
|
153
|
+
show_column(column),
|
|
154
|
+
column.title,
|
|
155
|
+
f"{column.dbType}({column.length})",
|
|
156
|
+
show_extend(column),
|
|
157
|
+
relation,
|
|
158
|
+
)
|
|
159
|
+
if meta.data.indexes:
|
|
160
|
+
print("\nindexes info\nname columns")
|
|
161
|
+
print("\n".join((f"{index.name} {index.columns}" for index in meta.data.indexes)))
|
|
162
|
+
else:
|
|
163
|
+
print("\nindexes info\n无索引信息")
|
|
132
164
|
|
|
133
165
|
|
|
134
166
|
@table_typer.command("count", no_args_is_help=True)
|
|
@@ -222,6 +254,46 @@ def get_table_data(
|
|
|
222
254
|
print(render_table(data))
|
|
223
255
|
|
|
224
256
|
|
|
257
|
+
@table_typer.command("exec", no_args_is_help=True)
|
|
258
|
+
def exec_sql(
|
|
259
|
+
datasource: Annotated[str, typer.Argument(help="数据源")],
|
|
260
|
+
sql: Annotated[str, typer.Argument(help="SQL 查询语句")],
|
|
261
|
+
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
262
|
+
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
263
|
+
) -> None:
|
|
264
|
+
"""执行任意 SQL 查询语句.
|
|
265
|
+
|
|
266
|
+
支持两种查询方式:
|
|
267
|
+
1. 通过表编码(CODE)直接查询
|
|
268
|
+
2. 通过数据源名称和表名组合查询
|
|
269
|
+
|
|
270
|
+
示例:
|
|
271
|
+
# 通过数据源 SQL
|
|
272
|
+
>>> data-ops-cli table exec-sql mydatasource "SELECT * FROM table LIMIT 10"
|
|
273
|
+
|
|
274
|
+
# 分页查询
|
|
275
|
+
>>> data-ops-cli table exec-sql mydatasource "SELECT * FROM table" --page-num 1 --page-size 50
|
|
276
|
+
|
|
277
|
+
# 以字典格式输出
|
|
278
|
+
>>> data-ops-cli table exec-sql mydatasource "SELECT * FROM table" --map
|
|
279
|
+
"""
|
|
280
|
+
if not sql:
|
|
281
|
+
typer.echo("请输入 SQL 查询语句")
|
|
282
|
+
raise typer.Exit(code=1)
|
|
283
|
+
try:
|
|
284
|
+
datas = service_exec_sql_by_datasource(datasource, sql, page_num, page_size)
|
|
285
|
+
except DataOpsError as e:
|
|
286
|
+
typer.echo(f"错误: {e.message}")
|
|
287
|
+
raise typer.Exit(code=1) from None
|
|
288
|
+
if not datas:
|
|
289
|
+
print("未查询到数据")
|
|
290
|
+
return
|
|
291
|
+
columns_name = datas[0].keys()
|
|
292
|
+
print(*columns_name)
|
|
293
|
+
for data in datas:
|
|
294
|
+
print(*data.values())
|
|
295
|
+
|
|
296
|
+
|
|
225
297
|
@column_typer.command("base", no_args_is_help=True)
|
|
226
298
|
def set_column_config(
|
|
227
299
|
datasource: Annotated[str, typer.Argument(help="编数据源")],
|
|
@@ -262,7 +334,7 @@ def set_column_dict_config(
|
|
|
262
334
|
column_item = next(filter(lambda c: c.name == column, table_meta.data.columns))
|
|
263
335
|
dict_meta = service_get_dict_detail_by_name(datasource, dict_name)
|
|
264
336
|
column_item.type = "dict"
|
|
265
|
-
column_item.typeExt =
|
|
337
|
+
column_item.typeExt = DataBaseColumnDictExternal(
|
|
266
338
|
ref__dict=DataBaseColumnReference(type="dict", code=dict_meta.code)
|
|
267
339
|
)
|
|
268
340
|
result = release_list_update(table_meta)
|
|
@@ -283,7 +355,7 @@ def set_column_dict_config(
|
|
|
283
355
|
dst_table_meta = service_get_table_detail_by_name(datasource, r_name)
|
|
284
356
|
dst_column_item = next(filter(lambda c: c.name == r_col_name, dst_table_meta.data.columns))
|
|
285
357
|
column_item.type = "relation"
|
|
286
|
-
column_item.typeExt =
|
|
358
|
+
column_item.typeExt = DataBaseColumnTableExternal(
|
|
287
359
|
ref__table=DataBaseColumnReference(type="table", code=dst_table_meta.code),
|
|
288
360
|
ref__valueField=DataBaseColumnReferenceValue(
|
|
289
361
|
type="table", code=dst_table_meta.code, subtype="column", subcode=dst_column_item.id
|