dexverse-cli 0.0.2__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 (54) hide show
  1. dexverse_cli-0.0.2/.dockerignore +14 -0
  2. dexverse_cli-0.0.2/.gitignore +41 -0
  3. dexverse_cli-0.0.2/648584.hdf5 +0 -0
  4. dexverse_cli-0.0.2/Dockerfile +37 -0
  5. dexverse_cli-0.0.2/PKG-INFO +198 -0
  6. dexverse_cli-0.0.2/README.md +168 -0
  7. dexverse_cli-0.0.2/dexverse/__init__.py +54 -0
  8. dexverse_cli-0.0.2/dexverse/cli.py +422 -0
  9. dexverse_cli-0.0.2/dexverse/client.py +128 -0
  10. dexverse_cli-0.0.2/dexverse/config.py +85 -0
  11. dexverse_cli-0.0.2/dexverse/convert/__init__.py +38 -0
  12. dexverse_cli-0.0.2/dexverse/convert/hdf5_to_raw.py +498 -0
  13. dexverse_cli-0.0.2/dexverse/convert/image_video_encode.py +449 -0
  14. dexverse_cli-0.0.2/dexverse/downloader/__init__.py +26 -0
  15. dexverse_cli-0.0.2/dexverse/downloader/base.py +101 -0
  16. dexverse_cli-0.0.2/dexverse/downloader/http_backend.py +508 -0
  17. dexverse_cli-0.0.2/dexverse/downloader/manager.py +365 -0
  18. dexverse_cli-0.0.2/dexverse/downloader/python_s3_backend.py +137 -0
  19. dexverse_cli-0.0.2/dexverse/downloader/s5cmd_backend.py +170 -0
  20. dexverse_cli-0.0.2/dexverse/downloader/state.py +263 -0
  21. dexverse_cli-0.0.2/dexverse/downloader/verify.py +114 -0
  22. dexverse_cli-0.0.2/dexverse/manifest.py +284 -0
  23. dexverse_cli-0.0.2/dexverse/mock/__init__.py +2 -0
  24. dexverse_cli-0.0.2/dexverse/mock/mock_tasks.json +22 -0
  25. dexverse_cli-0.0.2/dexverse/mock/server.py +211 -0
  26. dexverse_cli-0.0.2/docker_run.sh +105 -0
  27. dexverse_cli-0.0.2/docs/DexVerse_Downloader_S3_Final_/345/256/236/346/226/275/346/226/271/346/241/210_/345/216/237/350/267/257/345/276/204/350/220/275/347/233/230/347/211/210.md +1090 -0
  28. dexverse_cli-0.0.2/docs/PROMPT_copy_and_download_command.md +130 -0
  29. dexverse_cli-0.0.2/docs/Python_vs_Node_CLI/345/257/271/346/257/224/345/210/206/346/236/220.md +167 -0
  30. dexverse_cli-0.0.2/docs/Python_vs_Node_/346/216/245/345/205/245C++/345/257/271/346/257/224/345/210/206/346/236/220.md +197 -0
  31. dexverse_cli-0.0.2/docs//345/210/206/345/217/221/347/273/231/347/256/227/346/263/225/345/233/242/351/230/237_/346/225/231/347/250/213.md +315 -0
  32. dexverse_cli-0.0.2/docs//346/223/215/344/275/234/346/214/207/345/215/227--/345/234/250Dexechain/344/270/255/350/277/233/350/241/214/346/250/241/344/273/277/345/255/246/344/271/240.md +120 -0
  33. dexverse_cli-0.0.2/docs//346/234/215/345/212/241/345/231/250/344/275/277/347/224/250/346/211/213/345/206/214.md +64 -0
  34. dexverse_cli-0.0.2/examples/download (7).json +55 -0
  35. dexverse_cli-0.0.2/examples/local_demo.py +80 -0
  36. dexverse_cli-0.0.2/examples/manifest.json +45 -0
  37. dexverse_cli-0.0.2/examples/manifest_presigned.json +34 -0
  38. dexverse_cli-0.0.2/pyproject.toml +53 -0
  39. dexverse_cli-0.0.2/set-creds.ps1 +3 -0
  40. dexverse_cli-0.0.2/tests/conftest.py +19 -0
  41. dexverse_cli-0.0.2/tests/test_cli.py +134 -0
  42. dexverse_cli-0.0.2/tests/test_convert_task_instruction.py +87 -0
  43. dexverse_cli-0.0.2/tests/test_http_backend.py +405 -0
  44. dexverse_cli-0.0.2/tests/test_http_resilience.py +203 -0
  45. dexverse_cli-0.0.2/tests/test_manager_integration.py +202 -0
  46. dexverse_cli-0.0.2/tests/test_manifest.py +138 -0
  47. dexverse_cli-0.0.2/tests/test_manifest_aliases.py +134 -0
  48. dexverse_cli-0.0.2/tests/test_mock_server.py +72 -0
  49. dexverse_cli-0.0.2/tests/test_presigned_fixes.py +189 -0
  50. dexverse_cli-0.0.2/tests/test_review_fixes.py +265 -0
  51. dexverse_cli-0.0.2/tests/test_s5cmd_generation.py +72 -0
  52. dexverse_cli-0.0.2/tests/test_state.py +73 -0
  53. dexverse_cli-0.0.2/tests/test_verify.py +67 -0
  54. dexverse_cli-0.0.2/tests/test_version.py +13 -0
@@ -0,0 +1,14 @@
1
+ .venv/
2
+ venv/
3
+ __pycache__/
4
+ *.pyc
5
+ .pytest_cache/
6
+ .git/
7
+ .gitignore
8
+ tests/
9
+ examples/
10
+ *.md
11
+ DexVerse_Downloader_S3_Final_*.md
12
+ download-state.json
13
+ *.s5cmd
14
+ .dexverse/
@@ -0,0 +1,41 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ *.whl
9
+
10
+ # Virtual envs
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # Test / coverage
16
+ .pytest_cache/
17
+ .coverage
18
+ htmlcov/
19
+
20
+ # Secrets — NEVER commit (see doc section 13.1)
21
+ .env
22
+ .env.*
23
+ config.toml
24
+ dexverse/config.toml
25
+
26
+ # Real manifests with presigned URLs / S3 creds (regenerated per download).
27
+ # examples/manifest*.json are tracked templates with placeholder URLs.
28
+ /manifest.json
29
+ /manifest*.json
30
+
31
+ # Local download state / artifacts
32
+ .dexverse/
33
+ *.s5cmd
34
+ download-state.json
35
+ download.log
36
+
37
+ # Editor / OS
38
+ .idea/
39
+ .vscode/
40
+ .DS_Store
41
+ Thumbs.db
Binary file
@@ -0,0 +1,37 @@
1
+ # syntax=docker/dockerfile:1
2
+ # DexVerse downloader — bundles Python + dexverse + s5cmd (doc §19).
3
+ # Supports all three backends: s5cmd (default), python (boto3), http (presigned URLs).
4
+ #
5
+ # docker build -t dexverse/dexverse-dl:latest .
6
+ # docker run --rm -v /data:/out dexverse/dexverse-dl:latest \
7
+ # download --manifest /manifest.json --out /out --backend http
8
+ #
9
+ # Or with a task id (manifest fetched from the backend inside the container):
10
+ # docker run --rm -v /data:/out -e DEXVERSE_TOKEN=xxx \
11
+ # dexverse/dexverse-dl:latest download --task dl_xxx --out /out \
12
+ # --server https://dexverse.example.com --backend http
13
+
14
+ FROM python:3.11-slim AS base
15
+
16
+ ENV PYTHONDONTWRITEBYTECODE=1 \
17
+ PYTHONUNBUFFERED=1 \
18
+ PIP_NO_CACHE_DIR=1
19
+
20
+ # s5cmd (for the high-throughput s5cmd backend; harmless if you only use http/python)
21
+ ARG S5CMD_VERSION=v2.3.0
22
+ ADD https://github.com/peak/s5cmd/releases/download/${S5CMD_VERSION}/s5cmd_${S5CMD_VERSION}_Linux-64bit.tar.gz /tmp/s5cmd.tar.gz
23
+ RUN tar -xzf /tmp/s5cmd.tar.gz -C /usr/local/bin s5cmd && rm /tmp/s5cmd.tar.gz
24
+
25
+ # The package version comes from pyproject.toml. Keep exactly one built wheel
26
+ # in dist/ so Docker never needs a duplicated, hard-coded version number.
27
+ COPY dist/dexverse-*.whl /tmp/wheels/
28
+ RUN set -- /tmp/wheels/dexverse-*.whl; \
29
+ if [ "$#" -ne 1 ]; then \
30
+ echo "expected exactly one dexverse wheel in dist/, found $#"; \
31
+ exit 1; \
32
+ fi; \
33
+ pip install --no-cache-dir "${1}[s3]"
34
+
35
+ WORKDIR /work
36
+ ENTRYPOINT ["dexverse-dl"]
37
+ CMD ["--help"]
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: dexverse-cli
3
+ Version: 0.0.2
4
+ Summary: DexVerse dataset downloader for S3-compatible robot training datasets
5
+ Author: DexVerse
6
+ License: Apache-2.0
7
+ Keywords: dataset,dexverse,downloader,minio,robotics,s3,s5cmd
8
+ Requires-Python: >=3.9
9
+ Requires-Dist: av>=12
10
+ Requires-Dist: h5py>=3.10
11
+ Requires-Dist: httpx>=0.27
12
+ Requires-Dist: numpy>=1.26
13
+ Requires-Dist: pillow>=10
14
+ Requires-Dist: pydantic>=2.0
15
+ Requires-Dist: rich>=13.0
16
+ Requires-Dist: tomlkit>=0.12
17
+ Requires-Dist: typer>=0.12
18
+ Provides-Extra: dev
19
+ Requires-Dist: boto3>=1.34; extra == 'dev'
20
+ Requires-Dist: fastapi>=0.110; extra == 'dev'
21
+ Requires-Dist: httpx>=0.27; extra == 'dev'
22
+ Requires-Dist: moto[s3]>=5.0; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Provides-Extra: mock
25
+ Requires-Dist: fastapi>=0.110; extra == 'mock'
26
+ Requires-Dist: uvicorn>=0.27; extra == 'mock'
27
+ Provides-Extra: s3
28
+ Requires-Dist: boto3>=1.34; extra == 's3'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # DexVerse Downloader (`dexverse`)
32
+
33
+ Presigned-URL batch downloader for robot-training datasets.
34
+
35
+ ```text
36
+ manifest -> dexverse-dl -> httpx -> presigned URLs -> local file landing
37
+ ```
38
+
39
+ The primary input is the DexVerse backend's raw presigned-URL JSON. For those
40
+ payloads, `storage_path` is the remote object key and `file_name` is the local
41
+ landing path under `--out`.
42
+
43
+ Canonical manifests are still supported. Their local paths come from
44
+ `relativePath`, falling back to `originalPath`, then `objectKey`:
45
+
46
+ ```text
47
+ localPath = out / (file.relativePath || file.originalPath || file.objectKey)
48
+ ```
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install "dexverse[s3,mock]" # boto3 + fastapi mock server
54
+ # optional legacy S3 backend:
55
+ # install s5cmd (https://github.com/peak/s5cmd) and put it on PATH
56
+ ```
57
+
58
+ Development:
59
+
60
+ ```bash
61
+ uv venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
62
+ uv pip install -e ".[dev]"
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ If your backend issues short-lived presigned URLs per file, save that response
68
+ as `download.json` and run:
69
+
70
+ ```bash
71
+ dexverse-dl download --manifest ./download.json --out D:\DexVerse
72
+ ```
73
+
74
+ No login, no `AWS_*` credentials, no s5cmd, no backend flag, and no TLS flag are
75
+ required for the common internal/self-signed endpoint case. The default backend
76
+ is `http`, and TLS verification is disabled by default for http/presigned
77
+ downloads. Use `--secure` when the endpoint has a valid certificate and you want
78
+ certificate validation.
79
+
80
+ Raw backend output is accepted directly:
81
+
82
+ ```json
83
+ [{
84
+ "download_url": "https://host/bucket/datasets/.../20260429_180359.hdf5?X-Amz-Signature=...",
85
+ "storage_bucket": "dexverse",
86
+ "storage_path": "datasets/.../20260429_180359.hdf5",
87
+ "file_name": "20260429_180359.hdf5",
88
+ "file_size": 14994636,
89
+ "task_instruction": {
90
+ "aaa": "111",
91
+ "aaaa": 222,
92
+ "ewrwrwe": 1.1111111111111112e+54
93
+ }
94
+ }]
95
+ ```
96
+
97
+ Result:
98
+
99
+ ```text
100
+ D:\DexVerse\20260429_180359.hdf5
101
+ ```
102
+
103
+ `task_instruction` is optional and must be a JSON object. If multiple manifest
104
+ items resolve to the same local path (for example, repeated `file_name`
105
+ values), the first item wins and later duplicates are ignored.
106
+
107
+ Include `file_size` (and preferably `sha256`) for large files. The HTTP backend
108
+ also learns the total size from `Content-Length`/`Content-Range`, but manifest
109
+ metadata lets the CLI verify an existing local file before making a request.
110
+
111
+ Transient timeouts and HTTP 408/425/429/5xx responses are retried five times by
112
+ default. Bytes already received stay in a sibling `<file>.part`; retries and
113
+ later CLI runs request the remaining bytes with HTTP Range, while the final
114
+ destination path only appears after the size check succeeds. The object server
115
+ must support Range requests for efficient resume.
116
+
117
+ Presigned URLs expire, often after 1 hour. Have the backend regenerate the
118
+ manifest right before each download; expired URLs surface as per-file `HTTP 403`
119
+ errors. After generating a fresh `download.json`, run the same command with the
120
+ same `--out` path to continue from the retained `.part`.
121
+
122
+ ## CLI
123
+
124
+ ```bash
125
+ dexverse-dl login --server https://dexverse.xxx.com [--token TOKEN]
126
+ dexverse-dl download --manifest ./download.json --out /data/dexverse [--parallel 16] [--secure] [--backend http|python|s5cmd]
127
+ dexverse-dl download --manifest ./download.json --out /data/dexverse [--http-read-timeout 120] [--http-retries 5]
128
+ dexverse-dl download --task dl_xxx --out /data/dexverse [--server URL]
129
+ dexverse-dl verify --manifest PATH --out /data/dexverse [--deep]
130
+ dexverse-dl repair --manifest PATH --out /data/dexverse [--backend http|python|s5cmd]
131
+ ```
132
+
133
+ ### 还原 HDF5 → 可训练数据
134
+
135
+ 下载完成后,把落盘的 `.hdf5` 还原为原始录制结构(逐帧 JPEG + `pose_record_*.json`
136
+ + `metadata.jsonl`)。如果对应 manifest 带有 `task_instruction`,还会自动生成
137
+ `task_instruction.json`:
138
+
139
+ ```bash
140
+ # 单文件
141
+ dexverse-dl convert -i /data/dexverse/20260429_180359.hdf5 -o /data/dexverse/restored
142
+ # 批量(递归处理目录下所有 *.hdf5,保持目录结构)
143
+ dexverse-dl convert --input-dir /data/dexverse -o /data/dexverse/restored
144
+ ```
145
+
146
+ 还原输出形如:
147
+
148
+ ```text
149
+ /data/dexverse/restored/20260429_180359/
150
+ head/left/000000.jpg ...
151
+ head/right/000000.jpg ...
152
+ hand/left/000000.jpg ...
153
+ hand/right/000000.jpg ...
154
+ pose_record_20260429_180359.json
155
+ metadata.jsonl
156
+ task_instruction.json
157
+ ```
158
+
159
+ `task_instruction.json` 的内容就是 manifest 中的对象本身,不增加外层包装。
160
+ 下载器会把转换所需的映射保存在 `.dexverse/task-instructions/`,无需为
161
+ `convert` 增加额外参数。独立来源且没有该隐藏元数据的 HDF5 仍按原行为还原。
162
+
163
+ 该命令依赖 `h5py` / `numpy` / `av` / `pillow`,已列入核心依赖,安装时随包装上。
164
+
165
+ ## Python SDK
166
+
167
+ ```python
168
+ from dexverse import DexVerseClient, download_manifest
169
+
170
+ client = DexVerseClient(server="https://dexverse.xxx.com", token="xxx")
171
+ local_root = client.download_task(task_id="dl_xxx", out="/data/dexverse", parallel=16)
172
+
173
+ # or from a local manifest file
174
+ download_manifest(manifest_path="./download.json", out="/data/dexverse")
175
+ ```
176
+
177
+ ## Layout
178
+
179
+ State files live under `<out>/.dexverse/` and never mix into the dataset tree:
180
+
181
+ ```text
182
+ /data/dexverse/
183
+ .dexverse/task-instructions/
184
+ 20260429_180359.hdf5.json
185
+ .dexverse/tasks/<taskId>/
186
+ manifest.json
187
+ download-state.json
188
+ download.log
189
+ 20260429_180359.hdf5
190
+ ```
191
+
192
+ ## Backends
193
+
194
+ | backend | engine | notes |
195
+ |----------|-------------------|-----------------------------------------|
196
+ | `http` | httpx | default; presigned URLs, no creds/login |
197
+ | `python` | boto3 | legacy S3 fallback |
198
+ | `s5cmd` | peak/s5cmd binary | legacy S3 high-throughput backend |
@@ -0,0 +1,168 @@
1
+ # DexVerse Downloader (`dexverse`)
2
+
3
+ Presigned-URL batch downloader for robot-training datasets.
4
+
5
+ ```text
6
+ manifest -> dexverse-dl -> httpx -> presigned URLs -> local file landing
7
+ ```
8
+
9
+ The primary input is the DexVerse backend's raw presigned-URL JSON. For those
10
+ payloads, `storage_path` is the remote object key and `file_name` is the local
11
+ landing path under `--out`.
12
+
13
+ Canonical manifests are still supported. Their local paths come from
14
+ `relativePath`, falling back to `originalPath`, then `objectKey`:
15
+
16
+ ```text
17
+ localPath = out / (file.relativePath || file.originalPath || file.objectKey)
18
+ ```
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install "dexverse[s3,mock]" # boto3 + fastapi mock server
24
+ # optional legacy S3 backend:
25
+ # install s5cmd (https://github.com/peak/s5cmd) and put it on PATH
26
+ ```
27
+
28
+ Development:
29
+
30
+ ```bash
31
+ uv venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
32
+ uv pip install -e ".[dev]"
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ If your backend issues short-lived presigned URLs per file, save that response
38
+ as `download.json` and run:
39
+
40
+ ```bash
41
+ dexverse-dl download --manifest ./download.json --out D:\DexVerse
42
+ ```
43
+
44
+ No login, no `AWS_*` credentials, no s5cmd, no backend flag, and no TLS flag are
45
+ required for the common internal/self-signed endpoint case. The default backend
46
+ is `http`, and TLS verification is disabled by default for http/presigned
47
+ downloads. Use `--secure` when the endpoint has a valid certificate and you want
48
+ certificate validation.
49
+
50
+ Raw backend output is accepted directly:
51
+
52
+ ```json
53
+ [{
54
+ "download_url": "https://host/bucket/datasets/.../20260429_180359.hdf5?X-Amz-Signature=...",
55
+ "storage_bucket": "dexverse",
56
+ "storage_path": "datasets/.../20260429_180359.hdf5",
57
+ "file_name": "20260429_180359.hdf5",
58
+ "file_size": 14994636,
59
+ "task_instruction": {
60
+ "aaa": "111",
61
+ "aaaa": 222,
62
+ "ewrwrwe": 1.1111111111111112e+54
63
+ }
64
+ }]
65
+ ```
66
+
67
+ Result:
68
+
69
+ ```text
70
+ D:\DexVerse\20260429_180359.hdf5
71
+ ```
72
+
73
+ `task_instruction` is optional and must be a JSON object. If multiple manifest
74
+ items resolve to the same local path (for example, repeated `file_name`
75
+ values), the first item wins and later duplicates are ignored.
76
+
77
+ Include `file_size` (and preferably `sha256`) for large files. The HTTP backend
78
+ also learns the total size from `Content-Length`/`Content-Range`, but manifest
79
+ metadata lets the CLI verify an existing local file before making a request.
80
+
81
+ Transient timeouts and HTTP 408/425/429/5xx responses are retried five times by
82
+ default. Bytes already received stay in a sibling `<file>.part`; retries and
83
+ later CLI runs request the remaining bytes with HTTP Range, while the final
84
+ destination path only appears after the size check succeeds. The object server
85
+ must support Range requests for efficient resume.
86
+
87
+ Presigned URLs expire, often after 1 hour. Have the backend regenerate the
88
+ manifest right before each download; expired URLs surface as per-file `HTTP 403`
89
+ errors. After generating a fresh `download.json`, run the same command with the
90
+ same `--out` path to continue from the retained `.part`.
91
+
92
+ ## CLI
93
+
94
+ ```bash
95
+ dexverse-dl login --server https://dexverse.xxx.com [--token TOKEN]
96
+ dexverse-dl download --manifest ./download.json --out /data/dexverse [--parallel 16] [--secure] [--backend http|python|s5cmd]
97
+ dexverse-dl download --manifest ./download.json --out /data/dexverse [--http-read-timeout 120] [--http-retries 5]
98
+ dexverse-dl download --task dl_xxx --out /data/dexverse [--server URL]
99
+ dexverse-dl verify --manifest PATH --out /data/dexverse [--deep]
100
+ dexverse-dl repair --manifest PATH --out /data/dexverse [--backend http|python|s5cmd]
101
+ ```
102
+
103
+ ### 还原 HDF5 → 可训练数据
104
+
105
+ 下载完成后,把落盘的 `.hdf5` 还原为原始录制结构(逐帧 JPEG + `pose_record_*.json`
106
+ + `metadata.jsonl`)。如果对应 manifest 带有 `task_instruction`,还会自动生成
107
+ `task_instruction.json`:
108
+
109
+ ```bash
110
+ # 单文件
111
+ dexverse-dl convert -i /data/dexverse/20260429_180359.hdf5 -o /data/dexverse/restored
112
+ # 批量(递归处理目录下所有 *.hdf5,保持目录结构)
113
+ dexverse-dl convert --input-dir /data/dexverse -o /data/dexverse/restored
114
+ ```
115
+
116
+ 还原输出形如:
117
+
118
+ ```text
119
+ /data/dexverse/restored/20260429_180359/
120
+ head/left/000000.jpg ...
121
+ head/right/000000.jpg ...
122
+ hand/left/000000.jpg ...
123
+ hand/right/000000.jpg ...
124
+ pose_record_20260429_180359.json
125
+ metadata.jsonl
126
+ task_instruction.json
127
+ ```
128
+
129
+ `task_instruction.json` 的内容就是 manifest 中的对象本身,不增加外层包装。
130
+ 下载器会把转换所需的映射保存在 `.dexverse/task-instructions/`,无需为
131
+ `convert` 增加额外参数。独立来源且没有该隐藏元数据的 HDF5 仍按原行为还原。
132
+
133
+ 该命令依赖 `h5py` / `numpy` / `av` / `pillow`,已列入核心依赖,安装时随包装上。
134
+
135
+ ## Python SDK
136
+
137
+ ```python
138
+ from dexverse import DexVerseClient, download_manifest
139
+
140
+ client = DexVerseClient(server="https://dexverse.xxx.com", token="xxx")
141
+ local_root = client.download_task(task_id="dl_xxx", out="/data/dexverse", parallel=16)
142
+
143
+ # or from a local manifest file
144
+ download_manifest(manifest_path="./download.json", out="/data/dexverse")
145
+ ```
146
+
147
+ ## Layout
148
+
149
+ State files live under `<out>/.dexverse/` and never mix into the dataset tree:
150
+
151
+ ```text
152
+ /data/dexverse/
153
+ .dexverse/task-instructions/
154
+ 20260429_180359.hdf5.json
155
+ .dexverse/tasks/<taskId>/
156
+ manifest.json
157
+ download-state.json
158
+ download.log
159
+ 20260429_180359.hdf5
160
+ ```
161
+
162
+ ## Backends
163
+
164
+ | backend | engine | notes |
165
+ |----------|-------------------|-----------------------------------------|
166
+ | `http` | httpx | default; presigned URLs, no creds/login |
167
+ | `python` | boto3 | legacy S3 fallback |
168
+ | `s5cmd` | peak/s5cmd binary | legacy S3 high-throughput backend |
@@ -0,0 +1,54 @@
1
+ """DexVerse Downloader — S3-compatible dataset downloader.
2
+
3
+ Public API:
4
+
5
+ from dexverse import DexVerseClient, download_manifest
6
+ from dexverse import Manifest, FileSpec
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from importlib.metadata import PackageNotFoundError, version
11
+ from pathlib import Path
12
+
13
+ import tomlkit
14
+
15
+ from .client import DexVerseClient, DexVerseError, download_manifest
16
+ from .manifest import (
17
+ FileSpec,
18
+ Manifest,
19
+ Storage,
20
+ StorageCredentials,
21
+ DownloadOptions,
22
+ resolve_dest,
23
+ resolve_relpath,
24
+ )
25
+
26
+ def _resolve_version() -> str:
27
+ """Read the single source version in development, package metadata otherwise."""
28
+ pyproject = Path(__file__).resolve().parent.parent / "pyproject.toml"
29
+ if pyproject.is_file():
30
+ document = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
31
+ project_version = document.get("project", {}).get("version")
32
+ if isinstance(project_version, str):
33
+ return project_version
34
+ try:
35
+ return version("dexverse")
36
+ except PackageNotFoundError:
37
+ return "0.0.0+unknown"
38
+
39
+
40
+ __version__ = _resolve_version()
41
+
42
+ __all__ = [
43
+ "DexVerseClient",
44
+ "DexVerseError",
45
+ "download_manifest",
46
+ "Manifest",
47
+ "FileSpec",
48
+ "Storage",
49
+ "StorageCredentials",
50
+ "DownloadOptions",
51
+ "resolve_dest",
52
+ "resolve_relpath",
53
+ "__version__",
54
+ ]