data-ops-cli 0.4.0__tar.gz → 0.4.1__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.4.0 → data_ops_cli-0.4.1}/PKG-INFO +2 -2
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/pyproject.toml +1 -1
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/PKG-INFO +2 -2
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/SOURCES.txt +2 -1
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/requires.txt +1 -1
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/__init__.py +1 -1
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/auth.py +23 -16
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/dataset.py +46 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/metrics.py +68 -4
- data_ops_cli-0.4.1/src/dataops_cli/cli/report.py +142 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/skill.py +17 -2
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/table.py +162 -7
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/utils.py +73 -1
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/widget.py +40 -5
- data_ops_cli-0.4.1/tests/test_table_relation.py +450 -0
- data_ops_cli-0.4.0/src/dataops_cli/cli/report.py +0 -81
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/README.md +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/setup.cfg +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/dependency_links.txt +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/entry_points.txt +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/data_ops_cli.egg-info/top_level.txt +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/_compat.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/__init__.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/alarm.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/api.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/data_table.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/datasource.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/dict_.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/factory.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/hazard.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/ref.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/cli/workflow.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/exceptions.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/runner.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/schems.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/sdk.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/session.py +0 -0
- {data_ops_cli-0.4.0 → data_ops_cli-0.4.1}/src/dataops_cli/utils.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: data-ops-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Command-line wrapper around dataops_sdk for the DataOps platform.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: dataops-sdk[runner]>=0.4.
|
|
7
|
+
Requires-Dist: dataops-sdk[runner]>=0.4.1
|
|
8
8
|
Requires-Dist: typer
|
|
9
9
|
Requires-Dist: rich
|
|
10
10
|
Provides-Extra: dev
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: data-ops-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Command-line wrapper around dataops_sdk for the DataOps platform.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: dataops-sdk[runner]>=0.4.
|
|
7
|
+
Requires-Dist: dataops-sdk[runner]>=0.4.1
|
|
8
8
|
Requires-Dist: typer
|
|
9
9
|
Requires-Dist: rich
|
|
10
10
|
Provides-Extra: dev
|
|
@@ -9,14 +9,13 @@
|
|
|
9
9
|
from typing import Annotated
|
|
10
10
|
|
|
11
11
|
import typer
|
|
12
|
-
from dataops_sdk.constants import USER_INFO_FILE
|
|
12
|
+
from dataops_sdk.constants import APPLICATION_FILE, USER_INFO_FILE
|
|
13
13
|
from dataops_sdk.exceptions import AuthenticationError
|
|
14
14
|
from dataops_sdk.schemas import UserInfo
|
|
15
15
|
from dataops_sdk.services.auth import (
|
|
16
16
|
service_get_current_application,
|
|
17
17
|
service_list_applications,
|
|
18
18
|
service_login,
|
|
19
|
-
service_logout,
|
|
20
19
|
service_set_application,
|
|
21
20
|
)
|
|
22
21
|
from dataops_sdk.services.datasource import (
|
|
@@ -33,6 +32,15 @@ application_typer = typer.Typer(name="application", help="应用相关命令", n
|
|
|
33
32
|
auth_typer.add_typer(application_typer)
|
|
34
33
|
|
|
35
34
|
|
|
35
|
+
def _require_login() -> None:
|
|
36
|
+
"""未登录时引导登录并退出。"""
|
|
37
|
+
if not get_work_dir(USER_INFO_FILE).exists():
|
|
38
|
+
typer.echo("未登录,请先执行登录:")
|
|
39
|
+
typer.echo(" data-ops-cli auth login <用户名> <密码>")
|
|
40
|
+
typer.echo("登录后执行 data-ops-cli auth application set <应用code> 设置应用")
|
|
41
|
+
raise typer.Exit(code=401)
|
|
42
|
+
|
|
43
|
+
|
|
36
44
|
@auth_typer.command("status")
|
|
37
45
|
def auth_status() -> None:
|
|
38
46
|
"""显示当前认证状态。
|
|
@@ -43,13 +51,9 @@ def auth_status() -> None:
|
|
|
43
51
|
如果已登录但未设置应用,提示用户设置应用;
|
|
44
52
|
否则同时输出应用关联的主/隐患数据源信息。
|
|
45
53
|
"""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
print("未登录")
|
|
49
|
-
else:
|
|
50
|
-
user_info = UserInfo.model_validate_json(target_path.read_bytes())
|
|
54
|
+
_require_login()
|
|
55
|
+
user_info = UserInfo.model_validate_json(get_work_dir(USER_INFO_FILE).read_bytes())
|
|
51
56
|
try:
|
|
52
|
-
# application
|
|
53
57
|
application = service_get_current_application()
|
|
54
58
|
datasource_config = service_get_main_datasource_config_by_application()
|
|
55
59
|
except AuthenticationError:
|
|
@@ -120,11 +124,11 @@ def logout() -> None:
|
|
|
120
124
|
Examples:
|
|
121
125
|
>>> data-ops-cli auth logout
|
|
122
126
|
"""
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
for filename in (USER_INFO_FILE, APPLICATION_FILE):
|
|
128
|
+
path = get_work_dir(filename)
|
|
129
|
+
if path.exists() and path.is_file():
|
|
130
|
+
path.unlink()
|
|
131
|
+
print("登出成功,已清除本地登录信息")
|
|
128
132
|
|
|
129
133
|
|
|
130
134
|
@application_typer.command("list")
|
|
@@ -146,6 +150,7 @@ def application_list(
|
|
|
146
150
|
通过关键字过滤应用
|
|
147
151
|
>>> data-ops-cli auth application list -q myapp
|
|
148
152
|
"""
|
|
153
|
+
_require_login()
|
|
149
154
|
try:
|
|
150
155
|
applications = service_list_applications(query)
|
|
151
156
|
except Exception as e:
|
|
@@ -175,11 +180,12 @@ def application_set(code: Annotated[str, typer.Argument(help="应用编码")]) -
|
|
|
175
180
|
设置当前应用
|
|
176
181
|
>>> data-ops-cli auth application set myapp_code
|
|
177
182
|
"""
|
|
183
|
+
_require_login()
|
|
178
184
|
try:
|
|
179
185
|
application = service_set_application(code)
|
|
180
|
-
except ValueError
|
|
181
|
-
typer.echo(
|
|
182
|
-
raise typer.Exit(code=1)
|
|
186
|
+
except ValueError:
|
|
187
|
+
typer.echo("输入的code值错误,请重新输入!")
|
|
188
|
+
raise typer.Exit(code=1)
|
|
183
189
|
|
|
184
190
|
table = Table("field", "value", title="应用信息", show_header=False)
|
|
185
191
|
table.add_row("code", application.CODE)
|
|
@@ -197,6 +203,7 @@ def application_info() -> None:
|
|
|
197
203
|
查看当前已设置应用的详细信息,包括编码、标题和备注。
|
|
198
204
|
如果尚未设置应用,提示用户使用 ``auth application set`` 命令进行设置。
|
|
199
205
|
"""
|
|
206
|
+
_require_login()
|
|
200
207
|
application = service_get_current_application()
|
|
201
208
|
if application is None:
|
|
202
209
|
print("未设置应用, 执行 `data-ops-cli auth application set <code>` 进行设置应用.")
|
|
@@ -9,6 +9,7 @@ import typer
|
|
|
9
9
|
from dataops_sdk.exceptions import DataOpsError
|
|
10
10
|
from dataops_sdk.schemas import PageParam, SqlFilter, SqlQueryParam
|
|
11
11
|
from dataops_sdk.services import (
|
|
12
|
+
release_list_update,
|
|
12
13
|
service_count_dataset_by_code,
|
|
13
14
|
service_get_dataset_data_by_code,
|
|
14
15
|
service_get_dataset_detail_by_code,
|
|
@@ -19,6 +20,10 @@ from dataops_sdk.utils import filter_nodes_by_pattern
|
|
|
19
20
|
from dataops_cli.cli.utils import print_list, print_table_column_detail
|
|
20
21
|
|
|
21
22
|
dataset_typer = typer.Typer(name="dataset", help="Manage dataset.", no_args_is_help=True)
|
|
23
|
+
update_typer = typer.Typer(name="update", help="变更", no_args_is_help=True)
|
|
24
|
+
dataset_typer.add_typer(update_typer)
|
|
25
|
+
column_typer = typer.Typer(name="column", help="列变更", no_args_is_help=True)
|
|
26
|
+
update_typer.add_typer(column_typer)
|
|
22
27
|
|
|
23
28
|
|
|
24
29
|
@dataset_typer.command("list")
|
|
@@ -195,3 +200,44 @@ def get_dataset_data(
|
|
|
195
200
|
headers = list(data[0].keys())
|
|
196
201
|
rows = (tuple(row.get(header) for header in headers) for row in data)
|
|
197
202
|
print_list(headers, rows)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@column_typer.command("base", no_args_is_help=True)
|
|
206
|
+
def update_dataset_column(
|
|
207
|
+
code: Annotated[str, typer.Argument(help="数据集编码")],
|
|
208
|
+
column_name: Annotated[str, typer.Argument(help="列名")],
|
|
209
|
+
title: Annotated[str | None, typer.Option(help="中文名称")] = None,
|
|
210
|
+
pk: Annotated[bool | None, typer.Option(help="主键")] = None,
|
|
211
|
+
nullable: Annotated[bool | None, typer.Option(help="是否可为空")] = None,
|
|
212
|
+
labelKey: Annotated[bool | None, typer.Option(help="名称键")] = None,
|
|
213
|
+
remark: Annotated[str | None, typer.Option(help="备注")] = None,
|
|
214
|
+
) -> None:
|
|
215
|
+
"""修改数据集的列基础配置."""
|
|
216
|
+
updates = {
|
|
217
|
+
attr: value
|
|
218
|
+
for attr, value in {
|
|
219
|
+
"title": title,
|
|
220
|
+
"pk": pk,
|
|
221
|
+
"nullable": nullable,
|
|
222
|
+
"labelKey": labelKey,
|
|
223
|
+
"remark": remark,
|
|
224
|
+
}.items()
|
|
225
|
+
if value is not None
|
|
226
|
+
}
|
|
227
|
+
if not updates:
|
|
228
|
+
typer.echo("请输入要修改的列配置", err=True)
|
|
229
|
+
raise typer.Exit(code=1)
|
|
230
|
+
try:
|
|
231
|
+
meta = service_get_dataset_detail_by_code(code)
|
|
232
|
+
assert meta.data, f"数据集 {code} 不存在"
|
|
233
|
+
column_item = next((c for c in meta.data.columns if c.name == column_name), None)
|
|
234
|
+
if column_item is None:
|
|
235
|
+
typer.echo(f"数据集 {code} 中不存在字段 {column_name}")
|
|
236
|
+
raise typer.Exit(code=1)
|
|
237
|
+
for attr, value in updates.items():
|
|
238
|
+
setattr(column_item, attr, value)
|
|
239
|
+
release_list_update(meta)
|
|
240
|
+
except DataOpsError as e:
|
|
241
|
+
typer.echo(f"错误: {e.message}")
|
|
242
|
+
raise typer.Exit(code=1) from None
|
|
243
|
+
typer.echo(f"修改数据集 {code} 字段 {column_item.name} 完成")
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
from typing import Annotated
|
|
10
10
|
|
|
11
11
|
import typer
|
|
12
|
-
from dataops_sdk.
|
|
13
|
-
from dataops_sdk.schemas
|
|
14
|
-
from dataops_sdk.services
|
|
15
|
-
DataOpsError,
|
|
12
|
+
from dataops_sdk.exceptions import DataOpsError
|
|
13
|
+
from dataops_sdk.schemas import MetaType, PageParam, SqlFilter, SqlQueryParam
|
|
14
|
+
from dataops_sdk.services import (
|
|
16
15
|
release_list_get_by_code,
|
|
17
16
|
release_list_list,
|
|
17
|
+
service_get_metrics_data_by_code,
|
|
18
18
|
)
|
|
19
19
|
from dataops_sdk.utils import filter_nodes_by_pattern
|
|
20
20
|
from rich.console import Console
|
|
@@ -175,3 +175,67 @@ def get_metrics_detail(
|
|
|
175
175
|
style.get("color", ""),
|
|
176
176
|
)
|
|
177
177
|
console.print(level_table)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@metrics_typer.command("data", no_args_is_help=True)
|
|
181
|
+
def get_metrics_data(
|
|
182
|
+
code: Annotated[str, typer.Argument(help="指标编码")],
|
|
183
|
+
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
184
|
+
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
185
|
+
filters: Annotated[
|
|
186
|
+
list[SqlFilter] | None,
|
|
187
|
+
typer.Option(
|
|
188
|
+
"--condition",
|
|
189
|
+
"-c",
|
|
190
|
+
parser=SqlFilter.from_str,
|
|
191
|
+
help='查询条件(可多次传入),JSON 格式 {"name":"字段名","value":值[,"expression":"eq"]},expression 缺省 eq',
|
|
192
|
+
),
|
|
193
|
+
] = None,
|
|
194
|
+
dimensions: Annotated[
|
|
195
|
+
list[str] | None,
|
|
196
|
+
typer.Option(
|
|
197
|
+
"--dimension",
|
|
198
|
+
"-d",
|
|
199
|
+
help="维度字段名",
|
|
200
|
+
),
|
|
201
|
+
] = None,
|
|
202
|
+
) -> None:
|
|
203
|
+
"""获取指标实际数据。
|
|
204
|
+
|
|
205
|
+
通过指标编码查询指标维度下的实际数据行,支持分页与查询条件过滤。
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
code: 指标编码。
|
|
209
|
+
page_num: 页码,默认 0。
|
|
210
|
+
page_size: 每页大小,默认 20。
|
|
211
|
+
filters: 查询条件,JSON 格式 ``{"name": 字段名, "value": 值[, "expression": 表达式]}``。
|
|
212
|
+
可多次传入,多个条件按 AND 组合;``expression`` 缺省为 ``eq``,可选
|
|
213
|
+
``eq/ne/gt/ge/lt/le/in/notin/like/notlike/between/notbetween/isnull/isnotnull``。
|
|
214
|
+
|
|
215
|
+
Examples:
|
|
216
|
+
通过指标编码获取指标数据(默认返回前20条)
|
|
217
|
+
>>> data-ops-cli metrics data 1777544300561_98429
|
|
218
|
+
|
|
219
|
+
从第2页开始,每页50条
|
|
220
|
+
>>> data-ops-cli metrics data 1777544300561_98429 --page-num 2 --page-size 50
|
|
221
|
+
|
|
222
|
+
带查询条件过滤(d_cycle_time 等于 2026-04-18)
|
|
223
|
+
>>> data-ops-cli metrics data 1777544300561_98429 -c '{"name":"d_cycle_time","value":"2026-04-18"}'
|
|
224
|
+
"""
|
|
225
|
+
pp = PageParam(start=page_num * page_size, limit=page_size)
|
|
226
|
+
|
|
227
|
+
qp = SqlQueryParam()
|
|
228
|
+
if filters:
|
|
229
|
+
qp.add(*(filter_item.to_condition() for filter_item in filters))
|
|
230
|
+
try:
|
|
231
|
+
data = service_get_metrics_data_by_code(code, pp, qp, dimensions)
|
|
232
|
+
except DataOpsError as e:
|
|
233
|
+
typer.echo(f"错误: {e.message}")
|
|
234
|
+
raise typer.Exit(code=1) from None
|
|
235
|
+
if not data:
|
|
236
|
+
typer.echo("未查询到数据", err=True)
|
|
237
|
+
return
|
|
238
|
+
# 使用第一行字段顺序作为表头,保证每行数据与表头位置对应。
|
|
239
|
+
headers = list(data[0].keys())
|
|
240
|
+
rows = (tuple(row.get(header) for header in headers) for row in data)
|
|
241
|
+
print_list(headers, rows)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""文档管理模块.
|
|
2
|
+
|
|
3
|
+
提供文档的读取和列表查询功能。
|
|
4
|
+
|
|
5
|
+
- 服务层函数 (service_*):纯 Python 接口,返回原始数据
|
|
6
|
+
- CLI 命令:基于服务层的薄包装,负责格式化输出
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Annotated
|
|
10
|
+
|
|
11
|
+
import typer
|
|
12
|
+
from dataops_cli.cli.utils import print_group_tree, print_list
|
|
13
|
+
from dataops_sdk.exceptions import DataOpsError
|
|
14
|
+
from dataops_sdk.schemas import MetaReportSubType, MetaType
|
|
15
|
+
from dataops_sdk.services.meta import (
|
|
16
|
+
release_list_list,
|
|
17
|
+
)
|
|
18
|
+
from dataops_sdk.services.report import service_get_report, servive_tree_report
|
|
19
|
+
from dataops_sdk.utils import filter_nodes_by_pattern
|
|
20
|
+
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
# CLI 命令
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
report_typer = typer.Typer(name="report", help="Manage reports", no_args_is_help=True)
|
|
26
|
+
space_typer = typer.Typer(name="space", help="Manage spaces", no_args_is_help=True)
|
|
27
|
+
report_typer.add_typer(space_typer)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@report_typer.command("list", rich_help_panel="报告查询")
|
|
31
|
+
def list_reports(
|
|
32
|
+
sub_types: Annotated[
|
|
33
|
+
list[MetaReportSubType],
|
|
34
|
+
typer.Option("--type", "-t", help="报告子类型", default_factory=list),
|
|
35
|
+
],
|
|
36
|
+
query: Annotated[str | None, typer.Option("-q", "--query", help="正则关键词")] = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""列出所有报告。
|
|
39
|
+
|
|
40
|
+
从元数据服务获取报告列表,支持按报告子类型过滤,也支持通过正则表达式过滤报告编码或标题。
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
sub_types: 可选报告子类型列表(doc / ontology / dashboard)。
|
|
44
|
+
query: 可选正则关键词。
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
列出所有报告
|
|
48
|
+
>>> data-ops-cli report list
|
|
49
|
+
|
|
50
|
+
只列出看板类报告
|
|
51
|
+
>>> data-ops-cli report list -t dashboard
|
|
52
|
+
|
|
53
|
+
通过正则关键词过滤报告
|
|
54
|
+
>>> data-ops-cli report list -q "daily.*"
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
group_nodes = release_list_list(
|
|
58
|
+
MetaType.REPORT,
|
|
59
|
+
sub_types=[sub_type.value for sub_type in sub_types] if sub_types else None,
|
|
60
|
+
)
|
|
61
|
+
except DataOpsError as e:
|
|
62
|
+
typer.echo(f"错误: {e.message}")
|
|
63
|
+
raise typer.Exit(code=1)
|
|
64
|
+
|
|
65
|
+
if query:
|
|
66
|
+
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
67
|
+
|
|
68
|
+
print_list(
|
|
69
|
+
["code", "title", "subType"],
|
|
70
|
+
[[column.code, column.title, column.subType or "doc"] for column in group_nodes],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@report_typer.command("detail", rich_help_panel="报告查询")
|
|
75
|
+
def read_report(code: Annotated[str, typer.Argument(help="报告编码")]) -> None:
|
|
76
|
+
"""读取指定报告的完整内容。
|
|
77
|
+
|
|
78
|
+
通过报告编码从元数据服务获取报告详情,包括报告名称和正文内容。
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
code: 报告编码。
|
|
82
|
+
|
|
83
|
+
Examples:
|
|
84
|
+
读取报告详情
|
|
85
|
+
>>> data-ops-cli report detail daily_sales_2024
|
|
86
|
+
"""
|
|
87
|
+
try:
|
|
88
|
+
meta = service_get_report(code)
|
|
89
|
+
except DataOpsError as e:
|
|
90
|
+
typer.echo(f"错误: {e.message}")
|
|
91
|
+
raise typer.Exit(code=1) from e
|
|
92
|
+
if meta.data is None:
|
|
93
|
+
typer.echo(f"错误: 报告({code})不存在")
|
|
94
|
+
raise typer.Exit(code=1) from None
|
|
95
|
+
content = meta.data.content
|
|
96
|
+
print(f"文档({meta.name})\n\n{content}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@space_typer.command("tree", no_args_is_help=True)
|
|
100
|
+
def tree_report(
|
|
101
|
+
space_code: Annotated[str, typer.Argument(help="文档中心空间编码")],
|
|
102
|
+
query: Annotated[str | None, typer.Option("-q", "--query", help="表名关键字")] = None,
|
|
103
|
+
types: Annotated[
|
|
104
|
+
list[str] | None,
|
|
105
|
+
typer.Option("--type", "-t", help="类型过滤 (report/skill/workflow/data_table)"),
|
|
106
|
+
] = None,
|
|
107
|
+
) -> None:
|
|
108
|
+
"""展示文档中心树结构。
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
space_code: 文档中心空间编码。
|
|
112
|
+
query: 表名关键字。
|
|
113
|
+
types: 文档、多维表格、技能、工作流子类型列表。
|
|
114
|
+
"""
|
|
115
|
+
try:
|
|
116
|
+
tree = servive_tree_report(space_code)
|
|
117
|
+
except DataOpsError as e:
|
|
118
|
+
typer.echo(f"错误: {e.message}")
|
|
119
|
+
raise typer.Exit(code=1) from None
|
|
120
|
+
print_group_tree(tree, query, types=types)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@space_typer.command("list")
|
|
124
|
+
def list_report_space(
|
|
125
|
+
query: Annotated[str | None, typer.Option("-q", "--query", help="正则关键词")] = None,
|
|
126
|
+
):
|
|
127
|
+
try:
|
|
128
|
+
group_nodes = release_list_list("report_space")
|
|
129
|
+
except DataOpsError as e:
|
|
130
|
+
typer.echo(f"错误: {e.message}")
|
|
131
|
+
raise typer.Exit(code=1)
|
|
132
|
+
|
|
133
|
+
if query:
|
|
134
|
+
group_nodes = filter_nodes_by_pattern(group_nodes, query)
|
|
135
|
+
|
|
136
|
+
output = [["report", "默认空间", "禁止删除"]]
|
|
137
|
+
output.extend([column.code, column.title, column.remark or ""] for column in group_nodes)
|
|
138
|
+
|
|
139
|
+
print_list(
|
|
140
|
+
["space-code", "title", "remark"],
|
|
141
|
+
output,
|
|
142
|
+
)
|
|
@@ -14,6 +14,7 @@ import typer
|
|
|
14
14
|
from dataops_cli.cli.utils import paginate_with_line_numbers, print_list
|
|
15
15
|
from dataops_sdk.exceptions import DataOpsError
|
|
16
16
|
from dataops_sdk.schemas import MetaSkillFileSubType, MetaSkillSubType, MetaType
|
|
17
|
+
from dataops_sdk.schemas.enums import GroupNodeRefType
|
|
17
18
|
from dataops_sdk.services import (
|
|
18
19
|
SkillPackValidationError,
|
|
19
20
|
service_delete_skill,
|
|
@@ -122,17 +123,28 @@ def detail_cmd(
|
|
|
122
123
|
|
|
123
124
|
@skill_typer.command("upload", no_args_is_help=True)
|
|
124
125
|
def upload_cmd(
|
|
126
|
+
space_code: Annotated[
|
|
127
|
+
str, typer.Argument(help="空间编码 (通过 ``report sapce list`` 查看空间编码)")
|
|
128
|
+
],
|
|
125
129
|
file: Annotated[Path, typer.Argument(help="技能 ZIP 文件路径")],
|
|
126
130
|
dtype: Annotated[
|
|
127
131
|
MetaSkillSubType,
|
|
128
132
|
typer.Option("--type", help="技能子类型"),
|
|
129
133
|
],
|
|
134
|
+
ref_node_id: Annotated[
|
|
135
|
+
str | None, typer.Option("--ref-node-id", help="引用节点ID (通过 `report sapce tree` 查看)")
|
|
136
|
+
] = None,
|
|
137
|
+
ref_type: Annotated[
|
|
138
|
+
GroupNodeRefType,
|
|
139
|
+
typer.Option("--ref-type", help="引用节点类型 (放置在引用节点前、后还是内)"),
|
|
140
|
+
] = GroupNodeRefType.AFTER,
|
|
130
141
|
title: Annotated[str | None, typer.Option("--title", help="技能简体中文名称")] = None,
|
|
131
142
|
) -> None:
|
|
132
|
-
"""从 ZIP
|
|
143
|
+
"""从 ZIP 包上传技能到文档中心指定位置。
|
|
133
144
|
|
|
134
145
|
Examples:
|
|
135
|
-
|
|
146
|
+
把技能上传到指定空间的执行Node里面
|
|
147
|
+
>>> data-ops-cli skill import {space-code} my-skill.zip --type api --ref-node-id {node-id} --ref-type inner
|
|
136
148
|
"""
|
|
137
149
|
if not file.exists():
|
|
138
150
|
typer.echo(f"错误: 文件不存在 {file}")
|
|
@@ -143,6 +155,9 @@ def upload_cmd(
|
|
|
143
155
|
file_path=str(file),
|
|
144
156
|
sub_type=dtype,
|
|
145
157
|
title=title,
|
|
158
|
+
group_name=space_code,
|
|
159
|
+
ref_node_id=ref_node_id,
|
|
160
|
+
ref_type=ref_type,
|
|
146
161
|
)
|
|
147
162
|
except DataOpsError as e:
|
|
148
163
|
typer.echo(f"错误: {e.message}")
|