instance-repo 1.3.2.dev0__py3-none-any.whl → 1.3.2.dev1__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.
instance_repo/__init__.py CHANGED
@@ -18,7 +18,7 @@ from .errors import (
18
18
  TransportError,
19
19
  )
20
20
 
21
- __version__ = "1.3.2.dev0"
21
+ __version__ = "1.3.2.dev1"
22
22
 
23
23
  __all__ = [
24
24
  "Repo", "load_instances",
@@ -261,29 +261,26 @@ class SplitsClient:
261
261
  page: int, page_size: int) -> PagedResult:
262
262
  """OSS 回退的 splits.list — 处理 version_scope 和 status 过滤。
263
263
 
264
- version_scope="unversioned" → OSS 回退天然有版本结构,返回空。
265
- version_scope="exact" → 只返回精确匹配的 version。
266
- version_scope="all"(或空)+ version 非空 → 精确匹配 version。
264
+ 注意:回退场景(dataset 未注册)下 ``version_scope`` 是 MongoDB 语义,
265
+ OSS 探测无从区分 versioned/unversioned——**忽略 scope 并返回全部探测结果**
266
+ (G4:否则 ap CLI 无 --version 的 split list 恒空)。``version`` 非空时
267
+ 仍精确匹配该 version。
267
268
  """
268
269
  from ..store.oss_discovery import (
269
270
  parse_dataset_level, build_synthetic_split,
270
- _in_memory_paged, _empty_paged_result, _warn_if_truncated,
271
+ _in_memory_paged, _warn_if_truncated,
271
272
  )
272
- if (version_scope or "").strip() == "unversioned":
273
- return _empty_paged_result(int(page), int(page_size))
274
273
  info = parse_dataset_level(
275
274
  self._content, dataset, oss_prefix=self._oss_prefix)
276
275
  _warn_if_truncated(info, dataset, 500)
277
276
  splits: list[DatasetSplit] = []
278
277
  for v in info.versions:
279
- if version and (version_scope or "all") != "all" and v.version != version:
280
- continue
281
- elif version and v.version != version:
278
+ if version and v.version != version:
282
279
  continue
283
280
  if v.has_default_instances:
284
281
  splits.append(build_synthetic_split(
285
282
  dataset, v.version, "default",
286
- instance_count=v.instance_count))
283
+ instance_count=v.default_instance_count))
287
284
  for s in v.splits:
288
285
  splits.append(build_synthetic_split(
289
286
  dataset, v.version, s))
@@ -306,7 +303,7 @@ class SplitsClient:
306
303
  if split_name == "default" and v.has_default_instances:
307
304
  return build_synthetic_split(
308
305
  dataset, v.version, "default",
309
- instance_count=v.instance_count)
306
+ instance_count=v.default_instance_count)
310
307
  if split_name in v.splits:
311
308
  return build_synthetic_split(
312
309
  dataset, v.version, split_name)
@@ -235,11 +235,15 @@ class VersionsClient:
235
235
  def list_paged(self, dataset: str, *, status: str | None = None,
236
236
  environment: str | None = None,
237
237
  metadata_model: str | None = None,
238
- page: int = 1, page_size: int = 20) -> "PagedResult":
238
+ page: int = 1, page_size: int = 20,
239
+ fallback_to_oss: bool = True) -> "PagedResult":
239
240
  """版本分页列表(单页,``GET /datasets/versions``)。
240
241
 
241
242
  服务端参数集仅 status + environment/metadata_model + 分页(**无 q 模糊
242
243
  搜索**——找数据集用 datasets.list_paged(q=),两段式检索)。
244
+
245
+ ``fallback_to_oss``: dataset 未注册(92001)时自动回退到 OSS 目录探测
246
+ (与 :meth:`list` 一致),在内存中按 status 过滤 + 分页。
243
247
  """
244
248
  from ..models import PagedResult
245
249
  if not (dataset or "").strip():
@@ -254,7 +258,14 @@ class VersionsClient:
254
258
  q += f"&status={quote(s, safe='')}"
255
259
  q += (f"&page={int(page)}&page_size={int(page_size)}"
256
260
  f"{self._version_extra_q(environment, metadata_model)}")
257
- data, pagination = self._t.request_with_meta("GET", f"{self._BASE}?{q}")
261
+ try:
262
+ data, pagination = self._t.request_with_meta("GET", f"{self._BASE}?{q}")
263
+ except TransportError as e:
264
+ if (e.biz_code == 92001 and fallback_to_oss
265
+ and self._content is not None):
266
+ return self._discover_versions_paged(
267
+ dataset, status, int(page), int(page_size))
268
+ raise
258
269
  rows = data.get("versions", data) if isinstance(data, dict) else data
259
270
  rows = rows if isinstance(rows, list) else []
260
271
  items = [DatasetVersion(**_pick(r)) for r in rows if isinstance(r, dict)]
@@ -891,6 +902,15 @@ class VersionsClient:
891
902
  raise DatasetNotFound(f"dataset {dataset!r} not found in OSS")
892
903
  return [build_synthetic_version(dataset, v) for v in info.versions]
893
904
 
905
+ def _discover_versions_paged(self, dataset: str, status: str | None,
906
+ page: int, page_size: int):
907
+ """OSS 回退的 list_paged:全量探测后按 status 过滤 + 内存分页。"""
908
+ from ..store.oss_discovery import _in_memory_paged
909
+ items = self._discover_versions(dataset)
910
+ if (status or "").strip():
911
+ items = [v for v in items if v.status == status.strip()]
912
+ return _in_memory_paged(items, int(page), int(page_size))
913
+
894
914
  def _discover_version(self, dataset: str, version: str):
895
915
  from ..store.oss_discovery import (
896
916
  parse_dataset_level, build_synthetic_version, _warn_if_truncated)
instance_repo/models.py CHANGED
@@ -21,7 +21,9 @@ RUN_TYPE_VALUES = ("train", "eval")
21
21
  STORAGE_TYPE_VALUES = ("oss",)
22
22
  # permission 是签发 OSS 凭据时的**权限封顶**(apiserver credential_handler 的 permission
23
23
  # 字段):只能把本次令牌收窄到不高于调用方真实角色,绝不提权。ACR 分支不支持该字段。
24
- PERMISSION_VALUES = ("admin", "writer", "reader")
24
+ # "list" 是 list-only 模式(OSS 回退发现专用):仅授 ListObjects + GetBucketInfo,
25
+ # 跳过 DatasetRBAC 检查(未注册 dataset 无 RBAC 记录),无任何对象级读写动作。
26
+ PERMISSION_VALUES = ("admin", "writer", "reader", "list")
25
27
 
26
28
 
27
29
  def canonical_json(obj: Any) -> str:
@@ -59,6 +59,8 @@ class OssVersionInfo:
59
59
  splits: list[str]
60
60
  has_default_instances: bool
61
61
  instance_count: int
62
+ # default split(3 层布局)的直接 .json 数,与 instance_count(含命名 split)区分
63
+ default_instance_count: int = 0
62
64
 
63
65
 
64
66
  @dataclass
@@ -279,9 +281,11 @@ def parse_dataset_level(
279
281
  version_dir, permission="list")
280
282
  v_json_keys = _direct_json_keys(v_all_keys, version_dir)
281
283
  has_default_instances = len(v_json_keys) > 0
284
+ default_instance_count = len(v_json_keys)
282
285
  instance_count = len(v_json_keys)
283
286
  except Exception: # noqa: BLE001
284
287
  has_default_instances = False
288
+ default_instance_count = 0
285
289
  instance_count = 0
286
290
 
287
291
  # Count instances in each named split directory.
@@ -303,6 +307,7 @@ def parse_dataset_level(
303
307
  splits=splits,
304
308
  has_default_instances=has_default_instances,
305
309
  instance_count=instance_count,
310
+ default_instance_count=default_instance_count,
306
311
  ))
307
312
 
308
313
  return OssDatasetLevelInfo(
@@ -528,12 +533,15 @@ def build_synthetic_instance(
528
533
  key = P.metadata_key(
529
534
  dataset, version, instance_id, split, prefix=oss_prefix)
530
535
 
536
+ # 存在性判定用 LIST(permission="list" 仅需 ListObjects)而非 HEAD——
537
+ # list-only STS 无 oss:GetObject,object_exists 的 HEAD 会在 STS 签发或
538
+ # OSS 侧被拒,导致已存在的实例恒被误判为不存在。
531
539
  try:
532
- exists = content_store.object_exists(key)
540
+ keys = content_store.list_objects(key, permission="list")
533
541
  except Exception: # noqa: BLE001
534
542
  return None
535
543
 
536
- if not exists:
544
+ if key not in keys:
537
545
  return None
538
546
 
539
547
  inst = DatasetInstance(
@@ -333,11 +333,13 @@ class Transport:
333
333
  降到 ~1 次。dataset_id / dataset_name 至少传一个(细粒度授权场景),二者可并存,
334
334
  服务端校验一致性。
335
335
 
336
- ``permission``(可选,admin/writer/reader)是**权限封顶**:apiserver 取
336
+ ``permission``(可选,admin/writer/reader/list)是**权限封顶**:apiserver 取
337
337
  ``min(调用方真实角色, permission)``,**只能收窄不能提权**——传 admin 不会把
338
338
  reader 变成 admin。用途是最小权限原则(只读任务显式请求 reader,即便自己是
339
339
  admin),以及避免把可写令牌交给下游只读组件。admin 与 writer 在 STS 策略层等价,
340
- 真正有区别的是 reader(只给 GetObject)。ACR 分支不支持该字段(镜像令牌是实例级的)。
340
+ 真正有区别的是 reader(只给 GetObject)。``list`` 是 list-only 模式(OSS 回退
341
+ 发现专用):仅授 ListObjects + GetBucketInfo,跳过 DatasetRBAC 检查,用于未
342
+ 注册 dataset 的目录结构探测。ACR 分支不支持该字段(镜像令牌是实例级的)。
341
343
  """
342
344
  # 空串与 None 一律视为"不封顶"(与 Go 的 Permission == "" 语义对齐)。
343
345
  if permission and permission not in PERMISSION_VALUES:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.3.2.dev0
3
+ Version: 1.3.2.dev1
4
4
  Summary: InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,4 +1,4 @@
1
- instance_repo/__init__.py,sha256=gbklD8A9cq8YL2H0n3_MB0XyZJ5FSrIC7c6mfbNAYA0,1422
1
+ instance_repo/__init__.py,sha256=8ybL0ZVRO_IDt_dQeYOOUIvnJMx0OEPjNrT0Z_v38n4,1422
2
2
  instance_repo/_routing.py,sha256=XbdKPF-Zh2sEkr4UyLC9HuiRcTLP-ssvhp6SCDC98YM,8326
3
3
  instance_repo/_site_defaults.py,sha256=ck7aHHTup8ibBo0l5MSR03XpTtxJ11hYo7oM2DzWs4A,2383
4
4
  instance_repo/artifacts.py,sha256=OOcSI1ehB_dw1ZNScjyhzghPqOdL534kQp_iI2Hz7IU,10659
@@ -12,13 +12,13 @@ instance_repo/errors.py,sha256=2W6VS1fpkfkBsKPaNKCq1iJenAg60_G2BPjzWt0Ta3Y,5621
12
12
  instance_repo/image.py,sha256=tUTRyeNNiAzd2ULbmjhNj436558j_IPwpTDXTld1KVY,3822
13
13
  instance_repo/layout.py,sha256=8o4dVD4-76hTAvRSp7UZFNvXG5AxzEqMCVgrVXNfdok,11943
14
14
  instance_repo/loader.py,sha256=lWjhw0MjEIIxbZ5w6cjyaDIWkNVFDhjjNdu1lc5zRuo,474
15
- instance_repo/models.py,sha256=bPKh3EEgpF-mqZruuvK5fIT9qWU5E7XxrePY8aKAgL4,35902
15
+ instance_repo/models.py,sha256=OHBslrA2c5-c-QR_-008hk1ryxQKezNlCZG7JWt_f1E,36111
16
16
  instance_repo/paths.py,sha256=EL0d613T0mnabiYCtZQBC50rZT3mWKUq-3TepPbTRec,8438
17
17
  instance_repo/release.py,sha256=Up96Qeh2GRH26BSAHVEjDFQnFCaEA-vIvSme3a8FQFo,13882
18
18
  instance_repo/repo.py,sha256=5D7jYLeaDSZLKnf548YlfXT9tUPNgdcXT2j31wzShpA,40305
19
19
  instance_repo/retry.py,sha256=8y-AX9qmnLqGwqRzVJ5PKqZt2fWyqUL2t2P0suSBAA4,3438
20
20
  instance_repo/tasktoml.py,sha256=b-tWfNiOHN9D-ixCbPpCLnZaaU9Q6LRGG0Wl4YN8r10,5152
21
- instance_repo/transport.py,sha256=Hhw89xxQ7YCJaxmr35he0t9IALeYGvIqcx1jUwzKSzo,21420
21
+ instance_repo/transport.py,sha256=B5ZxixaHuqyi9BzjTRCKlBdkrrG0Dft6O2FhL7inceY,21616
22
22
  instance_repo/validate.py,sha256=NMR-vFBIU_FQ0WKdBZuQ-ua4jtkAzvWwEjnAHyAFwDs,11877
23
23
  instance_repo/clients/__init__.py,sha256=5V7Pe0b6nnMiwIhACA4ctQowovrL4iHTiHKKcjmsBQo,488
24
24
  instance_repo/clients/benchmarks.py,sha256=RzHY8VzDP1o2jT4M8gxxbcr3amuNr4mlSblZhhJqG_w,2778
@@ -28,17 +28,17 @@ instance_repo/clients/images.py,sha256=8i0FXxAAL2mOUUTrVgDdWSYM2imJ5nOEXzpVRBa-G
28
28
  instance_repo/clients/instances.py,sha256=IOAKl3MAlW3UcftX8b5cGIEdC5_1qfouaVSE_0-OAxE,58125
29
29
  instance_repo/clients/reports.py,sha256=4Z8bpcSi-mmfkQLKpMklelLI4mgHcnjfb0725bE2nkI,3001
30
30
  instance_repo/clients/scaffold.py,sha256=VLicNFnqKi2iYB-gjOkQ9wa1unNOJXO7UxBZlz7El5A,4998
31
- instance_repo/clients/splits.py,sha256=h4WBveww1z-a7A8W3FJa6CBGfuH2M5eLVmviu3okbsU,27366
32
- instance_repo/clients/versions.py,sha256=5aJOvONQyn_eP0D2xrEv0p4IgFSjJqGP_2SjPTIveF0,51631
31
+ instance_repo/clients/splits.py,sha256=9hUZAiLCv0gZpxbEPvxtsJZ0qeGxSxaYl21ARF3sl58,27211
32
+ instance_repo/clients/versions.py,sha256=jeLwV0K5h4lpeeEMPQMnv-BpzfRcm0jiqcGIa0Nl2RI,52658
33
33
  instance_repo/clients/workflows.py,sha256=6ftl1tuyEGx8BtMLSjfExP9_VcQhK4veo7ex1jDOdlc,3686
34
34
  instance_repo/store/__init__.py,sha256=fGwePNjKuojqx1yagSaY-svONE5pjaEz2BZmG0ISUZ0,674
35
35
  instance_repo/store/acr.py,sha256=OD7LH3GZY4HrrbEht86Mf3NfW_lh-8MhCTOGyX6gLT4,19468
36
36
  instance_repo/store/base.py,sha256=7feHdDXDvSkq60wXYvF6p8TK9KRj7YTLlESdgZ5MQHo,2622
37
37
  instance_repo/store/oss.py,sha256=4jHGPO7ceTx7xC6MqzNK26eHRTmvIe_rLrV36oPDfkk,30718
38
- instance_repo/store/oss_discovery.py,sha256=S9V1FhzxALkSVBbvS5eXu2HbjmyHHSeW-1X8Xr4QrWI,19472
38
+ instance_repo/store/oss_discovery.py,sha256=2nwJwtdWO6Pa5FK0MfOFZlFhSav8jzFrh7uNHA_oLqg,20032
39
39
  instance_repo/store/registry.py,sha256=1R2GqXsuDZ8wc3IGpncF9yL6IHk-FeiwUlZN7v2ndSc,10837
40
- instance_repo-1.3.2.dev0.dist-info/METADATA,sha256=c0EhI853YMKbYrN6Qh-zdHsie_R-PC6feSmw5kRLpyQ,14227
41
- instance_repo-1.3.2.dev0.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
42
- instance_repo-1.3.2.dev0.dist-info/entry_points.txt,sha256=tn6jgwYChSx7eAqw9YNed_JFYYgoRtE7WkFn8xqa8Rw,53
43
- instance_repo-1.3.2.dev0.dist-info/top_level.txt,sha256=mblK0Bkwwp6jCZioS6q3sSuFFs8NR9DKTJ0DJpIRDmY,14
44
- instance_repo-1.3.2.dev0.dist-info/RECORD,,
40
+ instance_repo-1.3.2.dev1.dist-info/METADATA,sha256=gFmfOf-KacPoB2hUdJeAqRfvNOfR6T4Mu61IEMsNf7s,14227
41
+ instance_repo-1.3.2.dev1.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
42
+ instance_repo-1.3.2.dev1.dist-info/entry_points.txt,sha256=tn6jgwYChSx7eAqw9YNed_JFYYgoRtE7WkFn8xqa8Rw,53
43
+ instance_repo-1.3.2.dev1.dist-info/top_level.txt,sha256=mblK0Bkwwp6jCZioS6q3sSuFFs8NR9DKTJ0DJpIRDmY,14
44
+ instance_repo-1.3.2.dev1.dist-info/RECORD,,