ap-client 0.6.1.dev4__tar.gz → 0.6.1.dev6__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.
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/PKG-INFO +3 -3
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/dataset_commands.py +2 -2
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/dataset_register.py +55 -1
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/dfs_commands.py +23 -1
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/irepo_sdk.py +15 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/pyproject.toml +3 -3
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/__init__.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/akpool_commands.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/api.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/cli.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/config.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/dataset_name.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/exporter.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/fs_commands.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/instance_commands.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/instance_options.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/managed_ak.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/manifest_view.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/ossutil_hash.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/ossutil_io.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/profile_commands.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/repo_read_guard.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/share_api.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/split_publish.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/tbb.py +0 -0
- {ap_client-0.6.1.dev4 → ap_client-0.6.1.dev6}/ap_client/waiter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ap-client
|
|
3
|
-
Version: 0.6.1.
|
|
3
|
+
Version: 0.6.1.dev6
|
|
4
4
|
Summary: Agent Platform API Client & CLI
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: irepo-artifact==0.2.2
|
|
@@ -10,9 +10,9 @@ Requires-Dist: rich>=13.0.0
|
|
|
10
10
|
Requires-Dist: typer>=0.9.0
|
|
11
11
|
Requires-Dist: websockets>=13.0
|
|
12
12
|
Provides-Extra: all
|
|
13
|
-
Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.
|
|
13
|
+
Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.dev6; extra == 'all'
|
|
14
14
|
Provides-Extra: dataset
|
|
15
|
-
Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.
|
|
15
|
+
Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.dev6; extra == 'dataset'
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
18
|
A lightweight Python SDK and command line interface for Agent Platform. It provides helpers for configuring API access and managing templates, datasets, jobs, and groups.
|
|
@@ -795,12 +795,12 @@ def _split_names(detail: dict) -> list[str]:
|
|
|
795
795
|
return names
|
|
796
796
|
|
|
797
797
|
|
|
798
|
-
def _dataset_repo() -> "Repo":
|
|
798
|
+
def _dataset_repo(*, request_timeout: float | None = None) -> "Repo":
|
|
799
799
|
"""dataset 写路径统一走 InstanceRepo SDK;未装 ``dataset`` extra 时退出 2。"""
|
|
800
800
|
from .irepo_sdk import SdkMissing, load_repo
|
|
801
801
|
|
|
802
802
|
try:
|
|
803
|
-
return load_repo()
|
|
803
|
+
return load_repo(request_timeout=request_timeout)
|
|
804
804
|
except SdkMissing as exc:
|
|
805
805
|
typer.echo(str(exc), err=True)
|
|
806
806
|
raise typer.Exit(2) from exc
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import math
|
|
7
|
+
import os
|
|
7
8
|
import sys
|
|
8
9
|
from typing import Any, List, Optional
|
|
9
10
|
from urllib.parse import quote
|
|
@@ -33,6 +34,42 @@ def _emit_preview_stderr(payload: dict, output_format: str) -> None:
|
|
|
33
34
|
typer.echo(json.dumps(payload, ensure_ascii=False, indent=2), err=True)
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
def _parse_request_timeout() -> float:
|
|
38
|
+
"""Read ``AP_REQUEST_TIMEOUT`` from the environment, falling back to 30 s.
|
|
39
|
+
|
|
40
|
+
Empty, missing, or non-numeric values all resolve to the default rather
|
|
41
|
+
than raising ``ValueError`` at import time (which would break ``ap --help``).
|
|
42
|
+
"""
|
|
43
|
+
raw = os.environ.get("AP_REQUEST_TIMEOUT", "").strip()
|
|
44
|
+
if not raw:
|
|
45
|
+
return 30.0
|
|
46
|
+
try:
|
|
47
|
+
value = float(raw)
|
|
48
|
+
except (TypeError, ValueError):
|
|
49
|
+
return 30.0
|
|
50
|
+
return value if math.isfinite(value) and value > 0 else 30.0
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _set_sdk_request_timeout(repo: Any, timeout: float) -> None:
|
|
54
|
+
"""Override the IR SDK per-request HTTP timeout on the shared Transport.
|
|
55
|
+
|
|
56
|
+
All sub-clients (``datasets``, ``versions``, ``instances``) share
|
|
57
|
+
``repo.transport``, so a single assignment covers every control-plane
|
|
58
|
+
call the register command makes (preview and submission alike).
|
|
59
|
+
Falls back to setting the attribute on each sub-client's ``_t`` when the
|
|
60
|
+
``transport`` attribute is absent (older SDK shapes).
|
|
61
|
+
"""
|
|
62
|
+
transport = getattr(repo, "transport", None)
|
|
63
|
+
if transport is not None and hasattr(transport, "timeout"):
|
|
64
|
+
transport.timeout = timeout
|
|
65
|
+
return
|
|
66
|
+
for name in ("datasets", "versions", "instances", "images"):
|
|
67
|
+
client = getattr(repo, name, None)
|
|
68
|
+
t = getattr(client, "_t", None)
|
|
69
|
+
if t is not None and hasattr(t, "timeout"):
|
|
70
|
+
t.timeout = timeout
|
|
71
|
+
|
|
72
|
+
|
|
36
73
|
def _confirm(dataset: str, *, yes: bool) -> None:
|
|
37
74
|
if yes:
|
|
38
75
|
return
|
|
@@ -220,6 +257,13 @@ def dataset_register(
|
|
|
220
257
|
yes: bool = typer.Option(False, "--yes", "-y", help="Skip the registration confirmation"),
|
|
221
258
|
wait: bool = typer.Option(False, "--wait", help="Wait for the ingest task to finish"),
|
|
222
259
|
timeout: float = typer.Option(1800.0, "--timeout", help="Local wait timeout in seconds"),
|
|
260
|
+
request_timeout: float = typer.Option(
|
|
261
|
+
_parse_request_timeout(),
|
|
262
|
+
"--request-timeout",
|
|
263
|
+
help="Per-request HTTP timeout in seconds for control-plane calls "
|
|
264
|
+
"(env: AP_REQUEST_TIMEOUT, default: 30). "
|
|
265
|
+
"Increase for datasets with many objects where the preview scan takes longer.",
|
|
266
|
+
),
|
|
223
267
|
output_format: Optional[str] = typer.Option(None, "--format", help=datasets._FORMAT_HELP),
|
|
224
268
|
owner: Optional[str] = typer.Option(
|
|
225
269
|
None, "--owner", help="Ensure ownership before ingest; the only supported value is @me"
|
|
@@ -273,7 +317,17 @@ def dataset_register(
|
|
|
273
317
|
)
|
|
274
318
|
|
|
275
319
|
env = datasets._environment(environment)
|
|
276
|
-
repo = datasets._dataset_repo()
|
|
320
|
+
repo = datasets._dataset_repo(request_timeout=request_timeout)
|
|
321
|
+
# Override the IR SDK per-request HTTP timeout. All sub-clients
|
|
322
|
+
# (datasets, versions, instances) share repo.transport, so one
|
|
323
|
+
# assignment covers preview and submission alike.
|
|
324
|
+
if not math.isfinite(request_timeout) or request_timeout <= 0:
|
|
325
|
+
raise datasets._fail(
|
|
326
|
+
"--request-timeout must be a positive finite number",
|
|
327
|
+
"Pass a positive number of seconds",
|
|
328
|
+
exit_code=2,
|
|
329
|
+
)
|
|
330
|
+
_set_sdk_request_timeout(repo, request_timeout)
|
|
277
331
|
datasets._check_storage_side(repo, env)
|
|
278
332
|
ingest = getattr(getattr(repo, "versions", None), "ingest", None)
|
|
279
333
|
if not callable(ingest):
|
|
@@ -32,12 +32,34 @@ def register(app: typer.Typer) -> None:
|
|
|
32
32
|
app.add_typer(dfs_app, name="dfs")
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
_DFS_ACCESS_DENIED_CODES = frozenset({94016, 94018, 10002})
|
|
36
|
+
|
|
37
|
+
|
|
35
38
|
def _files() -> OssFiles:
|
|
36
39
|
from .cli import app
|
|
37
40
|
from .irepo_sdk import load_ossutil_repo
|
|
38
41
|
|
|
39
42
|
app.pretty_exceptions_show_locals = False
|
|
40
|
-
|
|
43
|
+
try:
|
|
44
|
+
repo, config = load_ossutil_repo()
|
|
45
|
+
except Exception as exc:
|
|
46
|
+
biz_code = getattr(exc, "biz_code", None)
|
|
47
|
+
status = getattr(exc, "status", None) or getattr(exc, "status_code", None)
|
|
48
|
+
msg = str(exc).lower()
|
|
49
|
+
is_forbidden = (
|
|
50
|
+
biz_code in _DFS_ACCESS_DENIED_CODES
|
|
51
|
+
or status == 403
|
|
52
|
+
or "forbidden" in msg
|
|
53
|
+
or "permission" in msg
|
|
54
|
+
or "not allowed" in msg
|
|
55
|
+
)
|
|
56
|
+
if is_forbidden:
|
|
57
|
+
typer.echo(
|
|
58
|
+
"ap dfs is currently available to platform admins and allow-listed users only.",
|
|
59
|
+
err=True,
|
|
60
|
+
)
|
|
61
|
+
raise typer.Exit(1) from exc
|
|
62
|
+
raise
|
|
41
63
|
return OssFiles(repo, OssBinding.from_payload(config))
|
|
42
64
|
|
|
43
65
|
|
|
@@ -884,6 +884,7 @@ def load_repo(
|
|
|
884
884
|
cluster: str | None = None,
|
|
885
885
|
storage_env: str | None = None,
|
|
886
886
|
environment: str | None = None,
|
|
887
|
+
request_timeout: float | None = None,
|
|
887
888
|
) -> "Repo":
|
|
888
889
|
"""按 AP ``Config`` 构造 ``instance_repo.Repo``。
|
|
889
890
|
|
|
@@ -942,7 +943,21 @@ def load_repo(
|
|
|
942
943
|
if cfg.verbose and "transport" in supported:
|
|
943
944
|
transport = _verbose_sdk_transport(cfg, api_env)
|
|
944
945
|
if transport is not None:
|
|
946
|
+
if request_timeout is not None:
|
|
947
|
+
transport.timeout = request_timeout
|
|
945
948
|
kwargs["transport"] = transport
|
|
949
|
+
elif request_timeout is not None and "transport" in supported:
|
|
950
|
+
# Inject a pre-configured Transport so the custom timeout is effective
|
|
951
|
+
# from the very first HTTP call inside Repo.__init__ / _bind_dataset_profile.
|
|
952
|
+
try:
|
|
953
|
+
from instance_repo.transport import Transport as _Transport
|
|
954
|
+
except ImportError:
|
|
955
|
+
_Transport = None
|
|
956
|
+
if _Transport is not None:
|
|
957
|
+
kwargs["transport"] = _Transport(
|
|
958
|
+
cfg.base_url, cfg.token_key or "", env=api_env,
|
|
959
|
+
timeout=request_timeout,
|
|
960
|
+
)
|
|
946
961
|
|
|
947
962
|
if "api_base" not in supported or "cluster" not in supported:
|
|
948
963
|
# 0.8.x 兼容路径:构造参数缺位,只能退回环境变量契约。
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ap-client"
|
|
7
|
-
version = "0.6.1.
|
|
7
|
+
version = "0.6.1.dev6"
|
|
8
8
|
description = "Agent Platform API Client & CLI"
|
|
9
9
|
readme = { text = "A lightweight Python SDK and command line interface for Agent Platform. It provides helpers for configuring API access and managing templates, datasets, jobs, and groups.", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -19,10 +19,10 @@ dependencies = [
|
|
|
19
19
|
|
|
20
20
|
[project.optional-dependencies]
|
|
21
21
|
dataset = [
|
|
22
|
-
"instance-repo[oss]>=1.4.0.
|
|
22
|
+
"instance-repo[oss]>=1.4.0.dev6,<2.0.0",
|
|
23
23
|
]
|
|
24
24
|
all = [
|
|
25
|
-
"instance-repo[oss]>=1.4.0.
|
|
25
|
+
"instance-repo[oss]>=1.4.0.dev6,<2.0.0",
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
[project.scripts]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|