lamindb 0.74.3__py3-none-any.whl → 0.75.1__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.
lamindb/_collection.py CHANGED
@@ -60,7 +60,9 @@ def __init__(
60
60
  artifacts: Artifact | Iterable[Artifact] = (
61
61
  kwargs.pop("artifacts") if len(args) == 0 else args[0]
62
62
  )
63
- meta: Artifact | None = kwargs.pop("meta") if "meta" in kwargs else None
63
+ meta_artifact: Artifact | None = (
64
+ kwargs.pop("meta_artifact") if "meta_artifact" in kwargs else None
65
+ )
64
66
  name: str | None = kwargs.pop("name") if "name" in kwargs else None
65
67
  description: str | None = (
66
68
  kwargs.pop("description") if "description" in kwargs else None
@@ -102,16 +104,18 @@ def __init__(
102
104
  raise ValueError("Artifact or List[Artifact] is allowed.")
103
105
  assert isinstance(artifacts[0], Artifact) # type: ignore # noqa: S101
104
106
  hash, feature_sets = from_artifacts(artifacts) # type: ignore
105
- if meta is not None:
106
- if not isinstance(meta, Artifact):
107
- raise ValueError("meta has to be an Artifact")
108
- if isinstance(meta, Artifact):
109
- if meta._state.adding:
110
- raise ValueError("Save meta artifact before creating collection!")
107
+ if meta_artifact is not None:
108
+ if not isinstance(meta_artifact, Artifact):
109
+ raise ValueError("meta_artifact has to be an Artifact")
110
+ if isinstance(meta_artifact, Artifact):
111
+ if meta_artifact._state.adding:
112
+ raise ValueError(
113
+ "Save meta_artifact artifact before creating collection!"
114
+ )
111
115
  if not feature_sets:
112
- feature_sets = meta.features._feature_set_by_slot
116
+ feature_sets = meta_artifact.features._feature_set_by_slot
113
117
  else:
114
- if len(meta.features._feature_set_by_slot) > 0:
118
+ if len(meta_artifact.features._feature_set_by_slot) > 0:
115
119
  logger.info("overwriting feature sets linked to artifact")
116
120
  # we ignore collections in trash containing the same hash
117
121
  if hash is not None:
@@ -149,7 +153,7 @@ def __init__(
149
153
  description=description,
150
154
  reference=reference,
151
155
  reference_type=reference_type,
152
- artifact=meta,
156
+ meta_artifact=meta_artifact,
153
157
  hash=hash,
154
158
  run=run,
155
159
  version=version,
@@ -176,13 +180,13 @@ def from_artifacts(artifacts: Iterable[Artifact]) -> tuple[str, dict[str, str]]:
176
180
  artifact_ids = [artifact.id for artifact in artifacts]
177
181
  # query all feature sets at the same time rather
178
182
  # than making a single query per artifact
179
- logger.debug("feature_set_artifact_links")
180
- feature_set_artifact_links = Artifact.feature_sets.through.objects.filter(
183
+ logger.debug("links_feature_set_artifact")
184
+ links_feature_set_artifact = Artifact.feature_sets.through.objects.filter(
181
185
  artifact_id__in=artifact_ids
182
186
  )
183
187
  feature_sets_by_slots = defaultdict(list)
184
188
  logger.debug("slots")
185
- for link in feature_set_artifact_links:
189
+ for link in links_feature_set_artifact:
186
190
  feature_sets_by_slots[link.slot].append(link.featureset_id)
187
191
  feature_sets_union = {}
188
192
  logger.debug("union")
@@ -240,7 +244,7 @@ def mapped(
240
244
  is_run_input: bool | None = None,
241
245
  ) -> MappedCollection:
242
246
  path_list = []
243
- for artifact in self.artifacts.all():
247
+ for artifact in self.ordered_artifacts.all():
244
248
  if artifact.suffix not in {".h5ad", ".zarr"}:
245
249
  logger.warning(f"Ignoring artifact with suffix {artifact.suffix}")
246
250
  continue
@@ -267,10 +271,10 @@ def mapped(
267
271
 
268
272
  # docstring handled through attach_func_to_class_method
269
273
  def cache(self, is_run_input: bool | None = None) -> list[UPath]:
270
- _track_run_input(self, is_run_input)
271
274
  path_list = []
272
- for artifact in self.artifacts.all():
275
+ for artifact in self.ordered_artifacts.all():
273
276
  path_list.append(artifact.cache())
277
+ _track_run_input(self, is_run_input)
274
278
  return path_list
275
279
 
276
280
 
@@ -282,7 +286,7 @@ def load(
282
286
  **kwargs,
283
287
  ) -> Any:
284
288
  # cannot call _track_run_input here, see comment further down
285
- all_artifacts = self.artifacts.all()
289
+ all_artifacts = self.ordered_artifacts.all()
286
290
  suffixes = [artifact.suffix for artifact in all_artifacts]
287
291
  if len(set(suffixes)) != 1:
288
292
  raise RuntimeError(
@@ -329,8 +333,8 @@ def delete(self, permanent: bool | None = None) -> None:
329
333
 
330
334
  # docstring handled through attach_func_to_class_method
331
335
  def save(self, using: str | None = None) -> Collection:
332
- if self.artifact is not None:
333
- self.artifact.save()
336
+ if self.meta_artifact is not None:
337
+ self.meta_artifact.save()
334
338
  # we don't need to save feature sets again
335
339
  save_feature_sets(self)
336
340
  super(Collection, self).save()
@@ -344,7 +348,7 @@ def save(self, using: str | None = None) -> Collection:
344
348
  ]
345
349
  # the below seems to preserve the order of the list in the
346
350
  # auto-incrementing integer primary
347
- # merely using .unordered_artifacts.set(*...) doesn't achieve this
351
+ # merely using .artifacts.set(*...) doesn't achieve this
348
352
  # we need ignore_conflicts=True so that this won't error if links already exist
349
353
  CollectionArtifact.objects.bulk_create(links, ignore_conflicts=True)
350
354
  save_feature_set_links(self)
@@ -357,16 +361,20 @@ def save(self, using: str | None = None) -> Collection:
357
361
  def restore(self) -> None:
358
362
  self.visibility = VisibilityChoice.default.value
359
363
  self.save()
360
- if self.artifact is not None:
361
- self.artifact.visibility = VisibilityChoice.default.value
362
- self.artifact.save()
363
364
 
364
365
 
365
366
  @property # type: ignore
366
- @doc_args(Collection.artifacts.__doc__)
367
- def artifacts(self) -> QuerySet:
367
+ @doc_args(Collection.ordered_artifacts.__doc__)
368
+ def ordered_artifacts(self) -> QuerySet:
369
+ """{}""" # noqa: D415
370
+ return self.artifacts.order_by("links_collection__id")
371
+
372
+
373
+ @property # type: ignore
374
+ @doc_args(Collection.data_artifact.__doc__)
375
+ def data_artifact(self) -> Artifact | None:
368
376
  """{}""" # noqa: D415
369
- return self.unordered_artifacts.order_by("collection_links__id")
377
+ return self.artifacts.first()
370
378
 
371
379
 
372
380
  METHOD_NAMES = [
@@ -391,5 +399,5 @@ if ln_setup._TESTING:
391
399
  for name in METHOD_NAMES:
392
400
  attach_func_to_class_method(name, Collection, globals())
393
401
 
394
- Collection.artifacts = artifacts
395
- Collection.stage = cache
402
+ Collection.ordered_artifacts = ordered_artifacts
403
+ Collection.data_artifact = data_artifact