lamindb 1.10.1__py3-none-any.whl → 1.11.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.
Files changed (55) hide show
  1. lamindb/__init__.py +89 -49
  2. lamindb/_finish.py +17 -15
  3. lamindb/_tracked.py +2 -4
  4. lamindb/_view.py +1 -1
  5. lamindb/base/__init__.py +2 -1
  6. lamindb/base/dtypes.py +76 -0
  7. lamindb/core/_settings.py +45 -2
  8. lamindb/core/storage/_anndata_accessor.py +118 -26
  9. lamindb/core/storage/_backed_access.py +10 -7
  10. lamindb/core/storage/_spatialdata_accessor.py +15 -4
  11. lamindb/core/storage/_zarr.py +3 -0
  12. lamindb/curators/_legacy.py +16 -3
  13. lamindb/curators/core.py +449 -193
  14. lamindb/errors.py +6 -0
  15. lamindb/examples/cellxgene/__init__.py +8 -3
  16. lamindb/examples/cellxgene/_cellxgene.py +127 -13
  17. lamindb/examples/cellxgene/{cxg_schema_versions.csv → cellxgene_schema_versions.csv} +11 -0
  18. lamindb/examples/croissant/__init__.py +32 -6
  19. lamindb/examples/datasets/__init__.py +2 -2
  20. lamindb/examples/datasets/_core.py +9 -2
  21. lamindb/examples/datasets/_small.py +66 -22
  22. lamindb/examples/fixtures/sheets.py +8 -2
  23. lamindb/integrations/_croissant.py +34 -11
  24. lamindb/migrations/0118_alter_recordproject_value_projectrecord.py +99 -0
  25. lamindb/migrations/0119_rename_records_project_linked_in_records.py +26 -0
  26. lamindb/migrations/{0117_squashed.py → 0119_squashed.py} +92 -5
  27. lamindb/migrations/0120_add_record_fk_constraint.py +64 -0
  28. lamindb/migrations/0121_recorduser.py +60 -0
  29. lamindb/models/__init__.py +4 -1
  30. lamindb/models/_describe.py +2 -2
  31. lamindb/models/_feature_manager.py +131 -71
  32. lamindb/models/_from_values.py +2 -2
  33. lamindb/models/_is_versioned.py +4 -4
  34. lamindb/models/_label_manager.py +4 -4
  35. lamindb/models/artifact.py +357 -192
  36. lamindb/models/artifact_set.py +45 -1
  37. lamindb/models/can_curate.py +1 -2
  38. lamindb/models/collection.py +3 -34
  39. lamindb/models/feature.py +111 -7
  40. lamindb/models/has_parents.py +11 -11
  41. lamindb/models/project.py +42 -2
  42. lamindb/models/query_manager.py +16 -7
  43. lamindb/models/query_set.py +191 -78
  44. lamindb/models/record.py +30 -5
  45. lamindb/models/run.py +10 -33
  46. lamindb/models/save.py +6 -8
  47. lamindb/models/schema.py +54 -26
  48. lamindb/models/sqlrecord.py +152 -40
  49. lamindb/models/storage.py +59 -14
  50. lamindb/models/transform.py +17 -17
  51. lamindb/models/ulabel.py +6 -1
  52. {lamindb-1.10.1.dist-info → lamindb-1.11.0.dist-info}/METADATA +11 -16
  53. {lamindb-1.10.1.dist-info → lamindb-1.11.0.dist-info}/RECORD +55 -50
  54. {lamindb-1.10.1.dist-info → lamindb-1.11.0.dist-info}/LICENSE +0 -0
  55. {lamindb-1.10.1.dist-info → lamindb-1.11.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,99 @@
1
+ # Generated by Django 5.2 on 2025-08-07 15:28
2
+
3
+ import django.db.models.deletion
4
+ import django.db.models.functions.datetime
5
+ from django.db import migrations, models
6
+
7
+ import lamindb.base.fields
8
+ import lamindb.base.users
9
+ import lamindb.models.run
10
+ import lamindb.models.sqlrecord
11
+
12
+
13
+ class Migration(migrations.Migration):
14
+ dependencies = [
15
+ ("lamindb", "0117_fix_artifact_storage_hash_unique_constraints"),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.AlterField(
20
+ model_name="recordproject",
21
+ name="value",
22
+ field=lamindb.base.fields.ForeignKey(
23
+ blank=True,
24
+ on_delete=django.db.models.deletion.PROTECT,
25
+ related_name="links_in_record",
26
+ to="lamindb.project",
27
+ ),
28
+ ),
29
+ migrations.CreateModel(
30
+ name="ProjectRecord",
31
+ fields=[
32
+ (
33
+ "created_at",
34
+ lamindb.base.fields.DateTimeField(
35
+ blank=True,
36
+ db_default=django.db.models.functions.datetime.Now(),
37
+ db_index=True,
38
+ editable=False,
39
+ ),
40
+ ),
41
+ ("id", models.BigAutoField(primary_key=True, serialize=False)),
42
+ (
43
+ "created_by",
44
+ lamindb.base.fields.ForeignKey(
45
+ blank=True,
46
+ default=lamindb.base.users.current_user_id,
47
+ editable=False,
48
+ on_delete=django.db.models.deletion.PROTECT,
49
+ related_name="+",
50
+ to="lamindb.user",
51
+ ),
52
+ ),
53
+ (
54
+ "feature",
55
+ lamindb.base.fields.ForeignKey(
56
+ blank=True,
57
+ default=None,
58
+ null=True,
59
+ on_delete=django.db.models.deletion.PROTECT,
60
+ related_name="links_projectrecord",
61
+ to="lamindb.feature",
62
+ ),
63
+ ),
64
+ (
65
+ "project",
66
+ lamindb.base.fields.ForeignKey(
67
+ blank=True,
68
+ on_delete=django.db.models.deletion.PROTECT,
69
+ related_name="links_record",
70
+ to="lamindb.project",
71
+ ),
72
+ ),
73
+ (
74
+ "record",
75
+ lamindb.base.fields.ForeignKey(
76
+ blank=True,
77
+ on_delete=django.db.models.deletion.CASCADE,
78
+ related_name="links_project",
79
+ to="lamindb.record",
80
+ ),
81
+ ),
82
+ (
83
+ "run",
84
+ lamindb.base.fields.ForeignKey(
85
+ blank=True,
86
+ default=lamindb.models.run.current_run,
87
+ null=True,
88
+ on_delete=django.db.models.deletion.PROTECT,
89
+ related_name="+",
90
+ to="lamindb.run",
91
+ ),
92
+ ),
93
+ ],
94
+ options={
95
+ "unique_together": {("record", "project", "feature")},
96
+ },
97
+ bases=(lamindb.models.sqlrecord.IsLink, models.Model),
98
+ ),
99
+ ]
@@ -0,0 +1,26 @@
1
+ # Generated by Django 5.2 on 2025-08-09 13:31
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("lamindb", "0118_alter_recordproject_value_projectrecord"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.RenameField(
13
+ model_name="project",
14
+ old_name="records",
15
+ new_name="linked_in_records",
16
+ ),
17
+ migrations.AddField(
18
+ model_name="project",
19
+ name="records",
20
+ field=models.ManyToManyField(
21
+ related_name="projects",
22
+ through="lamindb.ProjectRecord",
23
+ to="lamindb.record",
24
+ ),
25
+ ),
26
+ ]
@@ -1,4 +1,4 @@
1
- # Generated by Django 5.2 on 2025-07-26 18:58
1
+ # Generated by Django 5.2 on 2025-08-09 13:33
2
2
 
3
3
  import django.core.validators
4
4
  import django.db.models.deletion
@@ -139,6 +139,8 @@ class Migration(migrations.Migration):
139
139
  ("lamindb", "0115_alter_space_uid"),
140
140
  ("lamindb", "0116_remove_artifact_unique_artifact_storage_key_hash_and_more"),
141
141
  ("lamindb", "0117_fix_artifact_storage_hash_unique_constraints"),
142
+ ("lamindb", "0118_alter_recordproject_value_projectrecord"),
143
+ ("lamindb", "0119_rename_records_project_linked_in_records"),
142
144
  ]
143
145
 
144
146
  dependencies = [] # type: ignore
@@ -217,9 +219,8 @@ class Migration(migrations.Migration):
217
219
  "uid",
218
220
  lamindb.base.fields.CharField(
219
221
  blank=True,
220
- db_default="aaaaaaaaaaaa",
221
222
  db_index=True,
222
- default="aaaaaaaaaaaaa",
223
+ default=lamindb.base.uids.base62_12,
223
224
  editable=False,
224
225
  max_length=12,
225
226
  unique=True,
@@ -1522,6 +1523,60 @@ class Migration(migrations.Migration):
1522
1523
  },
1523
1524
  bases=(lamindb.models.can_curate.CanCurate, models.Model),
1524
1525
  ),
1526
+ migrations.CreateModel(
1527
+ name="ProjectRecord",
1528
+ fields=[
1529
+ (
1530
+ "created_at",
1531
+ lamindb.base.fields.DateTimeField(
1532
+ blank=True,
1533
+ db_default=django.db.models.functions.datetime.Now(),
1534
+ db_index=True,
1535
+ editable=False,
1536
+ ),
1537
+ ),
1538
+ ("id", models.BigAutoField(primary_key=True, serialize=False)),
1539
+ (
1540
+ "feature",
1541
+ lamindb.base.fields.ForeignKey(
1542
+ blank=True,
1543
+ default=None,
1544
+ null=True,
1545
+ on_delete=django.db.models.deletion.PROTECT,
1546
+ related_name="links_projectrecord",
1547
+ to="lamindb.feature",
1548
+ ),
1549
+ ),
1550
+ (
1551
+ "project",
1552
+ lamindb.base.fields.ForeignKey(
1553
+ blank=True,
1554
+ on_delete=django.db.models.deletion.PROTECT,
1555
+ related_name="links_record",
1556
+ to="lamindb.project",
1557
+ ),
1558
+ ),
1559
+ (
1560
+ "record",
1561
+ lamindb.base.fields.ForeignKey(
1562
+ blank=True,
1563
+ on_delete=django.db.models.deletion.CASCADE,
1564
+ related_name="links_project",
1565
+ to="lamindb.record",
1566
+ ),
1567
+ ),
1568
+ ],
1569
+ bases=(lamindb.models.sqlrecord.IsLink, models.Model),
1570
+ ),
1571
+ migrations.AddField(
1572
+ model_name="project",
1573
+ name="records",
1574
+ field=models.ManyToManyField(
1575
+ related_name="projects",
1576
+ through="lamindb.ProjectRecord",
1577
+ to="lamindb.record",
1578
+ ),
1579
+ ),
1525
1580
  migrations.AddField(
1526
1581
  model_name="artifactrecord",
1527
1582
  name="record",
@@ -1651,7 +1706,7 @@ class Migration(migrations.Migration):
1651
1706
  lamindb.base.fields.ForeignKey(
1652
1707
  blank=True,
1653
1708
  on_delete=django.db.models.deletion.PROTECT,
1654
- related_name="links_record",
1709
+ related_name="links_in_record",
1655
1710
  to="lamindb.project",
1656
1711
  ),
1657
1712
  ),
@@ -1663,7 +1718,7 @@ class Migration(migrations.Migration):
1663
1718
  ),
1664
1719
  migrations.AddField(
1665
1720
  model_name="project",
1666
- name="records",
1721
+ name="linked_in_records",
1667
1722
  field=models.ManyToManyField(
1668
1723
  related_name="linked_projects",
1669
1724
  through="lamindb.RecordProject",
@@ -2198,6 +2253,18 @@ class Migration(migrations.Migration):
2198
2253
  to="lamindb.run",
2199
2254
  ),
2200
2255
  ),
2256
+ migrations.AddField(
2257
+ model_name="projectrecord",
2258
+ name="run",
2259
+ field=lamindb.base.fields.ForeignKey(
2260
+ blank=True,
2261
+ default=lamindb.models.run.current_run,
2262
+ null=True,
2263
+ on_delete=django.db.models.deletion.PROTECT,
2264
+ related_name="+",
2265
+ to="lamindb.run",
2266
+ ),
2267
+ ),
2201
2268
  migrations.AddField(
2202
2269
  model_name="project",
2203
2270
  name="run",
@@ -4174,6 +4241,18 @@ class Migration(migrations.Migration):
4174
4241
  to="lamindb.user",
4175
4242
  ),
4176
4243
  ),
4244
+ migrations.AddField(
4245
+ model_name="projectrecord",
4246
+ name="created_by",
4247
+ field=lamindb.base.fields.ForeignKey(
4248
+ blank=True,
4249
+ default=lamindb.base.users.current_user_id,
4250
+ editable=False,
4251
+ on_delete=django.db.models.deletion.PROTECT,
4252
+ related_name="+",
4253
+ to="lamindb.user",
4254
+ ),
4255
+ ),
4177
4256
  migrations.AddField(
4178
4257
  model_name="project",
4179
4258
  name="created_by",
@@ -4427,6 +4506,10 @@ class Migration(migrations.Migration):
4427
4506
  name="runfeaturevalue",
4428
4507
  unique_together={("run", "featurevalue")},
4429
4508
  ),
4509
+ migrations.AlterUniqueTogether(
4510
+ name="projectrecord",
4511
+ unique_together={("record", "project", "feature")},
4512
+ ),
4430
4513
  migrations.AlterUniqueTogether(
4431
4514
  name="personproject",
4432
4515
  unique_together={("person", "project")},
@@ -4498,4 +4581,8 @@ class Migration(migrations.Migration):
4498
4581
  name="unique_artifact_storage_hash_null_key",
4499
4582
  ),
4500
4583
  ),
4584
+ migrations.AlterModelOptions(
4585
+ name="user",
4586
+ options={},
4587
+ ),
4501
4588
  ]
@@ -0,0 +1,64 @@
1
+ # Generated by Django 5.2 on 2025-08-07 18:52
2
+
3
+ from django.db import migrations
4
+
5
+ CREATE_FUNCTION_SQL = """
6
+ CREATE OR REPLACE FUNCTION is_valid_record_type(record_type_id INTEGER, record_is_type BOOLEAN)
7
+ RETURNS BOOLEAN AS $$
8
+ BEGIN
9
+ -- Record with no type is valid
10
+ IF record_type_id IS NULL THEN
11
+ RETURN TRUE;
12
+ END IF;
13
+
14
+ -- If current record is a type, it can only reference schema-less types
15
+ IF record_is_type THEN
16
+ RETURN EXISTS (
17
+ SELECT 1 FROM lamindb_record r
18
+ WHERE r.id = record_type_id AND r.is_type AND r.schema_id IS NULL
19
+ );
20
+ END IF;
21
+
22
+ -- Regular records can reference any type
23
+ RETURN EXISTS (
24
+ SELECT 1 FROM lamindb_record r
25
+ WHERE r.id = record_type_id AND r.is_type
26
+ );
27
+ END;
28
+ $$ LANGUAGE plpgsql;
29
+ """
30
+
31
+ ADD_CONSTRAINT_SQL = """
32
+ ALTER TABLE lamindb_record
33
+ ADD CONSTRAINT record_type_is_valid_fk
34
+ CHECK (is_valid_record_type(type_id, is_type));
35
+ """
36
+
37
+ DROP_CONSTRAINT_SQL = (
38
+ "ALTER TABLE lamindb_record DROP CONSTRAINT IF EXISTS record_type_is_valid_fk;"
39
+ )
40
+ DROP_FUNCTION_SQL = "DROP FUNCTION IF EXISTS is_valid_record_type(INTEGER, BOOLEAN);"
41
+
42
+
43
+ def apply_postgres_constraint(apps, schema_editor):
44
+ if schema_editor.connection.vendor == "postgresql":
45
+ schema_editor.execute(CREATE_FUNCTION_SQL)
46
+ schema_editor.execute(ADD_CONSTRAINT_SQL)
47
+
48
+
49
+ def revert_postgres_constraint(apps, schema_editor):
50
+ if schema_editor.connection.vendor == "postgresql":
51
+ schema_editor.execute(DROP_CONSTRAINT_SQL)
52
+ schema_editor.execute(DROP_FUNCTION_SQL)
53
+
54
+
55
+ class Migration(migrations.Migration):
56
+ dependencies = [
57
+ ("lamindb", "0119_squashed"),
58
+ ]
59
+
60
+ operations = [
61
+ migrations.RunPython(
62
+ apply_postgres_constraint, reverse_code=revert_postgres_constraint
63
+ ),
64
+ ]
@@ -0,0 +1,60 @@
1
+ # Generated by Django 5.2 on 2025-09-05 12:25
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+ import lamindb.base.fields
7
+ import lamindb.models.sqlrecord
8
+
9
+
10
+ class Migration(migrations.Migration):
11
+ dependencies = [
12
+ ("lamindb", "0120_add_record_fk_constraint"),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name="RecordUser",
18
+ fields=[
19
+ ("id", models.BigAutoField(primary_key=True, serialize=False)),
20
+ (
21
+ "feature",
22
+ lamindb.base.fields.ForeignKey(
23
+ blank=True,
24
+ on_delete=django.db.models.deletion.PROTECT,
25
+ related_name="links_recorduser",
26
+ to="lamindb.feature",
27
+ ),
28
+ ),
29
+ (
30
+ "record",
31
+ lamindb.base.fields.ForeignKey(
32
+ blank=True,
33
+ on_delete=django.db.models.deletion.CASCADE,
34
+ related_name="values_user",
35
+ to="lamindb.record",
36
+ ),
37
+ ),
38
+ (
39
+ "value",
40
+ lamindb.base.fields.ForeignKey(
41
+ blank=True,
42
+ on_delete=django.db.models.deletion.PROTECT,
43
+ related_name="links_record",
44
+ to="lamindb.user",
45
+ ),
46
+ ),
47
+ ],
48
+ options={
49
+ "unique_together": {("record", "feature", "value")},
50
+ },
51
+ bases=(models.Model, lamindb.models.sqlrecord.IsLink),
52
+ ),
53
+ migrations.AddField(
54
+ model_name="record",
55
+ name="linked_users",
56
+ field=models.ManyToManyField(
57
+ related_name="records", through="lamindb.RecordUser", to="lamindb.user"
58
+ ),
59
+ ),
60
+ ]
@@ -9,6 +9,7 @@
9
9
  BasicQuerySet
10
10
  QuerySet
11
11
  ArtifactSet
12
+ LazyArtifact
12
13
  QueryManager
13
14
  SQLRecordList
14
15
  FeatureManager
@@ -49,7 +50,7 @@ from .schema import Schema
49
50
  from .ulabel import ULabel
50
51
 
51
52
  # should come last as it needs everything else
52
- from .artifact import Artifact
53
+ from .artifact import Artifact, LazyArtifact
53
54
  from ._feature_manager import FeatureManager
54
55
  from ._label_manager import LabelManager
55
56
  from .collection import Collection, CollectionArtifact
@@ -78,6 +79,7 @@ from .project import (
78
79
  PersonProject,
79
80
  RecordPerson,
80
81
  RecordReference,
82
+ ProjectRecord,
81
83
  )
82
84
  from .run import RunFeatureValue
83
85
  from .schema import (
@@ -94,6 +96,7 @@ from .record import (
94
96
  RecordRecord,
95
97
  RecordULabel,
96
98
  RecordRun,
99
+ RecordUser,
97
100
  RecordArtifact,
98
101
  ArtifactRecord,
99
102
  )
@@ -8,8 +8,6 @@ from lamin_utils import logger
8
8
  from rich.text import Text
9
9
  from rich.tree import Tree
10
10
 
11
- from ..core._context import is_run_from_ipython
12
-
13
11
  if TYPE_CHECKING:
14
12
  from lamindb.models import Artifact, Collection, Run
15
13
 
@@ -41,6 +39,8 @@ def format_rich_tree(
41
39
  ) -> str | None:
42
40
  from rich.console import Console
43
41
 
42
+ from ..core._context import is_run_from_ipython
43
+
44
44
  # If tree has no children, return fallback
45
45
  if not tree.children:
46
46
  return fallback