lamindb 1.1.1__py3-none-any.whl → 1.2.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 +30 -25
- lamindb/_tracked.py +1 -1
- lamindb/_view.py +2 -3
- lamindb/base/__init__.py +1 -1
- lamindb/base/ids.py +1 -10
- lamindb/core/__init__.py +7 -65
- lamindb/core/_compat.py +60 -0
- lamindb/core/_context.py +43 -20
- lamindb/core/_settings.py +6 -6
- lamindb/core/_sync_git.py +1 -1
- lamindb/core/loaders.py +30 -19
- lamindb/core/storage/_backed_access.py +4 -2
- lamindb/core/storage/_tiledbsoma.py +8 -6
- lamindb/core/storage/_zarr.py +104 -25
- lamindb/core/storage/objects.py +63 -28
- lamindb/core/storage/paths.py +4 -1
- lamindb/core/types.py +10 -0
- lamindb/curators/__init__.py +100 -85
- lamindb/errors.py +1 -1
- lamindb/integrations/_vitessce.py +4 -4
- lamindb/migrations/0089_subsequent_runs.py +159 -0
- lamindb/migrations/0090_runproject_project_runs.py +73 -0
- lamindb/migrations/{0088_squashed.py → 0090_squashed.py} +245 -177
- lamindb/models/__init__.py +79 -0
- lamindb/{core → models}/_describe.py +3 -3
- lamindb/{core → models}/_django.py +8 -5
- lamindb/{core → models}/_feature_manager.py +103 -87
- lamindb/{_from_values.py → models/_from_values.py} +5 -2
- lamindb/{core/versioning.py → models/_is_versioned.py} +94 -6
- lamindb/{core → models}/_label_manager.py +10 -17
- lamindb/{core/relations.py → models/_relations.py} +8 -1
- lamindb/models/artifact.py +2602 -0
- lamindb/{_can_curate.py → models/can_curate.py} +349 -180
- lamindb/models/collection.py +683 -0
- lamindb/models/core.py +135 -0
- lamindb/models/feature.py +643 -0
- lamindb/models/flextable.py +163 -0
- lamindb/{_parents.py → models/has_parents.py} +55 -49
- lamindb/models/project.py +384 -0
- lamindb/{_query_manager.py → models/query_manager.py} +10 -8
- lamindb/{_query_set.py → models/query_set.py} +40 -26
- lamindb/models/record.py +1762 -0
- lamindb/models/run.py +563 -0
- lamindb/{_save.py → models/save.py} +9 -7
- lamindb/models/schema.py +732 -0
- lamindb/models/transform.py +360 -0
- lamindb/models/ulabel.py +249 -0
- {lamindb-1.1.1.dist-info → lamindb-1.2.0.dist-info}/METADATA +6 -6
- {lamindb-1.1.1.dist-info → lamindb-1.2.0.dist-info}/RECORD +51 -51
- lamindb/_artifact.py +0 -1379
- lamindb/_collection.py +0 -440
- lamindb/_feature.py +0 -316
- lamindb/_is_versioned.py +0 -40
- lamindb/_record.py +0 -1064
- lamindb/_run.py +0 -60
- lamindb/_schema.py +0 -347
- lamindb/_storage.py +0 -15
- lamindb/_transform.py +0 -170
- lamindb/_ulabel.py +0 -56
- lamindb/_utils.py +0 -9
- lamindb/base/validation.py +0 -63
- lamindb/core/_data.py +0 -491
- lamindb/core/fields.py +0 -12
- lamindb/models.py +0 -4475
- {lamindb-1.1.1.dist-info → lamindb-1.2.0.dist-info}/LICENSE +0 -0
- {lamindb-1.1.1.dist-info → lamindb-1.2.0.dist-info}/WHEEL +0 -0
@@ -1,15 +1,104 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from typing import TYPE_CHECKING, Literal
|
3
|
+
from typing import TYPE_CHECKING, Literal, overload
|
4
4
|
|
5
|
+
from django.db import models
|
5
6
|
from lamin_utils import logger
|
6
7
|
from lamin_utils._base62 import increment_base62
|
7
8
|
from lamindb_setup.core.upath import LocalPathClasses, UPath
|
8
9
|
|
9
10
|
from lamindb.base import ids
|
11
|
+
from lamindb.base.fields import (
|
12
|
+
BooleanField,
|
13
|
+
CharField,
|
14
|
+
)
|
10
15
|
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from lamindb.models import
|
16
|
+
if TYPE_CHECKING: # noqa
|
17
|
+
from lamindb.models.query_set import QuerySet
|
18
|
+
|
19
|
+
|
20
|
+
class IsVersioned(models.Model):
|
21
|
+
"""Base class for versioned models."""
|
22
|
+
|
23
|
+
class Meta:
|
24
|
+
abstract = True
|
25
|
+
|
26
|
+
_len_stem_uid: int
|
27
|
+
|
28
|
+
version: str | None = CharField(max_length=30, null=True, db_index=True)
|
29
|
+
"""Version (default `None`).
|
30
|
+
|
31
|
+
Defines version of a family of records characterized by the same `stem_uid`.
|
32
|
+
|
33
|
+
Consider using `semantic versioning <https://semver.org>`__
|
34
|
+
with `Python versioning <https://peps.python.org/pep-0440/>`__.
|
35
|
+
"""
|
36
|
+
is_latest: bool = BooleanField(default=True, db_index=True)
|
37
|
+
"""Boolean flag that indicates whether a record is the latest in its version family."""
|
38
|
+
|
39
|
+
@overload
|
40
|
+
def __init__(self): ...
|
41
|
+
|
42
|
+
@overload
|
43
|
+
def __init__(
|
44
|
+
self,
|
45
|
+
*db_args,
|
46
|
+
): ...
|
47
|
+
|
48
|
+
def __init__(
|
49
|
+
self,
|
50
|
+
*args,
|
51
|
+
**kwargs,
|
52
|
+
):
|
53
|
+
self._revises = kwargs.pop("revises") if "revises" in kwargs else None
|
54
|
+
super().__init__(*args, **kwargs)
|
55
|
+
|
56
|
+
@property
|
57
|
+
def stem_uid(self) -> str:
|
58
|
+
"""Universal id characterizing the version family.
|
59
|
+
|
60
|
+
The full uid of a record is obtained via concatenating the stem uid and version information::
|
61
|
+
|
62
|
+
stem_uid = random_base62(n_char) # a random base62 sequence of length 12 (transform) or 16 (artifact, collection)
|
63
|
+
version_uid = "0000" # an auto-incrementing 4-digit base62 number
|
64
|
+
uid = f"{stem_uid}{version_uid}" # concatenate the stem_uid & version_uid
|
65
|
+
|
66
|
+
"""
|
67
|
+
return self.uid[: self._len_stem_uid] # type: ignore
|
68
|
+
|
69
|
+
@property
|
70
|
+
def versions(self) -> QuerySet:
|
71
|
+
"""Lists all records of the same version family.
|
72
|
+
|
73
|
+
>>> new_artifact = ln.Artifact(df2, revises=artifact).save()
|
74
|
+
>>> new_artifact.versions()
|
75
|
+
"""
|
76
|
+
db = self._state.db
|
77
|
+
if db is not None and db != "default":
|
78
|
+
return self.__class__.using(db).filter(uid__startswith=self.stem_uid) # type: ignore
|
79
|
+
else:
|
80
|
+
return self.__class__.filter(uid__startswith=self.stem_uid) # type: ignore
|
81
|
+
|
82
|
+
def _add_to_version_family(self, revises: IsVersioned, version: str | None = None):
|
83
|
+
"""Add current record to a version family.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
revises: a record that belongs to the version family.
|
87
|
+
version: semantic version of the record.
|
88
|
+
"""
|
89
|
+
old_uid = self.uid # type: ignore
|
90
|
+
new_uid, revises = create_uid(revises=revises, version=version)
|
91
|
+
if self.__class__.__name__ == "Artifact" and self._key_is_virtual:
|
92
|
+
old_path = self.path
|
93
|
+
new_path = get_new_path_from_uid(
|
94
|
+
old_path=old_path, old_uid=old_uid, new_uid=new_uid
|
95
|
+
)
|
96
|
+
new_path = UPath(old_path).rename(new_path)
|
97
|
+
logger.success(f"updated path from {old_path} to {new_path}!")
|
98
|
+
self.uid = new_uid
|
99
|
+
self.version = version
|
100
|
+
self.save()
|
101
|
+
logger.success(f"updated uid from {old_uid} to {new_uid}!")
|
13
102
|
|
14
103
|
|
15
104
|
def message_update_key_in_version_family(
|
@@ -102,15 +191,14 @@ def create_uid(
|
|
102
191
|
f"didn't pass the latest version in `revises`, retrieved it: {revises}"
|
103
192
|
)
|
104
193
|
suid = revises.stem_uid
|
105
|
-
vuid = increment_base62(revises.uid[-4:])
|
194
|
+
vuid = increment_base62(revises.uid[-4:]) # type: ignore
|
106
195
|
else:
|
107
196
|
suid = ids.base62(n_full_id - 4)
|
108
197
|
vuid = "0000"
|
109
198
|
if version is not None:
|
110
199
|
if not isinstance(version, str):
|
111
200
|
raise ValueError(
|
112
|
-
"`version` parameter must be `None` or `str`, e.g., '0.1', '1', '2',"
|
113
|
-
" etc."
|
201
|
+
"`version` parameter must be `None` or `str`, e.g., '0.1', '1', '2', etc."
|
114
202
|
)
|
115
203
|
if revises is not None:
|
116
204
|
if version == revises.version:
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import warnings
|
4
3
|
from collections import defaultdict
|
5
4
|
from typing import TYPE_CHECKING
|
6
5
|
|
@@ -10,15 +9,15 @@ from rich.table import Column, Table
|
|
10
9
|
from rich.text import Text
|
11
10
|
from rich.tree import Tree
|
12
11
|
|
13
|
-
from lamindb.
|
14
|
-
from lamindb.
|
12
|
+
from lamindb.models import CanCurate, Feature
|
13
|
+
from lamindb.models._from_values import _format_values
|
14
|
+
from lamindb.models.record import (
|
15
15
|
REGISTRY_UNIQUE_FIELD,
|
16
16
|
get_name_field,
|
17
17
|
transfer_fk_to_default_db_bulk,
|
18
18
|
transfer_to_default_db,
|
19
19
|
)
|
20
|
-
from lamindb.
|
21
|
-
from lamindb.models import CanCurate, Feature
|
20
|
+
from lamindb.models.save import save
|
22
21
|
|
23
22
|
from ._describe import (
|
24
23
|
NAME_WIDTH,
|
@@ -28,12 +27,11 @@ from ._describe import (
|
|
28
27
|
print_rich_tree,
|
29
28
|
)
|
30
29
|
from ._django import get_artifact_with_related, get_related_model
|
31
|
-
from .
|
32
|
-
from .relations import dict_related_model_to_related_name
|
30
|
+
from ._relations import dict_related_model_to_related_name
|
33
31
|
|
34
32
|
if TYPE_CHECKING:
|
35
|
-
from lamindb._query_set import QuerySet
|
36
33
|
from lamindb.models import Artifact, Collection, Record
|
34
|
+
from lamindb.models.query_set import QuerySet
|
37
35
|
|
38
36
|
EXCLUDE_LABELS = {"feature_sets"}
|
39
37
|
|
@@ -75,17 +73,10 @@ def _get_labels_postgres(
|
|
75
73
|
def describe_labels(
|
76
74
|
self: Artifact | Collection,
|
77
75
|
labels_data: dict | None = None,
|
78
|
-
print_types: bool = False, # deprecated
|
79
76
|
tree: Tree | None = None,
|
80
77
|
as_subtree: bool = False,
|
81
78
|
):
|
82
79
|
"""Describe labels associated with an artifact or collection."""
|
83
|
-
if print_types:
|
84
|
-
warnings.warn(
|
85
|
-
"`print_types` parameter is deprecated and will be removed in a future version. Types are now always printed.",
|
86
|
-
DeprecationWarning,
|
87
|
-
stacklevel=2,
|
88
|
-
)
|
89
80
|
if not self._state.adding and connections[self._state.db].vendor == "postgresql":
|
90
81
|
labels_data = _get_labels_postgres(self, labels_data)
|
91
82
|
if not labels_data:
|
@@ -205,7 +196,7 @@ class LabelManager:
|
|
205
196
|
records: Label records to add.
|
206
197
|
feature: Feature under which to group the labels.
|
207
198
|
"""
|
208
|
-
from .
|
199
|
+
from .artifact import add_labels
|
209
200
|
|
210
201
|
return add_labels(self._host, records=records, feature=feature)
|
211
202
|
|
@@ -222,7 +213,7 @@ class LabelManager:
|
|
222
213
|
mute: Show no logging.
|
223
214
|
flat_names: Flatten list to names rather than returning records.
|
224
215
|
"""
|
225
|
-
from .
|
216
|
+
from .artifact import get_labels
|
226
217
|
|
227
218
|
return get_labels(self._host, feature=feature, mute=mute, flat_names=flat_names)
|
228
219
|
|
@@ -240,6 +231,8 @@ class LabelManager:
|
|
240
231
|
"""
|
241
232
|
if transfer_logs is None:
|
242
233
|
transfer_logs = {"mapped": [], "transferred": [], "run": None}
|
234
|
+
from lamindb import settings
|
235
|
+
|
243
236
|
using_key = settings._using_key
|
244
237
|
for related_name, labels in _get_labels(data, instance=data._state.db).items():
|
245
238
|
labels = labels.all()
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
3
5
|
import lamindb_setup as ln_setup
|
4
6
|
from django.db.models import ManyToManyField
|
5
7
|
from lamindb_setup._connect_instance import (
|
@@ -8,7 +10,10 @@ from lamindb_setup._connect_instance import (
|
|
8
10
|
)
|
9
11
|
from lamindb_setup.core._settings_store import instance_settings_file
|
10
12
|
|
11
|
-
from lamindb.models import LinkORM
|
13
|
+
from lamindb.models.record import LinkORM
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from lamindb.models.record import Record, Registry
|
12
17
|
|
13
18
|
|
14
19
|
def get_schema_modules(instance: str | None) -> set[str]:
|
@@ -84,6 +89,8 @@ def dict_related_model_to_related_name(
|
|
84
89
|
|
85
90
|
|
86
91
|
def get_related_name(features_type: type[Record]) -> str:
|
92
|
+
from lamindb.models.schema import Schema
|
93
|
+
|
87
94
|
candidates = [
|
88
95
|
field.related_name
|
89
96
|
for field in Schema._meta.related_objects
|