instance-repo 1.4.0.dev3__tar.gz → 1.4.0.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.
Files changed (49) hide show
  1. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/PKG-INFO +1 -1
  2. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/__init__.py +1 -1
  3. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/instances.py +51 -12
  4. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/errors.py +9 -0
  5. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/PKG-INFO +1 -1
  6. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/pyproject.toml +1 -1
  7. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/README.md +0 -0
  8. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/_routing.py +0 -0
  9. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/_site_defaults.py +0 -0
  10. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/artifacts.py +0 -0
  11. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/bootstrap.py +0 -0
  12. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/cache.py +0 -0
  13. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/cli.py +0 -0
  14. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/__init__.py +0 -0
  15. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/benchmarks.py +0 -0
  16. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/config.py +0 -0
  17. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/datasets.py +0 -0
  18. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/images.py +0 -0
  19. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/reports.py +0 -0
  20. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/scaffold.py +0 -0
  21. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/splits.py +0 -0
  22. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/versions.py +0 -0
  23. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/clients/workflows.py +0 -0
  24. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/concurrency.py +0 -0
  25. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/content.py +0 -0
  26. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/endpoints.py +0 -0
  27. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/image.py +0 -0
  28. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/layout.py +0 -0
  29. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/loader.py +0 -0
  30. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/models.py +0 -0
  31. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/paths.py +0 -0
  32. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/release.py +0 -0
  33. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/repo.py +0 -0
  34. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/retry.py +0 -0
  35. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/__init__.py +0 -0
  36. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/acr.py +0 -0
  37. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/base.py +0 -0
  38. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/oss.py +0 -0
  39. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/oss_discovery.py +0 -0
  40. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/store/registry.py +0 -0
  41. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/tasktoml.py +0 -0
  42. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/transport.py +0 -0
  43. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo/validate.py +0 -0
  44. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/SOURCES.txt +0 -0
  45. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/dependency_links.txt +0 -0
  46. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/entry_points.txt +0 -0
  47. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/requires.txt +0 -0
  48. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/instance_repo.egg-info/top_level.txt +0 -0
  49. {instance_repo-1.4.0.dev3 → instance_repo-1.4.0.dev6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.4.0.dev3
3
+ Version: 1.4.0.dev6
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
  RegistrationFailed, TransportError,
21
21
  )
22
22
 
23
- __version__ = "1.4.0.dev3"
23
+ __version__ = "1.4.0.dev6"
24
24
 
25
25
  __all__ = [
26
26
  "Repo", "load_instances",
@@ -154,6 +154,41 @@ class InstancesClient:
154
154
  prefix = getattr(self._p, "oss_prefix", None) or P.DEFAULT_PREFIX
155
155
  return Layout(model, prefix=prefix)
156
156
 
157
+ def _instance_assets_object_root(self, dataset: str, instance_id: str,
158
+ version: str, split: str,
159
+ metadata_model: str | None = None, *,
160
+ environment: str | None = None) -> str:
161
+ """资产目录相对于 object API 根的路径;注册的 object_path 优先。"""
162
+ lay = self._layout(metadata_model)
163
+ if version and self._reg is not None:
164
+ # 非标准 Version storage_path 可能已经是 object API 根,不能
165
+ # 无条件加版本名。服务端 object_path 已相对于它的真实根计算。
166
+ env = environment
167
+ if env is None:
168
+ env = getattr(self._p, "dataset_environment", None) or None
169
+ meta = self._reg.get(
170
+ dataset, version, instance_id, split,
171
+ **_registry_overrides(env, lay.model))
172
+ if meta is not None:
173
+ for entry in meta.manifest:
174
+ relative = (entry.object_path or "").rstrip("/")
175
+ if (entry.content_type == "directory" and relative
176
+ and relative.endswith("/" + instance_id)):
177
+ _validate_custom_asset_rel(relative)
178
+ return relative
179
+ for entry in meta.manifest:
180
+ relative = entry.object_path or ""
181
+ if (entry.content_type == "file"
182
+ and relative.endswith("/" + instance_id + ".json")):
183
+ _validate_custom_asset_rel(relative)
184
+ metadata_dir = relative.rsplit("/", 1)[0]
185
+ if metadata_dir == split or metadata_dir.endswith("/" + split):
186
+ return f"{metadata_dir}-assets/{instance_id}"
187
+ dataset_root = lay.dataset_root(dataset)
188
+ assets_dir = lay.assets_dir(
189
+ dataset, instance_id, version=version, split=split)
190
+ return assets_dir[len(dataset_root):].rstrip("/")
191
+
157
192
  # ── 只读 ──
158
193
  def validate(self, local_path):
159
194
  """校验实例:自动检测格式(目录→harbor,dir-notask→custom,.json→swe)。"""
@@ -414,7 +449,8 @@ class InstancesClient:
414
449
  """列举实例资产目录下的文件/子目录(自动翻页)。
415
450
 
416
451
  调用控制面 ``GET /apis/v1/datasets/objects``,返回指定实例的
417
- ``{split}-assets/{instance_id}/`` 路径下的目录和文件列表。
452
+ ``{version}/{split}-assets/{instance_id}/`` 路径下的目录和文件列表;
453
+ 无版本时省略 ``{version}/``。prefix 相对于 Dataset 根目录。
418
454
  自动翻页合并所有结果,直到 ``truncated=False`` 或达到 ``max_pages``。
419
455
 
420
456
  Parameters
@@ -455,12 +491,6 @@ class InstancesClient:
455
491
  raise SchemaError(
456
492
  "instance_id is required for instances.list_objects")
457
493
  split = (split or "default").strip()
458
- # 计算实例资产根前缀:{split}-assets/{instance_id}/
459
- instance_asset_prefix = f"{split}-assets/{instance_id.strip()}"
460
- if path:
461
- full_prefix = f"{instance_asset_prefix}/{path.strip().strip('/')}"
462
- else:
463
- full_prefix = instance_asset_prefix
464
494
  # environment / metadata_model:优先显式值,其次 profile 派生
465
495
  env = (environment or "").strip()
466
496
  if not env:
@@ -469,6 +499,14 @@ class InstancesClient:
469
499
  if requested_model is None:
470
500
  requested_model = getattr(self._p, "metadata_model", None)
471
501
  mm = business_metadata_model(requested_model)
502
+ # object API 的 prefix 相对于 Dataset 根,而非 Version 根。
503
+ instance_asset_prefix = self._instance_assets_object_root(
504
+ dataset.strip(), instance_id.strip(), version, split, mm,
505
+ environment=env or None)
506
+ if path:
507
+ full_prefix = f"{instance_asset_prefix}/{path.strip().strip('/')}"
508
+ else:
509
+ full_prefix = instance_asset_prefix
472
510
  # 自动翻页
473
511
  all_dirs: list = []
474
512
  all_files: list = []
@@ -1467,11 +1505,11 @@ class InstancesClient:
1467
1505
  # 递归列举:从根开始,遇到子目录继续深入
1468
1506
  asset_rels = []
1469
1507
  stack: list[str | None] = [None] # None = 实例资产根
1470
- # list_objects 返回的 f.path 包含完整前缀
1471
- # (如 test-assets/105-creep-forecast/solution/solve.py),
1472
- # 需要去掉 {split}-assets/{instance_id}/ 前缀得到相对路径。
1508
+ # 返回路径相对于 Dataset 根;去掉包含可选版本段的
1509
+ # 实例资产前缀,才是相对于实例目录的下载路径。
1473
1510
  split_str = (split or "default").strip()
1474
- assets_root = f"{split_str}-assets/{instance_id.strip()}/"
1511
+ assets_root = self._instance_assets_object_root(
1512
+ dataset, instance_id, version, split_str) + "/"
1475
1513
  while stack:
1476
1514
  cur_path = stack.pop()
1477
1515
  objs = self.list_objects(
@@ -1520,7 +1558,8 @@ class InstancesClient:
1520
1558
  asset_rels: list[str] = []
1521
1559
  stack: list[str | None] = [None]
1522
1560
  split_str = (split or "default").strip()
1523
- assets_root = f"{split_str}-assets/{instance_id.strip()}/"
1561
+ assets_root = self._instance_assets_object_root(
1562
+ dataset, instance_id, version, split_str) + "/"
1524
1563
  while stack:
1525
1564
  cur = stack.pop()
1526
1565
  page = self.list_objects(
@@ -110,6 +110,13 @@ class DatasetNotFound(BizCodeError):
110
110
  biz_code = 94021
111
111
 
112
112
 
113
+ class DatasetNamespaceConflict(BizCodeError):
114
+ """L1 命名空间冲突:根与子数据集不能共存(根先子后合法、子先根后拦截)。"""
115
+
116
+ code = "E_DATASET_NAMESPACE_CONFLICT"
117
+ biz_code = 92024
118
+
119
+
113
120
  class TransportError(InstanceRepoError):
114
121
  """apiserver HTTP 非预期响应。
115
122
 
@@ -169,6 +176,7 @@ CODE_TO_EXC: dict[str, type[InstanceRepoError]] = {
169
176
  CredExpired, PrivateNetworkRequired, WriteOutcomeUnknown,
170
177
  DatasetAccessDenied, DatasetClaimRequired, DatasetWriteDenied,
171
178
  DatasetIdentifierConflict, DatasetIdentifierRequired, DatasetNotFound,
179
+ DatasetNamespaceConflict,
172
180
  )
173
181
  }
174
182
 
@@ -178,6 +186,7 @@ BIZ_CODE_TO_EXC: dict[int, type[BizCodeError]] = {
178
186
  for e in (
179
187
  DatasetAccessDenied, DatasetClaimRequired, DatasetWriteDenied,
180
188
  DatasetIdentifierConflict, DatasetIdentifierRequired, DatasetNotFound,
189
+ DatasetNamespaceConflict,
181
190
  )
182
191
  }
183
192
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.4.0.dev3
3
+ Version: 1.4.0.dev6
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.4.0.dev3"
7
+ version = "1.4.0.dev6"
8
8
  description = "InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)"
9
9
  requires-python = ">=3.10"
10
10
  readme = "README.md"