ds-crawler 2.13.0__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.
- ds_crawler-2.13.0/.gitignore +23 -0
- ds_crawler-2.13.0/CHANGELOG.md +5 -0
- ds_crawler-2.13.0/CONTRIBUTING.md +46 -0
- ds_crawler-2.13.0/LICENSE +21 -0
- ds_crawler-2.13.0/PKG-INFO +342 -0
- ds_crawler-2.13.0/README.md +309 -0
- ds_crawler-2.13.0/SECURITY.md +15 -0
- ds_crawler-2.13.0/docs/configuration.md +222 -0
- ds_crawler-2.13.0/docs/validated-publication.md +65 -0
- ds_crawler-2.13.0/ds_crawler/__init__.py +119 -0
- ds_crawler-2.13.0/ds_crawler/_dataset_contract.py +45 -0
- ds_crawler-2.13.0/ds_crawler/_version.py +13 -0
- ds_crawler-2.13.0/ds_crawler/artifact_builder.py +255 -0
- ds_crawler-2.13.0/ds_crawler/artifacts.py +247 -0
- ds_crawler-2.13.0/ds_crawler/cli.py +375 -0
- ds_crawler-2.13.0/ds_crawler/config.py +509 -0
- ds_crawler-2.13.0/ds_crawler/handlers/__init__.py +36 -0
- ds_crawler-2.13.0/ds_crawler/handlers/base.py +30 -0
- ds_crawler-2.13.0/ds_crawler/handlers/generic.py +28 -0
- ds_crawler-2.13.0/ds_crawler/handlers/zip_handler.py +53 -0
- ds_crawler-2.13.0/ds_crawler/layout.py +165 -0
- ds_crawler-2.13.0/ds_crawler/migration.py +775 -0
- ds_crawler-2.13.0/ds_crawler/operations.py +1994 -0
- ds_crawler-2.13.0/ds_crawler/parser.py +831 -0
- ds_crawler-2.13.0/ds_crawler/path_filters.py +229 -0
- ds_crawler-2.13.0/ds_crawler/records.py +462 -0
- ds_crawler-2.13.0/ds_crawler/schema.py +159 -0
- ds_crawler-2.13.0/ds_crawler/traversal.py +391 -0
- ds_crawler-2.13.0/ds_crawler/validation.py +444 -0
- ds_crawler-2.13.0/ds_crawler/writer.py +758 -0
- ds_crawler-2.13.0/ds_crawler/zip_utils.py +722 -0
- ds_crawler-2.13.0/examples/augmented_rgb_example.py +175 -0
- ds_crawler-2.13.0/examples/basic_usage.py +48 -0
- ds_crawler-2.13.0/meta/__init__.py +0 -0
- ds_crawler-2.13.0/meta/build_meta_schema.py +26 -0
- ds_crawler-2.13.0/meta/schema.json +374 -0
- ds_crawler-2.13.0/pyproject.toml +78 -0
- ds_crawler-2.13.0/tests/__init__.py +0 -0
- ds_crawler-2.13.0/tests/current_helpers.py +133 -0
- ds_crawler-2.13.0/tests/test_align_datasets.py +65 -0
- ds_crawler-2.13.0/tests/test_artifact_builder.py +172 -0
- ds_crawler-2.13.0/tests/test_attributes_passthrough.py +111 -0
- ds_crawler-2.13.0/tests/test_config.py +137 -0
- ds_crawler-2.13.0/tests/test_copy_dataset.py +62 -0
- ds_crawler-2.13.0/tests/test_extract_datasets.py +87 -0
- ds_crawler-2.13.0/tests/test_handlers.py +44 -0
- ds_crawler-2.13.0/tests/test_inline_splits.py +365 -0
- ds_crawler-2.13.0/tests/test_integration.py +200 -0
- ds_crawler-2.13.0/tests/test_layout.py +59 -0
- ds_crawler-2.13.0/tests/test_meta_schema.py +51 -0
- ds_crawler-2.13.0/tests/test_metadata_scopes.py +312 -0
- ds_crawler-2.13.0/tests/test_new_metadata.py +474 -0
- ds_crawler-2.13.0/tests/test_parser.py +189 -0
- ds_crawler-2.13.0/tests/test_records.py +236 -0
- ds_crawler-2.13.0/tests/test_split_dataset.py +72 -0
- ds_crawler-2.13.0/tests/test_validation.py +125 -0
- ds_crawler-2.13.0/tests/test_writer.py +169 -0
- ds_crawler-2.13.0/tests/test_zip.py +63 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.coverage
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.venv/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
|
|
12
|
+
# Editors and operating systems
|
|
13
|
+
.DS_Store
|
|
14
|
+
.vscode/
|
|
15
|
+
|
|
16
|
+
# Local tooling and agent state
|
|
17
|
+
.ao-mcp/
|
|
18
|
+
.ao-provider-auth/
|
|
19
|
+
.claude/
|
|
20
|
+
|
|
21
|
+
# Local datasets and scratch output
|
|
22
|
+
/cluster/
|
|
23
|
+
/SHOULD_MATCH
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for improving `ds-crawler`. Small, focused changes with tests are the
|
|
4
|
+
easiest to review.
|
|
5
|
+
|
|
6
|
+
## Set up a development environment
|
|
7
|
+
|
|
8
|
+
The project uses Python 3.9 or newer and [uv](https://docs.astral.sh/uv/):
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/d-rothen/ds-crawler.git
|
|
12
|
+
cd ds-crawler
|
|
13
|
+
uv sync --extra dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Before opening a pull request
|
|
17
|
+
|
|
18
|
+
Run the same core checks as CI:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv run ruff check .
|
|
22
|
+
uv run pytest
|
|
23
|
+
uv build
|
|
24
|
+
uv run python scripts/verify_distribution.py dist/*
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
When changing modality metadata, regenerate the checked-in schema and run its
|
|
28
|
+
test:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
uv run build-meta-schema
|
|
32
|
+
uv run pytest tests/test_meta_schema.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Please include a regression test for behavior changes and update the README or
|
|
36
|
+
configuration reference when public behavior changes. Avoid committing dataset
|
|
37
|
+
archives, generated build output, local paths, credentials, or editor state.
|
|
38
|
+
|
|
39
|
+
## Reporting bugs
|
|
40
|
+
|
|
41
|
+
Open a GitHub issue with a minimal configuration, representative relative file
|
|
42
|
+
paths, the expected result, and the full error. Remove private dataset paths or
|
|
43
|
+
metadata before posting.
|
|
44
|
+
|
|
45
|
+
Security issues follow a separate private process described in
|
|
46
|
+
[SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Rothenpieler <rothenpielerdaniel@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ds-crawler
|
|
3
|
+
Version: 2.13.0
|
|
4
|
+
Summary: Regex-based dataset crawler, indexer, and artifact toolkit
|
|
5
|
+
Project-URL: Homepage, https://github.com/d-rothen/ds-crawler
|
|
6
|
+
Project-URL: Issues, https://github.com/d-rothen/ds-crawler/issues
|
|
7
|
+
Project-URL: Repository, https://github.com/d-rothen/ds-crawler
|
|
8
|
+
Author-email: Daniel Rothenpieler <rothenpielerdaniel@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: dataset,indexing,machine-learning,metadata,zip
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: euler-dataset-contract>=0.8.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
29
|
+
Requires-Dist: tqdm; extra == 'dev'
|
|
30
|
+
Provides-Extra: progress
|
|
31
|
+
Requires-Dist: tqdm; extra == 'progress'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# ds-crawler
|
|
35
|
+
|
|
36
|
+
[](https://github.com/d-rothen/ds-crawler/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/ds-crawler/)
|
|
38
|
+
[](https://pypi.org/project/ds-crawler/)
|
|
39
|
+
|
|
40
|
+
Build stable, queryable metadata for datasets whose structure is encoded in
|
|
41
|
+
file paths.
|
|
42
|
+
|
|
43
|
+
`ds-crawler` scans directories or ZIP archives, extracts IDs, hierarchy, and
|
|
44
|
+
properties with regular expressions, and writes a small set of versioned JSON
|
|
45
|
+
artifacts. It also aligns modalities, creates reproducible splits, copies or
|
|
46
|
+
extracts subsets, and indexes generated outputs.
|
|
47
|
+
|
|
48
|
+
- Directory and `.zip` inputs use the same API.
|
|
49
|
+
- Regex capture groups define IDs, hierarchy, and file properties.
|
|
50
|
+
- Include/exclude filters keep irrelevant files out of the index.
|
|
51
|
+
- Named splits and metadata scopes are first-class artifacts.
|
|
52
|
+
- Dataset semantics live in the shared `euler-dataset-contract` format.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install ds-crawler
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Progress bars are optional:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install "ds-crawler[progress]"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Python 3.9 or newer is required.
|
|
67
|
+
|
|
68
|
+
## Quick start
|
|
69
|
+
|
|
70
|
+
Given this dataset:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
foggy_rgb/
|
|
74
|
+
├── .ds_crawler/
|
|
75
|
+
│ ├── dataset-head.json
|
|
76
|
+
│ └── ds-crawler.json
|
|
77
|
+
├── scene_01/
|
|
78
|
+
│ ├── 0001.png
|
|
79
|
+
│ └── 0002.png
|
|
80
|
+
└── scene_02/
|
|
81
|
+
└── 0001.png
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
describe its semantic identity in `.ds_crawler/dataset-head.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"contract": {"kind": "dataset_head", "version": "1.0"},
|
|
89
|
+
"dataset": {"id": "foggy_rgb", "name": "Foggy RGB"},
|
|
90
|
+
"modality": {
|
|
91
|
+
"key": "rgb",
|
|
92
|
+
"meta": {"range": [0, 255]}
|
|
93
|
+
},
|
|
94
|
+
"addons": {
|
|
95
|
+
"euler_train": {
|
|
96
|
+
"version": "1.0",
|
|
97
|
+
"used_as": "input",
|
|
98
|
+
"slot": "dehaze.input.rgb"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then describe how paths become index entries in
|
|
105
|
+
`.ds_crawler/ds-crawler.json`:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"contract": {"kind": "ds_crawler_config", "version": "2.0"},
|
|
110
|
+
"head_file": "dataset-head.json",
|
|
111
|
+
"source": {"path": "."},
|
|
112
|
+
"indexing": {
|
|
113
|
+
"id": {
|
|
114
|
+
"regex": "^(?P<scene>[^/]+)/(?P<frame>\\d+)\\.png$",
|
|
115
|
+
"join_char": "+"
|
|
116
|
+
},
|
|
117
|
+
"hierarchy": {
|
|
118
|
+
"regex": "^(?P<scene>[^/]+)/",
|
|
119
|
+
"separator": ":"
|
|
120
|
+
},
|
|
121
|
+
"properties": {
|
|
122
|
+
"basename": {
|
|
123
|
+
"regex": "^(?P<frame>\\d+)\\.(?P<ext>png)$"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"files": {"extensions": [".png"]},
|
|
127
|
+
"constraints": {"flat_ids_unique": true}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Index and persist the dataset:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from ds_crawler import get_files, index_dataset_from_path
|
|
136
|
+
|
|
137
|
+
output = index_dataset_from_path("/data/foggy_rgb", save_index=True)
|
|
138
|
+
|
|
139
|
+
print(output["head"]["dataset"]["name"])
|
|
140
|
+
print(get_files(output))
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The returned object is hydrated with the dataset head and indexing recipe for
|
|
144
|
+
convenience. The saved `index.json` stays minimal.
|
|
145
|
+
|
|
146
|
+
For a self-contained example that creates a temporary dataset, see
|
|
147
|
+
[`examples/basic_usage.py`](examples/basic_usage.py).
|
|
148
|
+
|
|
149
|
+
## Artifact layout
|
|
150
|
+
|
|
151
|
+
For a physical root containing several logical modalities, prefer the scoped
|
|
152
|
+
layout. Each modality gets a complete, isolated artifact set and `scopes.json`
|
|
153
|
+
provides the discovery manifest:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
foggy_rgb/
|
|
157
|
+
├── .ds_crawler/
|
|
158
|
+
│ ├── scopes.json
|
|
159
|
+
│ ├── rgb/
|
|
160
|
+
│ │ ├── dataset-head.json
|
|
161
|
+
│ │ ├── ds-crawler.json
|
|
162
|
+
│ │ ├── index.json
|
|
163
|
+
│ │ └── split_train.json
|
|
164
|
+
│ └── camera_extrinsics/
|
|
165
|
+
│ ├── dataset-head.json
|
|
166
|
+
│ ├── ds-crawler.json
|
|
167
|
+
│ └── index.json
|
|
168
|
+
└── ...
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Pass `metadata_scope="rgb"` (or another safe modality name) to path-based APIs
|
|
172
|
+
to read and write `.ds_crawler/rgb/`. Scoped writes maintain `scopes.json`
|
|
173
|
+
automatically.
|
|
174
|
+
|
|
175
|
+
For a root with just one logical dataset, the compact unscoped layout remains
|
|
176
|
+
supported:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
foggy_rgb/
|
|
180
|
+
├── .ds_crawler/
|
|
181
|
+
│ ├── dataset-head.json
|
|
182
|
+
│ ├── ds-crawler.json
|
|
183
|
+
│ ├── index.json
|
|
184
|
+
│ └── split_train.json
|
|
185
|
+
└── ...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The files in either artifact set are:
|
|
189
|
+
|
|
190
|
+
| File | Purpose |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `dataset-head.json` | Dataset identity, modality metadata, and namespaced addons. |
|
|
193
|
+
| `ds-crawler.json` | Source and indexing recipe. |
|
|
194
|
+
| `index.json` | Materialized recursive file index. |
|
|
195
|
+
| `split_<name>.json` | A named, filtered index with provenance. |
|
|
196
|
+
|
|
197
|
+
See [the configuration reference](docs/configuration.md) for every supported
|
|
198
|
+
field, artifact shape, path filter, and hierarchy pattern.
|
|
199
|
+
|
|
200
|
+
## Common workflows
|
|
201
|
+
|
|
202
|
+
### Use the CLI
|
|
203
|
+
|
|
204
|
+
A CLI config can reference one or more datasets that already contain crawler
|
|
205
|
+
metadata:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"datasets": [
|
|
210
|
+
{"path": "/data/foggy_rgb"},
|
|
211
|
+
{"path": "/data/foggy_depth"}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
ds-crawler index datasets.json
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`index` is optional for backwards compatibility, so `ds-crawler datasets.json`
|
|
221
|
+
is equivalent. Useful flags include:
|
|
222
|
+
|
|
223
|
+
| Flag | Effect |
|
|
224
|
+
|---|---|
|
|
225
|
+
| `--strict` | Abort on duplicate IDs. |
|
|
226
|
+
| `--sample N` | Keep every Nth matched file deterministically. |
|
|
227
|
+
| `--match-index PATH` | Keep only hierarchy-qualified IDs found in another index. |
|
|
228
|
+
| `--metadata-scope SCOPE` | Read and write a scoped artifact set. |
|
|
229
|
+
| `--workdir PATH` | Resolve relative dataset paths from a specific directory. |
|
|
230
|
+
| `--verbose` | Log each skipped file. |
|
|
231
|
+
|
|
232
|
+
### Align modalities
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
from ds_crawler import align_datasets
|
|
236
|
+
|
|
237
|
+
aligned = align_datasets(
|
|
238
|
+
{"modality": "rgb", "source": "/data/foggy_rgb"},
|
|
239
|
+
{"modality": "depth", "source": "/data/foggy_depth"},
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
rgb_path = aligned["scene-scene_01+frame-0001"]["rgb"]["path"]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Alignment is by leaf ID. For modalities that apply at an ancestor hierarchy
|
|
246
|
+
level, preserve the hierarchy and join in the consumer instead; the runnable
|
|
247
|
+
[`augmented RGB example`](examples/augmented_rgb_example.py) demonstrates that
|
|
248
|
+
layout.
|
|
249
|
+
|
|
250
|
+
### Create reproducible splits
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from ds_crawler import create_dataset_splits, load_dataset_split
|
|
254
|
+
|
|
255
|
+
create_dataset_splits(
|
|
256
|
+
"/data/foggy_rgb",
|
|
257
|
+
split_names=["train", "validation"],
|
|
258
|
+
ratios=[80, 20],
|
|
259
|
+
seed=42,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
train = load_dataset_split("/data/foggy_rgb", "train")
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Use `create_aligned_dataset_splits` for several modalities,
|
|
266
|
+
`create_hierarchy_dataset_splits` for hierarchy rules, or
|
|
267
|
+
`create_mapped_dataset_splits` for an explicit qualified-ID mapping.
|
|
268
|
+
`copy_dataset_splits` transfers an existing partition to a sibling dataset and
|
|
269
|
+
fails before writing if any target ID is missing.
|
|
270
|
+
|
|
271
|
+
### Write generated data
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
from ds_crawler import DatasetWriter
|
|
275
|
+
|
|
276
|
+
head = {
|
|
277
|
+
"contract": {"kind": "dataset_head", "version": "1.0"},
|
|
278
|
+
"dataset": {"id": "predicted_rgb", "name": "Predicted RGB"},
|
|
279
|
+
"modality": {"key": "rgb", "meta": {"range": [0, 255]}},
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
writer = DatasetWriter("/data/predicted_rgb", head=head)
|
|
283
|
+
path = writer.get_path("/scene:scene_01/frame-0001", "0001.png")
|
|
284
|
+
path.write_bytes(encoded_image)
|
|
285
|
+
writer.save_index()
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`ZipDatasetWriter` provides the same index-building behavior for a new ZIP
|
|
289
|
+
archive and accepts bytes or writable file-like objects.
|
|
290
|
+
|
|
291
|
+
### Migrate legacy metadata
|
|
292
|
+
|
|
293
|
+
Normal loading is intentionally strict about the current schema. Migrate older
|
|
294
|
+
`output.json`-based datasets explicitly:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
ds-crawler migrate-metadata /data/legacy_dataset
|
|
298
|
+
ds-crawler migrate-metadata /data/archive.zip
|
|
299
|
+
ds-crawler migrate-metadata /data/datasets --scan-zips
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Run `ds-crawler migrate-metadata --help` for archive scanning, inline split,
|
|
303
|
+
and metadata-scope options.
|
|
304
|
+
|
|
305
|
+
## Python API
|
|
306
|
+
|
|
307
|
+
The main entry points are re-exported from `ds_crawler`:
|
|
308
|
+
|
|
309
|
+
| Area | Entry points |
|
|
310
|
+
|---|---|
|
|
311
|
+
| Build | `build_dataset_head`, `build_crawler_config`, `build_dataset_artifacts_from_files` |
|
|
312
|
+
| Index | `index_dataset`, `index_dataset_from_files`, `index_dataset_from_path` |
|
|
313
|
+
| Inspect | `get_files`, `collect_qualified_ids`, `get_dataset_contract`, `get_dataset_properties` |
|
|
314
|
+
| Split | `create_dataset_splits`, `create_aligned_dataset_splits`, `create_hierarchy_dataset_splits`, `create_mapped_dataset_splits`, `load_dataset_split` |
|
|
315
|
+
| Transform | `align_datasets`, `copy_dataset`, `extract_datasets`, `split_dataset`, `split_datasets` |
|
|
316
|
+
| Write | `DatasetWriter`, `ZipDatasetWriter` |
|
|
317
|
+
| Validate | `validate_crawler_config`, `validate_dataset`, `validate_output` |
|
|
318
|
+
|
|
319
|
+
All core path-based workflows support directories and ZIP archives. Scope-aware
|
|
320
|
+
operations accept `metadata_scope`; multi-source operations also expose
|
|
321
|
+
per-source scope arguments where needed.
|
|
322
|
+
|
|
323
|
+
## Development
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
git clone https://github.com/d-rothen/ds-crawler.git
|
|
327
|
+
cd ds-crawler
|
|
328
|
+
uv sync --extra dev
|
|
329
|
+
uv run pytest
|
|
330
|
+
uv run ruff check .
|
|
331
|
+
uv build
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) before submitting a change. To
|
|
335
|
+
report a vulnerability, follow [SECURITY.md](SECURITY.md).
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
Licensed under the [MIT License](LICENSE). Copyright © 2026 Daniel Rothenpieler
|
|
340
|
+
<rothenpielerdaniel@gmail.com>.
|
|
341
|
+
|
|
342
|
+
See [Phase 2 validated-publication](docs/validated-publication.md) for the opt-in captured spatial workflow (2.11.0, unreleased).
|