lamindb 1.3.2__py3-none-any.whl → 1.5.0__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/__init__.py +52 -36
- lamindb/_finish.py +17 -10
- lamindb/_tracked.py +1 -1
- lamindb/base/__init__.py +3 -1
- lamindb/base/fields.py +40 -22
- lamindb/base/ids.py +1 -94
- lamindb/base/types.py +2 -0
- lamindb/base/uids.py +117 -0
- lamindb/core/_context.py +216 -133
- lamindb/core/_settings.py +38 -25
- lamindb/core/datasets/__init__.py +11 -4
- lamindb/core/datasets/_core.py +5 -5
- lamindb/core/datasets/_small.py +0 -93
- lamindb/core/datasets/mini_immuno.py +172 -0
- lamindb/core/loaders.py +1 -1
- lamindb/core/storage/_backed_access.py +100 -6
- lamindb/core/storage/_polars_lazy_df.py +51 -0
- lamindb/core/storage/_pyarrow_dataset.py +15 -30
- lamindb/core/storage/objects.py +6 -0
- lamindb/core/subsettings/__init__.py +2 -0
- lamindb/core/subsettings/_annotation_settings.py +11 -0
- lamindb/curators/__init__.py +7 -3559
- lamindb/curators/_legacy.py +2056 -0
- lamindb/curators/core.py +1546 -0
- lamindb/errors.py +11 -0
- lamindb/examples/__init__.py +27 -0
- lamindb/examples/schemas/__init__.py +12 -0
- lamindb/examples/schemas/_anndata.py +25 -0
- lamindb/examples/schemas/_simple.py +19 -0
- lamindb/integrations/_vitessce.py +8 -5
- lamindb/migrations/0091_alter_featurevalue_options_alter_space_options_and_more.py +24 -0
- lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py +75 -0
- lamindb/models/__init__.py +12 -2
- lamindb/models/_describe.py +21 -4
- lamindb/models/_feature_manager.py +384 -301
- lamindb/models/_from_values.py +1 -1
- lamindb/models/_is_versioned.py +5 -15
- lamindb/models/_label_manager.py +8 -2
- lamindb/models/artifact.py +354 -177
- lamindb/models/artifact_set.py +122 -0
- lamindb/models/can_curate.py +4 -1
- lamindb/models/collection.py +79 -56
- lamindb/models/core.py +1 -1
- lamindb/models/feature.py +78 -47
- lamindb/models/has_parents.py +24 -9
- lamindb/models/project.py +3 -3
- lamindb/models/query_manager.py +221 -22
- lamindb/models/query_set.py +251 -206
- lamindb/models/record.py +211 -344
- lamindb/models/run.py +59 -5
- lamindb/models/save.py +9 -5
- lamindb/models/schema.py +673 -196
- lamindb/models/transform.py +5 -14
- lamindb/models/ulabel.py +8 -5
- {lamindb-1.3.2.dist-info → lamindb-1.5.0.dist-info}/METADATA +8 -7
- lamindb-1.5.0.dist-info/RECORD +108 -0
- lamindb-1.3.2.dist-info/RECORD +0 -95
- {lamindb-1.3.2.dist-info → lamindb-1.5.0.dist-info}/LICENSE +0 -0
- {lamindb-1.3.2.dist-info → lamindb-1.5.0.dist-info}/WHEEL +0 -0
lamindb/models/run.py
CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import TYPE_CHECKING, Any, overload
|
4
4
|
|
5
|
+
import numpy as np
|
5
6
|
from django.db import models
|
6
7
|
from django.db.models import (
|
7
8
|
CASCADE,
|
@@ -19,7 +20,7 @@ from lamindb.base.fields import (
|
|
19
20
|
ForeignKey,
|
20
21
|
)
|
21
22
|
from lamindb.base.users import current_user_id
|
22
|
-
from lamindb.errors import ValidationError
|
23
|
+
from lamindb.errors import InvalidArgument, ValidationError
|
23
24
|
|
24
25
|
from ..base.ids import base62_20
|
25
26
|
from .can_curate import CanCurate
|
@@ -33,6 +34,7 @@ if TYPE_CHECKING:
|
|
33
34
|
from .artifact import Artifact
|
34
35
|
from .collection import Collection
|
35
36
|
from .project import Project
|
37
|
+
from .query_set import QuerySet
|
36
38
|
from .schema import Schema
|
37
39
|
from .transform import Transform
|
38
40
|
from .ulabel import ULabel
|
@@ -345,7 +347,7 @@ class ParamValue(Record):
|
|
345
347
|
|
346
348
|
|
347
349
|
class Run(Record):
|
348
|
-
"""Runs.
|
350
|
+
"""Runs of transforms such as the execution of a script.
|
349
351
|
|
350
352
|
A registry to store runs of transforms, such as an executation of a script.
|
351
353
|
|
@@ -538,6 +540,56 @@ class Run(Record):
|
|
538
540
|
delete_run_artifacts(self)
|
539
541
|
super().delete()
|
540
542
|
|
543
|
+
@classmethod
|
544
|
+
def filter(
|
545
|
+
cls,
|
546
|
+
*queries,
|
547
|
+
**expressions,
|
548
|
+
) -> QuerySet:
|
549
|
+
"""Query a set of artifacts.
|
550
|
+
|
551
|
+
Args:
|
552
|
+
*queries: `Q` expressions.
|
553
|
+
**expressions: Params, fields, and values passed via the Django query syntax.
|
554
|
+
|
555
|
+
See Also:
|
556
|
+
- Guide: :doc:`docs:registries`
|
557
|
+
|
558
|
+
Examples:
|
559
|
+
|
560
|
+
Query by fields::
|
561
|
+
|
562
|
+
ln.Run.filter(key="examples/my_file.parquet")
|
563
|
+
|
564
|
+
Query by params::
|
565
|
+
|
566
|
+
ln.Run.filter(hyperparam_x=100)
|
567
|
+
"""
|
568
|
+
from ._feature_manager import filter_base
|
569
|
+
from .query_set import QuerySet
|
570
|
+
|
571
|
+
if expressions:
|
572
|
+
keys_normalized = [key.split("__")[0] for key in expressions]
|
573
|
+
field_or_feature_or_param = keys_normalized[0].split("__")[0]
|
574
|
+
if field_or_feature_or_param in Run.__get_available_fields__():
|
575
|
+
return QuerySet(model=cls).filter(*queries, **expressions)
|
576
|
+
elif all(
|
577
|
+
params_validated := Param.validate(
|
578
|
+
keys_normalized, field="name", mute=True
|
579
|
+
)
|
580
|
+
):
|
581
|
+
return filter_base(ParamManagerRun, **expressions)
|
582
|
+
else:
|
583
|
+
params = ", ".join(sorted(np.array(keys_normalized)[~params_validated]))
|
584
|
+
message = f"param names: {params}"
|
585
|
+
fields = ", ".join(sorted(cls.__get_available_fields__()))
|
586
|
+
raise InvalidArgument(
|
587
|
+
f"You can query either by available fields: {fields}\n"
|
588
|
+
f"Or fix invalid {message}"
|
589
|
+
)
|
590
|
+
else:
|
591
|
+
return QuerySet(model=cls).filter(*queries, **expressions)
|
592
|
+
|
541
593
|
|
542
594
|
def delete_run_artifacts(run: Run) -> None:
|
543
595
|
environment = None
|
@@ -555,14 +607,16 @@ def delete_run_artifacts(run: Run) -> None:
|
|
555
607
|
if environment._environment_of.count() == 0:
|
556
608
|
environment.delete(permanent=True)
|
557
609
|
if report is not None:
|
558
|
-
|
610
|
+
# only delete if there are no other runs attached to this environment
|
611
|
+
if report._report_of.count() == 0:
|
612
|
+
report.delete(permanent=True)
|
559
613
|
|
560
614
|
|
561
615
|
class RunParamValue(BasicRecord, LinkORM):
|
562
616
|
id: int = models.BigAutoField(primary_key=True)
|
563
|
-
run: Run = ForeignKey(Run, CASCADE, related_name="
|
617
|
+
run: Run = ForeignKey(Run, CASCADE, related_name="links_paramvalue")
|
564
618
|
# we follow the lower() case convention rather than snake case for link models
|
565
|
-
paramvalue: ParamValue = ForeignKey(ParamValue, PROTECT, related_name="
|
619
|
+
paramvalue: ParamValue = ForeignKey(ParamValue, PROTECT, related_name="links_run")
|
566
620
|
created_at: datetime = DateTimeField(
|
567
621
|
editable=False, db_default=models.functions.Now(), db_index=True
|
568
622
|
)
|
lamindb/models/save.py
CHANGED
@@ -30,7 +30,7 @@ if TYPE_CHECKING:
|
|
30
30
|
|
31
31
|
|
32
32
|
def save(records: Iterable[Record], ignore_conflicts: bool | None = False) -> None:
|
33
|
-
"""Bulk save
|
33
|
+
"""Bulk save records.
|
34
34
|
|
35
35
|
Note:
|
36
36
|
|
@@ -157,7 +157,13 @@ def check_and_attempt_upload(
|
|
157
157
|
return exception
|
158
158
|
# copies (if on-disk) or moves the temporary file (if in-memory) to the cache
|
159
159
|
if os.getenv("LAMINDB_MULTI_INSTANCE") is None:
|
160
|
-
|
160
|
+
# this happens only after the actual upload was performed
|
161
|
+
# we avoid failing here in case any problems happen in copy_or_move_to_cache
|
162
|
+
# because the cache copying or cleanup is not absolutely necessary
|
163
|
+
try:
|
164
|
+
copy_or_move_to_cache(artifact, storage_path, cache_path)
|
165
|
+
except Exception as e:
|
166
|
+
logger.warning(f"A problem with cache on saving: {e}")
|
161
167
|
# after successful upload, we should remove the attribute so that another call
|
162
168
|
# call to save won't upload again, the user should call replace() then
|
163
169
|
del artifact._local_filepath
|
@@ -192,9 +198,7 @@ def copy_or_move_to_cache(
|
|
192
198
|
# non-local storage_path further
|
193
199
|
if local_path != cache_path:
|
194
200
|
if cache_path.exists():
|
195
|
-
logger.warning(
|
196
|
-
f"The cache path {cache_path.as_posix()} already exists, replacing it."
|
197
|
-
)
|
201
|
+
logger.warning(f"replacing the existing cache path {cache_path.as_posix()}")
|
198
202
|
if cache_path.is_dir():
|
199
203
|
shutil.rmtree(cache_path)
|
200
204
|
else:
|