instance-repo 1.3.5.dev1__tar.gz → 1.3.5.dev2__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.
Files changed (49) hide show
  1. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/PKG-INFO +1 -1
  2. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/__init__.py +1 -1
  3. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/instances.py +91 -6
  4. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/PKG-INFO +1 -1
  5. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/pyproject.toml +1 -1
  6. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/README.md +0 -0
  7. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/_routing.py +0 -0
  8. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/_site_defaults.py +0 -0
  9. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/artifacts.py +0 -0
  10. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/bootstrap.py +0 -0
  11. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/cache.py +0 -0
  12. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/cli.py +0 -0
  13. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/__init__.py +0 -0
  14. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/benchmarks.py +0 -0
  15. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/config.py +0 -0
  16. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/datasets.py +0 -0
  17. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/images.py +0 -0
  18. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/reports.py +0 -0
  19. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/scaffold.py +0 -0
  20. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/splits.py +0 -0
  21. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/versions.py +0 -0
  22. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/clients/workflows.py +0 -0
  23. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/concurrency.py +0 -0
  24. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/content.py +0 -0
  25. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/endpoints.py +0 -0
  26. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/errors.py +0 -0
  27. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/image.py +0 -0
  28. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/layout.py +0 -0
  29. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/loader.py +0 -0
  30. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/models.py +0 -0
  31. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/paths.py +0 -0
  32. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/release.py +0 -0
  33. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/repo.py +0 -0
  34. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/retry.py +0 -0
  35. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/__init__.py +0 -0
  36. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/acr.py +0 -0
  37. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/base.py +0 -0
  38. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/oss.py +0 -0
  39. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/oss_discovery.py +0 -0
  40. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/store/registry.py +0 -0
  41. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/tasktoml.py +0 -0
  42. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/transport.py +0 -0
  43. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo/validate.py +0 -0
  44. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/SOURCES.txt +0 -0
  45. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/dependency_links.txt +0 -0
  46. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/entry_points.txt +0 -0
  47. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/requires.txt +0 -0
  48. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/instance_repo.egg-info/top_level.txt +0 -0
  49. {instance_repo-1.3.5.dev1 → instance_repo-1.3.5.dev2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.3.5.dev1
3
+ Version: 1.3.5.dev2
4
4
  Summary: InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -20,7 +20,7 @@ from .errors import (
20
20
  TransportError,
21
21
  )
22
22
 
23
- __version__ = "1.3.5.dev1"
23
+ __version__ = "1.3.5.dev2"
24
24
 
25
25
  __all__ = [
26
26
  "Repo", "load_instances",
@@ -1175,6 +1175,7 @@ class InstancesClient:
1175
1175
  validate_instance_id(instance_id, source="pull()")
1176
1176
  expected = None
1177
1177
  fmt = None # None = 未确定,需要探测
1178
+ dir_manifest = None # manifest 中的 directory 条目(如有)
1178
1179
  lay = self._layout()
1179
1180
  # 已下载的元数据字节(探测阶段下载一次,swe/custom 路径复用,避免二次网络往返)。
1180
1181
  meta_bytes: bytes | None = None
@@ -1192,15 +1193,27 @@ class InstancesClient:
1192
1193
  raise
1193
1194
  if meta is not None and meta.manifest:
1194
1195
  has_tgz = False
1196
+ has_dir = False
1195
1197
  for m in meta.manifest:
1196
1198
  if m.content_format == "tgz":
1197
1199
  expected = m.content_digest
1198
1200
  has_tgz = True
1199
1201
  break
1202
+ if m.content_type == "directory":
1203
+ has_dir = True
1204
+ dir_manifest = m
1200
1205
  if has_tgz:
1201
1206
  fmt = "harbor"
1207
+ elif has_dir:
1208
+ # manifest 同时有 json 和 directory 条目 → custom 格式
1209
+ # (directory 条目指向 assets 目录,需逐文件下载)。
1210
+ fmt = "custom"
1211
+ for m in meta.manifest:
1212
+ if m.content_format == "json":
1213
+ expected = m.content_digest
1214
+ break
1202
1215
  else:
1203
- # manifest 有 json entry 但无 tgz → swe 或 custom(需进一步探测)。
1216
+ # manifest 有 json entry 但无 tgz 也无 directory → swe 或 custom(需进一步探测)。
1204
1217
  # custom 推的 manifest 由 ingest 扫描生成,与 swe 同形态;
1205
1218
  # 唯一区分手段是读 metadata JSON 检查 metadata_model 字段。
1206
1219
  for m in meta.manifest:
@@ -1289,6 +1302,39 @@ class InstancesClient:
1289
1302
  if isinstance(meta_doc, dict) and isinstance(
1290
1303
  meta_doc.get("assets"), list):
1291
1304
  asset_rels = [str(x) for x in meta_doc["assets"]]
1305
+ # manifest 有 directory 条目但 JSON 无 assets 字段时,
1306
+ # 用控制面 list_objects API 递归枚举目录下的全部文件作为 asset_rels。
1307
+ if asset_rels is None and dir_manifest is not None:
1308
+ try:
1309
+ env = getattr(self._p, "dataset_environment", None)
1310
+ mm = getattr(self._p, "metadata_model", None)
1311
+ # 递归列举:从根开始,遇到子目录继续深入
1312
+ asset_rels = []
1313
+ stack: list[str | None] = [None] # None = 实例资产根
1314
+ # list_objects 返回的 f.path 包含完整前缀
1315
+ # (如 test-assets/105-creep-forecast/solution/solve.py),
1316
+ # 需要去掉 {split}-assets/{instance_id}/ 前缀得到相对路径。
1317
+ split_str = (split or "default").strip()
1318
+ assets_root = f"{split_str}-assets/{instance_id.strip()}/"
1319
+ while stack:
1320
+ cur_path = stack.pop()
1321
+ objs = self.list_objects(
1322
+ dataset, instance_id, split=split,
1323
+ version=version, path=cur_path,
1324
+ environment=env, metadata_model=mm)
1325
+ for f in objs.files:
1326
+ rel = f.path
1327
+ if rel.startswith(assets_root):
1328
+ rel = rel[len(assets_root):]
1329
+ asset_rels.append(rel)
1330
+ for d in objs.directories:
1331
+ # directory path 也含完整前缀,去掉后入栈
1332
+ d_path = d.path.rstrip("/")
1333
+ if d_path.startswith(assets_root):
1334
+ d_path = d_path[len(assets_root):]
1335
+ stack.append(d_path)
1336
+ except Exception: # noqa: BLE001
1337
+ asset_rels = None # 枚举失败回退到 OSS LIST
1292
1338
  self._download_custom_assets(
1293
1339
  dataset, instance_id, version, split, dest_dir, lay, sts_prefix,
1294
1340
  asset_rels=asset_rels, path=path)
@@ -1300,11 +1346,50 @@ class InstancesClient:
1300
1346
  # 已在探测阶段下载,直接写入本地。
1301
1347
  dest.parent.mkdir(parents=True, exist_ok=True)
1302
1348
  dest.write_bytes(meta_bytes)
1303
- return dest
1304
- return self._content.get_object(
1305
- idx_key, dest, expected_digest=expected,
1306
- sts_prefix=sts_prefix,
1307
- dataset=dataset)
1349
+ else:
1350
+ self._content.get_object(
1351
+ idx_key, dest, expected_digest=expected,
1352
+ sts_prefix=sts_prefix,
1353
+ dataset=dataset)
1354
+ # swe 格式也可能附带 assets 目录(JSON + directory 混合格式)。
1355
+ # 尝试用 list_objects 检查并下载目录内容。
1356
+ try:
1357
+ objs = self.list_objects(
1358
+ dataset, instance_id, split=split,
1359
+ version=version,
1360
+ environment=getattr(self._p, "dataset_environment", None),
1361
+ metadata_model=getattr(self._p, "metadata_model", None))
1362
+ if objs.files or objs.directories:
1363
+ # 有 assets 内容 → 递归枚举并下载
1364
+ asset_rels: list[str] = []
1365
+ stack: list[str | None] = [None]
1366
+ split_str = (split or "default").strip()
1367
+ assets_root = f"{split_str}-assets/{instance_id.strip()}/"
1368
+ while stack:
1369
+ cur = stack.pop()
1370
+ page = self.list_objects(
1371
+ dataset, instance_id, split=split,
1372
+ version=version, path=cur,
1373
+ environment=getattr(self._p, "dataset_environment", None),
1374
+ metadata_model=getattr(self._p, "metadata_model", None))
1375
+ for f in page.files:
1376
+ rel = f.path
1377
+ if rel.startswith(assets_root):
1378
+ rel = rel[len(assets_root):]
1379
+ asset_rels.append(rel)
1380
+ for d in page.directories:
1381
+ d_path = d.path.rstrip("/")
1382
+ if d_path.startswith(assets_root):
1383
+ d_path = d_path[len(assets_root):]
1384
+ stack.append(d_path)
1385
+ if asset_rels:
1386
+ self._download_custom_assets(
1387
+ dataset, instance_id, version, split,
1388
+ dest_dir, lay, sts_prefix,
1389
+ asset_rels=asset_rels, path=path)
1390
+ except Exception: # noqa: BLE001
1391
+ pass # assets 目录不存在或枚举失败 → 仅保留 JSON
1392
+ return dest
1308
1393
 
1309
1394
  # harbor:下载 content.tgz
1310
1395
  dest = Path(dest_dir) / instance_id / "content.tgz"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.3.5.dev1
3
+ Version: 1.3.5.dev2
4
4
  Summary: InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "instance-repo"
7
- version = "1.3.5.dev1"
7
+ version = "1.3.5.dev2"
8
8
  description = "InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)"
9
9
  requires-python = ">=3.10"
10
10
  readme = "README.md"