instance-repo 1.3.2.dev3__tar.gz → 1.3.2.dev5__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.2.dev3 → instance_repo-1.3.2.dev5}/PKG-INFO +1 -1
  2. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/__init__.py +1 -1
  3. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/datasets.py +5 -3
  4. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/versions.py +14 -9
  5. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/oss.py +18 -2
  6. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/oss_discovery.py +70 -0
  7. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/PKG-INFO +1 -1
  8. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/pyproject.toml +1 -1
  9. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/README.md +0 -0
  10. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/_routing.py +0 -0
  11. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/_site_defaults.py +0 -0
  12. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/artifacts.py +0 -0
  13. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/bootstrap.py +0 -0
  14. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/cache.py +0 -0
  15. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/cli.py +0 -0
  16. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/__init__.py +0 -0
  17. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/benchmarks.py +0 -0
  18. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/config.py +0 -0
  19. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/images.py +0 -0
  20. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/instances.py +0 -0
  21. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/reports.py +0 -0
  22. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/scaffold.py +0 -0
  23. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/splits.py +0 -0
  24. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/clients/workflows.py +0 -0
  25. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/concurrency.py +0 -0
  26. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/content.py +0 -0
  27. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/endpoints.py +0 -0
  28. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/errors.py +0 -0
  29. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/image.py +0 -0
  30. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/layout.py +0 -0
  31. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/loader.py +0 -0
  32. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/models.py +0 -0
  33. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/paths.py +0 -0
  34. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/release.py +0 -0
  35. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/repo.py +0 -0
  36. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/retry.py +0 -0
  37. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/__init__.py +0 -0
  38. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/acr.py +0 -0
  39. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/base.py +0 -0
  40. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/store/registry.py +0 -0
  41. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/tasktoml.py +0 -0
  42. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/transport.py +0 -0
  43. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo/validate.py +0 -0
  44. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/SOURCES.txt +0 -0
  45. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/dependency_links.txt +0 -0
  46. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/entry_points.txt +0 -0
  47. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/requires.txt +0 -0
  48. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/instance_repo.egg-info/top_level.txt +0 -0
  49. {instance_repo-1.3.2.dev3 → instance_repo-1.3.2.dev5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.3.2.dev3
3
+ Version: 1.3.2.dev5
4
4
  Summary: InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -18,7 +18,7 @@ from .errors import (
18
18
  TransportError,
19
19
  )
20
20
 
21
- __version__ = "1.3.2.dev3"
21
+ __version__ = "1.3.2.dev5"
22
22
 
23
23
  __all__ = [
24
24
  "Repo", "load_instances",
@@ -161,7 +161,8 @@ class DatasetsClient:
161
161
  except TransportError as e:
162
162
  if (e.biz_code == 92001 and fallback_to_oss
163
163
  and self._content is not None):
164
- return self._discover_detail(name, storage_env=environment)
164
+ return self._discover_detail(name, storage_env=environment,
165
+ metadata_model=metadata_model)
165
166
  raise
166
167
 
167
168
  def update(self, name: str, *, display_name: str | None = None,
@@ -396,13 +397,14 @@ class DatasetsClient:
396
397
  # ── OSS fallback discovery (private) ─────────────────────────────────
397
398
 
398
399
  def _discover_detail(self, name: str, *,
399
- storage_env: str | None = None) -> DatasetDetail:
400
+ storage_env: str | None = None,
401
+ metadata_model: str | None = None) -> DatasetDetail:
400
402
  from ..store.oss_discovery import (
401
403
  parse_dataset_level, build_synthetic_dataset_detail,
402
404
  _warn_if_truncated)
403
405
  info = parse_dataset_level(
404
406
  self._content, name, oss_prefix=self._oss_prefix,
405
- metadata_model=self._metadata_model)
407
+ metadata_model=metadata_model or self._metadata_model)
406
408
  _warn_if_truncated(info, name, 500)
407
409
  if not info.versions and not info.unversioned_splits:
408
410
  from ..errors import DatasetNotFound
@@ -229,7 +229,7 @@ class VersionsClient:
229
229
  except TransportError as e:
230
230
  if (e.biz_code == 92001 and fallback_to_oss
231
231
  and self._content is not None):
232
- return self._discover_versions(dataset)
232
+ return self._discover_versions(dataset, metadata_model=metadata_model)
233
233
  raise
234
234
 
235
235
  def list_paged(self, dataset: str, *, status: str | None = None,
@@ -264,7 +264,8 @@ class VersionsClient:
264
264
  if (e.biz_code == 92001 and fallback_to_oss
265
265
  and self._content is not None):
266
266
  return self._discover_versions_paged(
267
- dataset, status, int(page), int(page_size))
267
+ dataset, status, int(page), int(page_size),
268
+ metadata_model=metadata_model)
268
269
  raise
269
270
  rows = data.get("versions", data) if isinstance(data, dict) else data
270
271
  rows = rows if isinstance(rows, list) else []
@@ -295,7 +296,8 @@ class VersionsClient:
295
296
  except TransportError as e:
296
297
  if (e.biz_code == 92001 and fallback_to_oss
297
298
  and self._content is not None):
298
- return self._discover_version(dataset, version)
299
+ return self._discover_version(dataset, version,
300
+ metadata_model=metadata_model)
299
301
  raise
300
302
 
301
303
  def status(self, dataset: str, version: str, *,
@@ -891,12 +893,13 @@ class VersionsClient:
891
893
 
892
894
  # ── OSS fallback discovery (private) ─────────────────────────────────
893
895
 
894
- def _discover_versions(self, dataset: str) -> list:
896
+ def _discover_versions(self, dataset: str,
897
+ metadata_model: str | None = None) -> list:
895
898
  from ..store.oss_discovery import (
896
899
  parse_dataset_level, build_synthetic_version, _warn_if_truncated)
897
900
  info = parse_dataset_level(
898
901
  self._content, dataset, oss_prefix=self._oss_prefix,
899
- metadata_model=self._discovery_mm())
902
+ metadata_model=metadata_model or self._discovery_mm())
900
903
  _warn_if_truncated(info, dataset, 500)
901
904
  # split_first 无版本布局(只有 split)也是发现成功,只是没有版本可列
902
905
  if not info.versions and not info.unversioned_splits:
@@ -905,20 +908,22 @@ class VersionsClient:
905
908
  return [build_synthetic_version(dataset, v) for v in info.versions]
906
909
 
907
910
  def _discover_versions_paged(self, dataset: str, status: str | None,
908
- page: int, page_size: int):
911
+ page: int, page_size: int,
912
+ metadata_model: str | None = None):
909
913
  """OSS 回退的 list_paged:全量探测后按 status 过滤 + 内存分页。"""
910
914
  from ..store.oss_discovery import _in_memory_paged
911
- items = self._discover_versions(dataset)
915
+ items = self._discover_versions(dataset, metadata_model=metadata_model)
912
916
  if (status or "").strip():
913
917
  items = [v for v in items if v.status == status.strip()]
914
918
  return _in_memory_paged(items, int(page), int(page_size))
915
919
 
916
- def _discover_version(self, dataset: str, version: str):
920
+ def _discover_version(self, dataset: str, version: str,
921
+ metadata_model: str | None = None):
917
922
  from ..store.oss_discovery import (
918
923
  parse_dataset_level, build_synthetic_version, _warn_if_truncated)
919
924
  info = parse_dataset_level(
920
925
  self._content, dataset, oss_prefix=self._oss_prefix,
921
- metadata_model=self._discovery_mm())
926
+ metadata_model=metadata_model or self._discovery_mm())
922
927
  _warn_if_truncated(info, dataset, 500)
923
928
  for v in info.versions:
924
929
  if v.version == version:
@@ -100,6 +100,22 @@ def _unconfirmed_private_endpoint_error(endpoint: str) -> PrivateNetworkRequired
100
100
  )
101
101
 
102
102
 
103
+ def _import_oss2(): # pragma: no cover - 真实 oss2
104
+ """惰性 import oss2,屏蔽其编译期 SyntaxWarning。
105
+
106
+ oss2 2.19.1 的 ``sign_url`` docstring 含非 raw 字符串里的 ``\\&``
107
+ (示例 URL 的 OSSAccessKeyId=...&Expires=...),首次 import 时 Python
108
+ 编译器对其发出 ``SyntaxWarning: invalid escape sequence '\\&'``——纯第三方
109
+ 文档噪音,与请求拼接无关。仅抑制 SyntaxWarning(编译期),不影响运行时
110
+ 其他警告。
111
+ """
112
+ import warnings as _warnings
113
+ with _warnings.catch_warnings():
114
+ _warnings.simplefilter("ignore", SyntaxWarning)
115
+ import oss2
116
+ return oss2
117
+
118
+
103
119
  def _default_bucket_factory(sts: dict, bucket: str, *,
104
120
  private_download: bool = False): # pragma: no cover - 真实 oss2
105
121
  """Build the default oss2 bucket, hardening private-download transport.
@@ -108,7 +124,7 @@ def _default_bucket_factory(sts: dict, bucket: str, *,
108
124
  this transport guarantee. The built-in private-download path forces HTTPS, ignores ambient
109
125
  proxy variables, and rejects redirects before requests can follow them.
110
126
  """
111
- import oss2
127
+ oss2 = _import_oss2()
112
128
 
113
129
  endpoint = sts["endpoint"]
114
130
  session = None
@@ -139,7 +155,7 @@ def _default_bucket_factory(sts: dict, bucket: str, *,
139
155
 
140
156
 
141
157
  def _default_resumable_upload(bucket, key: str, filename: str): # pragma: no cover - 真实 oss2
142
- import oss2
158
+ oss2 = _import_oss2()
143
159
  oss2.resumable_upload(bucket, key, filename)
144
160
 
145
161
 
@@ -23,6 +23,7 @@ from ..models import (
23
23
  DatasetInstance,
24
24
  DatasetSplit,
25
25
  DatasetVersion,
26
+ ManifestEntry,
26
27
  PagedResult,
27
28
  SplitManifest,
28
29
  )
@@ -564,6 +565,62 @@ def build_synthetic_instances(
564
565
  return instances
565
566
 
566
567
 
568
+ def _instance_dir(dataset: str, version: str, split: str | None,
569
+ instance_id: str, suffix: str, oss_prefix: str) -> str:
570
+ """拼接实例的 -assets/-report 目录;version 为空表示无版本 split 布局。"""
571
+ l1, l2 = P.split_dataset(dataset)
572
+ base = f"{oss_prefix}/{l1}/{l2}" + (f"/{version}" if version else "")
573
+ if split and split != "default":
574
+ return f"{base}/{split}-{suffix}/{instance_id}/"
575
+ return f"{base}-{suffix}/{instance_id}/"
576
+
577
+
578
+ def _format_from_key(key: str) -> str:
579
+ if key.endswith(".jsonl"):
580
+ return "jsonl"
581
+ if key.endswith(".json"):
582
+ return "json"
583
+ if key.endswith(".tgz") or key.endswith(".tar.gz"):
584
+ return "tgz"
585
+ return ""
586
+
587
+
588
+ def _instance_manifest(
589
+ content_store,
590
+ dataset: str,
591
+ version: str,
592
+ instance_id: str,
593
+ split: str | None,
594
+ metadata_key: str,
595
+ *,
596
+ oss_prefix: str,
597
+ ) -> list[ManifestEntry]:
598
+ """用 LIST 枚举实例的文件结构(metadata + {split}-assets + {split}-report)。
599
+
600
+ 发现模式(list-only STS)无 GetObject,读不到 metadata JSON 内容,但目录
601
+ 结构可通过 LIST 完整呈现——恰好满足「查看实例的目录文件结构」需求。
602
+ """
603
+ keys = [metadata_key]
604
+ for suffix in ("assets", "report"):
605
+ try:
606
+ keys.extend(k for k in content_store.list_objects(
607
+ _instance_dir(dataset, version, split, instance_id,
608
+ suffix, oss_prefix),
609
+ list_only=True) if not k.endswith("/"))
610
+ except Exception: # noqa: BLE001
611
+ pass # best-effort:无 assets/report 目录时忽略
612
+ bucket = getattr(content_store, "bucket_name", "") or ""
613
+ return [
614
+ ManifestEntry(
615
+ file_path=f"oss://{bucket}/{k}" if bucket else k,
616
+ content_type="file",
617
+ content_format=_format_from_key(k),
618
+ object_path=k,
619
+ )
620
+ for k in keys
621
+ ]
622
+
623
+
567
624
  def build_synthetic_instance(
568
625
  content_store,
569
626
  dataset: str,
@@ -573,11 +630,17 @@ def build_synthetic_instance(
573
630
  *,
574
631
  oss_prefix: str = "swe/datasets",
575
632
  read_content: bool = False,
633
+ include_files: bool = True,
576
634
  ) -> DatasetInstance | None:
577
635
  """Build a single :class:`DatasetInstance` by exact key lookup in OSS.
578
636
 
579
637
  Returns ``None`` if the metadata JSON does not exist. ``read_content``
580
638
  语义同 :func:`build_synthetic_instances`(发现模式默认跳过 JSON 回填)。
639
+
640
+ ``include_files``(默认 True)用 LIST 枚举实例文件结构(metadata + assets
641
+ + report 目录)回填 ``manifest``——文件名为真实值,digest/大小留空
642
+ (list-only STS 无 GetObject)。仅 instance get 单条路径开启,避免列表
643
+ 路径 N 倍 LIST 开销。
581
644
  """
582
645
  if version:
583
646
  key = P.metadata_key(
@@ -609,6 +672,13 @@ def build_synthetic_instance(
609
672
  split=split or "default",
610
673
  registered=False,
611
674
  )
675
+ if include_files:
676
+ try:
677
+ inst.manifest = _instance_manifest(
678
+ content_store, dataset, version, instance_id, split, key,
679
+ oss_prefix=oss_prefix)
680
+ except Exception: # noqa: BLE001
681
+ pass # best-effort:manifest 枚举失败不阻断实例返回
612
682
  if read_content:
613
683
  data = _read_json_object(content_store, key)
614
684
  if data:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instance-repo
3
- Version: 1.3.2.dev3
3
+ Version: 1.3.2.dev5
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.2.dev3"
7
+ version = "1.3.2.dev5"
8
8
  description = "InstanceRepo SDK — 评测 Instance 统一存储客户端(SDK-only;控制面由 apiserver 承载)"
9
9
  requires-python = ">=3.10"
10
10
  readme = "README.md"