atdata 0.1.3b4__py3-none-any.whl → 0.2.2b1__py3-none-any.whl
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.
- atdata/__init__.py +44 -8
- atdata/_cid.py +150 -0
- atdata/_hf_api.py +692 -0
- atdata/_protocols.py +519 -0
- atdata/_schema_codec.py +442 -0
- atdata/_sources.py +515 -0
- atdata/_stub_manager.py +529 -0
- atdata/_type_utils.py +90 -0
- atdata/atmosphere/__init__.py +332 -0
- atdata/atmosphere/_types.py +331 -0
- atdata/atmosphere/client.py +533 -0
- atdata/atmosphere/lens.py +284 -0
- atdata/atmosphere/records.py +509 -0
- atdata/atmosphere/schema.py +239 -0
- atdata/atmosphere/store.py +208 -0
- atdata/cli/__init__.py +213 -0
- atdata/cli/diagnose.py +165 -0
- atdata/cli/local.py +280 -0
- atdata/dataset.py +510 -324
- atdata/lens.py +63 -112
- atdata/local.py +1707 -0
- atdata/promote.py +199 -0
- atdata-0.2.2b1.dist-info/METADATA +272 -0
- atdata-0.2.2b1.dist-info/RECORD +28 -0
- {atdata-0.1.3b4.dist-info → atdata-0.2.2b1.dist-info}/WHEEL +1 -1
- atdata-0.1.3b4.dist-info/METADATA +0 -172
- atdata-0.1.3b4.dist-info/RECORD +0 -9
- {atdata-0.1.3b4.dist-info → atdata-0.2.2b1.dist-info}/entry_points.txt +0 -0
- {atdata-0.1.3b4.dist-info → atdata-0.2.2b1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
"""Dataset record publishing and loading for ATProto.
|
|
2
|
+
|
|
3
|
+
This module provides classes for publishing dataset index records to ATProto
|
|
4
|
+
and loading them back. Dataset records are published as
|
|
5
|
+
``ac.foundation.dataset.record`` records.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Type, TypeVar, Optional
|
|
9
|
+
import msgpack
|
|
10
|
+
|
|
11
|
+
from .client import AtmosphereClient
|
|
12
|
+
from .schema import SchemaPublisher
|
|
13
|
+
from ._types import (
|
|
14
|
+
AtUri,
|
|
15
|
+
DatasetRecord,
|
|
16
|
+
StorageLocation,
|
|
17
|
+
LEXICON_NAMESPACE,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Import for type checking only to avoid circular imports
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from ..dataset import PackableSample, Dataset
|
|
24
|
+
|
|
25
|
+
ST = TypeVar("ST", bound="PackableSample")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DatasetPublisher:
|
|
29
|
+
"""Publishes dataset index records to ATProto.
|
|
30
|
+
|
|
31
|
+
This class creates dataset records that reference a schema and point to
|
|
32
|
+
external storage (WebDataset URLs) or ATProto blobs.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
::
|
|
36
|
+
|
|
37
|
+
>>> dataset = atdata.Dataset[MySample]("s3://bucket/data-{000000..000009}.tar")
|
|
38
|
+
>>>
|
|
39
|
+
>>> client = AtmosphereClient()
|
|
40
|
+
>>> client.login("handle", "password")
|
|
41
|
+
>>>
|
|
42
|
+
>>> publisher = DatasetPublisher(client)
|
|
43
|
+
>>> uri = publisher.publish(
|
|
44
|
+
... dataset,
|
|
45
|
+
... name="My Training Data",
|
|
46
|
+
... description="Training data for my model",
|
|
47
|
+
... tags=["computer-vision", "training"],
|
|
48
|
+
... )
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, client: AtmosphereClient):
|
|
52
|
+
"""Initialize the dataset publisher.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
client: Authenticated AtmosphereClient instance.
|
|
56
|
+
"""
|
|
57
|
+
self.client = client
|
|
58
|
+
self._schema_publisher = SchemaPublisher(client)
|
|
59
|
+
|
|
60
|
+
def publish(
|
|
61
|
+
self,
|
|
62
|
+
dataset: "Dataset[ST]",
|
|
63
|
+
*,
|
|
64
|
+
name: str,
|
|
65
|
+
schema_uri: Optional[str] = None,
|
|
66
|
+
description: Optional[str] = None,
|
|
67
|
+
tags: Optional[list[str]] = None,
|
|
68
|
+
license: Optional[str] = None,
|
|
69
|
+
auto_publish_schema: bool = True,
|
|
70
|
+
schema_version: str = "1.0.0",
|
|
71
|
+
rkey: Optional[str] = None,
|
|
72
|
+
) -> AtUri:
|
|
73
|
+
"""Publish a dataset index record to ATProto.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
dataset: The Dataset to publish.
|
|
77
|
+
name: Human-readable dataset name.
|
|
78
|
+
schema_uri: AT URI of the schema record. If not provided and
|
|
79
|
+
auto_publish_schema is True, the schema will be published.
|
|
80
|
+
description: Human-readable description.
|
|
81
|
+
tags: Searchable tags for discovery.
|
|
82
|
+
license: SPDX license identifier (e.g., 'MIT', 'Apache-2.0').
|
|
83
|
+
auto_publish_schema: If True and schema_uri not provided,
|
|
84
|
+
automatically publish the schema first.
|
|
85
|
+
schema_version: Version for auto-published schema.
|
|
86
|
+
rkey: Optional explicit record key.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
The AT URI of the created dataset record.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
ValueError: If schema_uri is not provided and auto_publish_schema is False.
|
|
93
|
+
"""
|
|
94
|
+
# Ensure we have a schema reference
|
|
95
|
+
if schema_uri is None:
|
|
96
|
+
if not auto_publish_schema:
|
|
97
|
+
raise ValueError(
|
|
98
|
+
"schema_uri is required when auto_publish_schema=False"
|
|
99
|
+
)
|
|
100
|
+
# Auto-publish the schema
|
|
101
|
+
schema_uri_obj = self._schema_publisher.publish(
|
|
102
|
+
dataset.sample_type,
|
|
103
|
+
version=schema_version,
|
|
104
|
+
)
|
|
105
|
+
schema_uri = str(schema_uri_obj)
|
|
106
|
+
|
|
107
|
+
# Build the storage location
|
|
108
|
+
storage = StorageLocation(
|
|
109
|
+
kind="external",
|
|
110
|
+
urls=[dataset.url],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Build dataset record
|
|
114
|
+
metadata_bytes: Optional[bytes] = None
|
|
115
|
+
if dataset.metadata is not None:
|
|
116
|
+
metadata_bytes = msgpack.packb(dataset.metadata)
|
|
117
|
+
|
|
118
|
+
dataset_record = DatasetRecord(
|
|
119
|
+
name=name,
|
|
120
|
+
schema_ref=schema_uri,
|
|
121
|
+
storage=storage,
|
|
122
|
+
description=description,
|
|
123
|
+
tags=tags or [],
|
|
124
|
+
license=license,
|
|
125
|
+
metadata=metadata_bytes,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Publish to ATProto
|
|
129
|
+
return self.client.create_record(
|
|
130
|
+
collection=f"{LEXICON_NAMESPACE}.record",
|
|
131
|
+
record=dataset_record.to_record(),
|
|
132
|
+
rkey=rkey,
|
|
133
|
+
validate=False,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def publish_with_urls(
|
|
137
|
+
self,
|
|
138
|
+
urls: list[str],
|
|
139
|
+
schema_uri: str,
|
|
140
|
+
*,
|
|
141
|
+
name: str,
|
|
142
|
+
description: Optional[str] = None,
|
|
143
|
+
tags: Optional[list[str]] = None,
|
|
144
|
+
license: Optional[str] = None,
|
|
145
|
+
metadata: Optional[dict] = None,
|
|
146
|
+
rkey: Optional[str] = None,
|
|
147
|
+
) -> AtUri:
|
|
148
|
+
"""Publish a dataset record with explicit URLs.
|
|
149
|
+
|
|
150
|
+
This method allows publishing a dataset record without having a
|
|
151
|
+
Dataset object, useful for registering existing WebDataset files.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
urls: List of WebDataset URLs with brace notation.
|
|
155
|
+
schema_uri: AT URI of the schema record.
|
|
156
|
+
name: Human-readable dataset name.
|
|
157
|
+
description: Human-readable description.
|
|
158
|
+
tags: Searchable tags for discovery.
|
|
159
|
+
license: SPDX license identifier.
|
|
160
|
+
metadata: Arbitrary metadata dictionary.
|
|
161
|
+
rkey: Optional explicit record key.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
The AT URI of the created dataset record.
|
|
165
|
+
"""
|
|
166
|
+
storage = StorageLocation(
|
|
167
|
+
kind="external",
|
|
168
|
+
urls=urls,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
metadata_bytes: Optional[bytes] = None
|
|
172
|
+
if metadata is not None:
|
|
173
|
+
metadata_bytes = msgpack.packb(metadata)
|
|
174
|
+
|
|
175
|
+
dataset_record = DatasetRecord(
|
|
176
|
+
name=name,
|
|
177
|
+
schema_ref=schema_uri,
|
|
178
|
+
storage=storage,
|
|
179
|
+
description=description,
|
|
180
|
+
tags=tags or [],
|
|
181
|
+
license=license,
|
|
182
|
+
metadata=metadata_bytes,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
return self.client.create_record(
|
|
186
|
+
collection=f"{LEXICON_NAMESPACE}.record",
|
|
187
|
+
record=dataset_record.to_record(),
|
|
188
|
+
rkey=rkey,
|
|
189
|
+
validate=False,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def publish_with_blobs(
|
|
193
|
+
self,
|
|
194
|
+
blobs: list[bytes],
|
|
195
|
+
schema_uri: str,
|
|
196
|
+
*,
|
|
197
|
+
name: str,
|
|
198
|
+
description: Optional[str] = None,
|
|
199
|
+
tags: Optional[list[str]] = None,
|
|
200
|
+
license: Optional[str] = None,
|
|
201
|
+
metadata: Optional[dict] = None,
|
|
202
|
+
mime_type: str = "application/x-tar",
|
|
203
|
+
rkey: Optional[str] = None,
|
|
204
|
+
) -> AtUri:
|
|
205
|
+
"""Publish a dataset with data stored as ATProto blobs.
|
|
206
|
+
|
|
207
|
+
This method uploads the provided data as blobs to the PDS and creates
|
|
208
|
+
a dataset record referencing them. Suitable for smaller datasets that
|
|
209
|
+
fit within blob size limits (typically 50MB per blob, configurable).
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
blobs: List of binary data (e.g., tar shards) to upload as blobs.
|
|
213
|
+
schema_uri: AT URI of the schema record.
|
|
214
|
+
name: Human-readable dataset name.
|
|
215
|
+
description: Human-readable description.
|
|
216
|
+
tags: Searchable tags for discovery.
|
|
217
|
+
license: SPDX license identifier.
|
|
218
|
+
metadata: Arbitrary metadata dictionary.
|
|
219
|
+
mime_type: MIME type for the blobs (default: application/x-tar).
|
|
220
|
+
rkey: Optional explicit record key.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
The AT URI of the created dataset record.
|
|
224
|
+
|
|
225
|
+
Note:
|
|
226
|
+
Blobs are only retained by the PDS when referenced in a committed
|
|
227
|
+
record. This method handles that automatically.
|
|
228
|
+
"""
|
|
229
|
+
# Upload all blobs
|
|
230
|
+
blob_refs = []
|
|
231
|
+
for blob_data in blobs:
|
|
232
|
+
blob_ref = self.client.upload_blob(blob_data, mime_type=mime_type)
|
|
233
|
+
blob_refs.append(blob_ref)
|
|
234
|
+
|
|
235
|
+
# Create storage location with blob references
|
|
236
|
+
storage = StorageLocation(
|
|
237
|
+
kind="blobs",
|
|
238
|
+
blob_refs=blob_refs,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
metadata_bytes: Optional[bytes] = None
|
|
242
|
+
if metadata is not None:
|
|
243
|
+
metadata_bytes = msgpack.packb(metadata)
|
|
244
|
+
|
|
245
|
+
dataset_record = DatasetRecord(
|
|
246
|
+
name=name,
|
|
247
|
+
schema_ref=schema_uri,
|
|
248
|
+
storage=storage,
|
|
249
|
+
description=description,
|
|
250
|
+
tags=tags or [],
|
|
251
|
+
license=license,
|
|
252
|
+
metadata=metadata_bytes,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
return self.client.create_record(
|
|
256
|
+
collection=f"{LEXICON_NAMESPACE}.record",
|
|
257
|
+
record=dataset_record.to_record(),
|
|
258
|
+
rkey=rkey,
|
|
259
|
+
validate=False,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class DatasetLoader:
|
|
264
|
+
"""Loads dataset records from ATProto.
|
|
265
|
+
|
|
266
|
+
This class fetches dataset index records and can create Dataset objects
|
|
267
|
+
from them. Note that loading a dataset requires having the corresponding
|
|
268
|
+
Python class for the sample type.
|
|
269
|
+
|
|
270
|
+
Example:
|
|
271
|
+
::
|
|
272
|
+
|
|
273
|
+
>>> client = AtmosphereClient()
|
|
274
|
+
>>> loader = DatasetLoader(client)
|
|
275
|
+
>>>
|
|
276
|
+
>>> # List available datasets
|
|
277
|
+
>>> datasets = loader.list()
|
|
278
|
+
>>> for ds in datasets:
|
|
279
|
+
... print(ds["name"], ds["schemaRef"])
|
|
280
|
+
>>>
|
|
281
|
+
>>> # Get a specific dataset record
|
|
282
|
+
>>> record = loader.get("at://did:plc:abc/ac.foundation.dataset.record/xyz")
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
def __init__(self, client: AtmosphereClient):
|
|
286
|
+
"""Initialize the dataset loader.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
client: AtmosphereClient instance.
|
|
290
|
+
"""
|
|
291
|
+
self.client = client
|
|
292
|
+
|
|
293
|
+
def get(self, uri: str | AtUri) -> dict:
|
|
294
|
+
"""Fetch a dataset record by AT URI.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
uri: The AT URI of the dataset record.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
The dataset record as a dictionary.
|
|
301
|
+
|
|
302
|
+
Raises:
|
|
303
|
+
ValueError: If the record is not a dataset record.
|
|
304
|
+
"""
|
|
305
|
+
record = self.client.get_record(uri)
|
|
306
|
+
|
|
307
|
+
expected_type = f"{LEXICON_NAMESPACE}.record"
|
|
308
|
+
if record.get("$type") != expected_type:
|
|
309
|
+
raise ValueError(
|
|
310
|
+
f"Record at {uri} is not a dataset record. "
|
|
311
|
+
f"Expected $type='{expected_type}', got '{record.get('$type')}'"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
return record
|
|
315
|
+
|
|
316
|
+
def list_all(
|
|
317
|
+
self,
|
|
318
|
+
repo: Optional[str] = None,
|
|
319
|
+
limit: int = 100,
|
|
320
|
+
) -> list[dict]:
|
|
321
|
+
"""List dataset records from a repository.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
repo: The DID of the repository. Defaults to authenticated user.
|
|
325
|
+
limit: Maximum number of records to return.
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
List of dataset records.
|
|
329
|
+
"""
|
|
330
|
+
return self.client.list_datasets(repo=repo, limit=limit)
|
|
331
|
+
|
|
332
|
+
def get_storage_type(self, uri: str | AtUri) -> str:
|
|
333
|
+
"""Get the storage type of a dataset record.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
uri: The AT URI of the dataset record.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
Either "external" or "blobs".
|
|
340
|
+
|
|
341
|
+
Raises:
|
|
342
|
+
ValueError: If storage type is unknown.
|
|
343
|
+
"""
|
|
344
|
+
record = self.get(uri)
|
|
345
|
+
storage = record.get("storage", {})
|
|
346
|
+
storage_type = storage.get("$type", "")
|
|
347
|
+
|
|
348
|
+
if "storageExternal" in storage_type:
|
|
349
|
+
return "external"
|
|
350
|
+
elif "storageBlobs" in storage_type:
|
|
351
|
+
return "blobs"
|
|
352
|
+
else:
|
|
353
|
+
raise ValueError(f"Unknown storage type: {storage_type}")
|
|
354
|
+
|
|
355
|
+
def get_urls(self, uri: str | AtUri) -> list[str]:
|
|
356
|
+
"""Get the WebDataset URLs from a dataset record.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
uri: The AT URI of the dataset record.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
List of WebDataset URLs.
|
|
363
|
+
|
|
364
|
+
Raises:
|
|
365
|
+
ValueError: If the storage type is not external URLs.
|
|
366
|
+
"""
|
|
367
|
+
record = self.get(uri)
|
|
368
|
+
storage = record.get("storage", {})
|
|
369
|
+
|
|
370
|
+
storage_type = storage.get("$type", "")
|
|
371
|
+
if "storageExternal" in storage_type:
|
|
372
|
+
return storage.get("urls", [])
|
|
373
|
+
elif "storageBlobs" in storage_type:
|
|
374
|
+
raise ValueError(
|
|
375
|
+
"Dataset uses blob storage, not external URLs. "
|
|
376
|
+
"Use get_blob_urls() instead."
|
|
377
|
+
)
|
|
378
|
+
else:
|
|
379
|
+
raise ValueError(f"Unknown storage type: {storage_type}")
|
|
380
|
+
|
|
381
|
+
def get_blobs(self, uri: str | AtUri) -> list[dict]:
|
|
382
|
+
"""Get the blob references from a dataset record.
|
|
383
|
+
|
|
384
|
+
Args:
|
|
385
|
+
uri: The AT URI of the dataset record.
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
List of blob reference dicts with keys: $type, ref, mimeType, size.
|
|
389
|
+
|
|
390
|
+
Raises:
|
|
391
|
+
ValueError: If the storage type is not blobs.
|
|
392
|
+
"""
|
|
393
|
+
record = self.get(uri)
|
|
394
|
+
storage = record.get("storage", {})
|
|
395
|
+
|
|
396
|
+
storage_type = storage.get("$type", "")
|
|
397
|
+
if "storageBlobs" in storage_type:
|
|
398
|
+
return storage.get("blobs", [])
|
|
399
|
+
elif "storageExternal" in storage_type:
|
|
400
|
+
raise ValueError(
|
|
401
|
+
"Dataset uses external URL storage, not blobs. "
|
|
402
|
+
"Use get_urls() instead."
|
|
403
|
+
)
|
|
404
|
+
else:
|
|
405
|
+
raise ValueError(f"Unknown storage type: {storage_type}")
|
|
406
|
+
|
|
407
|
+
def get_blob_urls(self, uri: str | AtUri) -> list[str]:
|
|
408
|
+
"""Get fetchable URLs for blob-stored dataset shards.
|
|
409
|
+
|
|
410
|
+
This resolves the PDS endpoint and constructs URLs that can be
|
|
411
|
+
used to fetch the blob data directly.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
uri: The AT URI of the dataset record.
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
List of URLs for fetching the blob data.
|
|
418
|
+
|
|
419
|
+
Raises:
|
|
420
|
+
ValueError: If storage type is not blobs or PDS cannot be resolved.
|
|
421
|
+
"""
|
|
422
|
+
if isinstance(uri, str):
|
|
423
|
+
parsed_uri = AtUri.parse(uri)
|
|
424
|
+
else:
|
|
425
|
+
parsed_uri = uri
|
|
426
|
+
|
|
427
|
+
blobs = self.get_blobs(uri)
|
|
428
|
+
did = parsed_uri.authority
|
|
429
|
+
|
|
430
|
+
urls = []
|
|
431
|
+
for blob in blobs:
|
|
432
|
+
# Extract CID from blob reference
|
|
433
|
+
ref = blob.get("ref", {})
|
|
434
|
+
cid = ref.get("$link") if isinstance(ref, dict) else str(ref)
|
|
435
|
+
if cid:
|
|
436
|
+
url = self.client.get_blob_url(did, cid)
|
|
437
|
+
urls.append(url)
|
|
438
|
+
|
|
439
|
+
return urls
|
|
440
|
+
|
|
441
|
+
def get_metadata(self, uri: str | AtUri) -> Optional[dict]:
|
|
442
|
+
"""Get the metadata from a dataset record.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
uri: The AT URI of the dataset record.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
The metadata dictionary, or None if no metadata.
|
|
449
|
+
"""
|
|
450
|
+
record = self.get(uri)
|
|
451
|
+
metadata_bytes = record.get("metadata")
|
|
452
|
+
|
|
453
|
+
if metadata_bytes is None:
|
|
454
|
+
return None
|
|
455
|
+
|
|
456
|
+
return msgpack.unpackb(metadata_bytes, raw=False)
|
|
457
|
+
|
|
458
|
+
def to_dataset(
|
|
459
|
+
self,
|
|
460
|
+
uri: str | AtUri,
|
|
461
|
+
sample_type: Type[ST],
|
|
462
|
+
) -> "Dataset[ST]":
|
|
463
|
+
"""Create a Dataset object from an ATProto record.
|
|
464
|
+
|
|
465
|
+
This method creates a Dataset instance from a published record.
|
|
466
|
+
You must provide the sample type class, which should match the
|
|
467
|
+
schema referenced by the record.
|
|
468
|
+
|
|
469
|
+
Supports both external URL storage and ATProto blob storage.
|
|
470
|
+
|
|
471
|
+
Args:
|
|
472
|
+
uri: The AT URI of the dataset record.
|
|
473
|
+
sample_type: The Python class for the sample type.
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
A Dataset instance configured from the record.
|
|
477
|
+
|
|
478
|
+
Raises:
|
|
479
|
+
ValueError: If no storage URLs can be resolved.
|
|
480
|
+
|
|
481
|
+
Example:
|
|
482
|
+
::
|
|
483
|
+
|
|
484
|
+
>>> loader = DatasetLoader(client)
|
|
485
|
+
>>> dataset = loader.to_dataset(uri, MySampleType)
|
|
486
|
+
>>> for batch in dataset.shuffled(batch_size=32):
|
|
487
|
+
... process(batch)
|
|
488
|
+
"""
|
|
489
|
+
# Import here to avoid circular import
|
|
490
|
+
from ..dataset import Dataset
|
|
491
|
+
|
|
492
|
+
storage_type = self.get_storage_type(uri)
|
|
493
|
+
|
|
494
|
+
if storage_type == "external":
|
|
495
|
+
urls = self.get_urls(uri)
|
|
496
|
+
else:
|
|
497
|
+
urls = self.get_blob_urls(uri)
|
|
498
|
+
|
|
499
|
+
if not urls:
|
|
500
|
+
raise ValueError("Dataset record has no storage URLs")
|
|
501
|
+
|
|
502
|
+
# Use the first URL (multi-URL support could be added later)
|
|
503
|
+
url = urls[0]
|
|
504
|
+
|
|
505
|
+
# Get metadata URL if available
|
|
506
|
+
record = self.get(uri)
|
|
507
|
+
metadata_url = record.get("metadataUrl")
|
|
508
|
+
|
|
509
|
+
return Dataset[sample_type](url, metadata_url=metadata_url)
|