lamindb 1.6.0__py3-none-any.whl → 1.6.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/__init__.py CHANGED
@@ -109,7 +109,7 @@ Backwards compatibility.
109
109
 
110
110
  # ruff: noqa: I001
111
111
  # denote a release candidate for 0.1.0 with 0.1rc1, 0.1a1, 0.1b1, etc.
112
- __version__ = "1.6.0"
112
+ __version__ = "1.6.1"
113
113
 
114
114
  import warnings
115
115
 
@@ -140,7 +140,6 @@ if _check_instance_setup(from_module="lamindb"):
140
140
  from .curators._legacy import CatManager as Curator
141
141
  from .models import (
142
142
  Artifact,
143
- Branch,
144
143
  Collection,
145
144
  Feature,
146
145
  FeatureSet, # backward compat
@@ -154,6 +153,7 @@ if _check_instance_setup(from_module="lamindb"):
154
153
  ULabel,
155
154
  User,
156
155
  Space,
156
+ Branch,
157
157
  Record,
158
158
  Sheet,
159
159
  )
lamindb/core/_context.py CHANGED
@@ -38,7 +38,7 @@ if TYPE_CHECKING:
38
38
  from lamindb_setup.core.types import UPathStr
39
39
 
40
40
  from lamindb.base.types import TransformType
41
- from lamindb.models import Project, Space
41
+ from lamindb.models import Branch, Project, Space
42
42
 
43
43
  is_run_from_ipython = getattr(builtins, "__IPYTHON__", False)
44
44
 
@@ -193,6 +193,7 @@ class Context:
193
193
  """A local path to the script or notebook that's running."""
194
194
  self._project: Project | None = None
195
195
  self._space: Space | None = None
196
+ self._branch: Branch | None = None
196
197
  self._logging_message_track: str = ""
197
198
  self._logging_message_imports: str = ""
198
199
  self._stream_tracker: LogStreamTracker = LogStreamTracker()
@@ -247,9 +248,14 @@ class Context:
247
248
 
248
249
  @property
249
250
  def space(self) -> Space | None:
250
- """The space in which entities are created during the run."""
251
+ """The space in which artifacts, collections, transforms, and runs are saved during the run."""
251
252
  return self._space
252
253
 
254
+ @property
255
+ def branch(self) -> Branch | None:
256
+ """The branch on which entities are created during the run."""
257
+ return self._branch
258
+
253
259
  @property
254
260
  def run(self) -> Run | None:
255
261
  """Managed run of context."""
@@ -261,6 +267,7 @@ class Context:
261
267
  *,
262
268
  project: str | Project | None = None,
263
269
  space: str | Space | None = None,
270
+ branch: str | Branch | None = None,
264
271
  params: dict | None = None,
265
272
  new_run: bool | None = None,
266
273
  path: str | None = None,
@@ -273,11 +280,11 @@ class Context:
273
280
 
274
281
  Args:
275
282
  transform: A transform (stem) `uid` (or record). If `None`, auto-creates a `transform` with its `uid`.
276
- project: A project, its `name` or `uid` for labeling entities created during the run.
277
- space: A restricted space, its `name` or `uid` for creating sensitive entities are created during the run.
278
- The default is the common `"All"` space that every LaminDB instance has.
279
- The `space` argument doesn't affect `Storage`, `ULabel`, `Feature`, `Schema`, `Param` and bionty entities as these provide structure that should typically be commonly accessible.
283
+ project: A project (or its `name` or `uid`) for labeling entities.
284
+ space: A restricted space (or its `name` or `uid`) in which to store artifacts, collections, transforms, and runs.
285
+ Default: the `"All"` space.
280
286
  If you want to manually move entities to a different space, set the `.space` field (:doc:`docs:access`).
287
+ branch: A branch (or its `name` or `uid`) on which to store records.
281
288
  params: A dictionary of parameters to track for the run.
282
289
  new_run: If `False`, loads the latest run of transform
283
290
  (default notebook), if `True`, creates new run (default non-notebook).
@@ -299,7 +306,7 @@ class Context:
299
306
 
300
307
  More examples: :doc:`/track`
301
308
  """
302
- from lamindb.models import Project, Space
309
+ from lamindb.models import Branch, Project, Space
303
310
 
304
311
  instance_settings = ln_setup.settings.instance
305
312
  # similar logic here: https://github.com/laminlabs/lamindb/pull/2527
@@ -337,6 +344,21 @@ class Context:
337
344
  f"Space '{space}', please check on the hub UI whether you have the correct `uid` or `name`."
338
345
  )
339
346
  self._space = space_record
347
+ if branch is not None:
348
+ if isinstance(branch, Branch):
349
+ assert branch._state.adding is False, ( # noqa: S101
350
+ "Branch must be saved before passing it to track()"
351
+ )
352
+ branch_record = branch
353
+ else:
354
+ branch_record = Branch.filter(
355
+ Q(name=branch) | Q(uid=branch)
356
+ ).one_or_none()
357
+ if branch_record is None:
358
+ raise InvalidArgument(
359
+ f"Space '{branch}', please check on the hub UI whether you have the correct `uid` or `name`."
360
+ )
361
+ self._branch = branch_record
340
362
  self._logging_message_track = ""
341
363
  self._logging_message_imports = ""
342
364
  if transform is not None and isinstance(transform, str):
@@ -105,9 +105,9 @@ def get_dataset1(
105
105
  "treatment_time_h": [24, 24, 6],
106
106
  "donor": ["D0001", "D0002", None],
107
107
  "donor_ethnicity": [
108
- ["African", "African American"],
109
- ["African", "West African"],
110
- ["Asian"],
108
+ ["Chinese", "Singaporean Chinese"],
109
+ ["Chinese", "Han Chinese"],
110
+ ["Chinese"],
111
111
  ],
112
112
  }
113
113
  # define the dataset-level metadata
@@ -8,42 +8,35 @@ import lamindb.base.fields
8
8
 
9
9
 
10
10
  def populate_hash_values(apps, schema_editor):
11
+ from tqdm import tqdm
12
+
11
13
  FeatureValue = apps.get_model("lamindb", "FeatureValue")
12
14
 
13
- # Get records that need updating
14
- records_to_update = FeatureValue.objects.filter(hash__isnull=True)
15
+ records_queryset = FeatureValue.objects.filter(hash__isnull=True)
16
+ total_count = records_queryset.count()
17
+ print(f"\nFound {total_count} FeatureValue records with hash=None. Populating...")
15
18
 
16
- print(
17
- f"\nFound {records_to_update.count()} FeatureValue records with hash=None. Populating..."
18
- )
19
+ # Convert to list to avoid QuerySet modification issues
20
+ records_to_update = list(records_queryset)
19
21
 
22
+ batch_size = 1000
20
23
  updated_count = 0
21
- skipped_count = 0
22
24
 
23
- # Iterate efficiently through records
24
- for record in records_to_update.iterator():
25
- value = record.value
26
- new_hash = None
25
+ for batch_start in tqdm(range(0, len(records_to_update), batch_size)):
26
+ batch_records = records_to_update[batch_start : batch_start + batch_size]
27
27
 
28
- if not isinstance(value, dict):
29
- new_hash = hash_string(str(value))
30
- else:
31
- new_hash = hash_dict(value)
28
+ # Calculate hashes for all records in batch
29
+ for record in batch_records:
30
+ if not isinstance(record.value, dict):
31
+ record.hash = hash_string(str(record.value))
32
+ else:
33
+ record.hash = hash_dict(record.value)
32
34
 
33
- try:
34
- record.hash = new_hash
35
- record.save(update_fields=["hash"])
36
- updated_count += 1
37
- except Exception as e:
38
- # This will likely catch IntegrityError if a duplicate hash exists
39
- # for the same feature. You might want to log these or handle them
40
- # based on your data cleanup strategy.
41
- print(
42
- f" - Could not update record {record.id} (value: {str(value)[:50]}...): {e}"
43
- )
44
- skipped_count += 1
35
+ # Bulk update the entire batch
36
+ FeatureValue.objects.bulk_update(batch_records, ["hash"], batch_size=batch_size)
37
+ updated_count += len(batch_records)
45
38
 
46
- print(f"Finished. Updated: {updated_count}, Skipped/Errors: {skipped_count}.")
39
+ print(f"Finished. Updated: {updated_count} records.")
47
40
 
48
41
 
49
42
  class Migration(migrations.Migration):
@@ -0,0 +1,403 @@
1
+ # Generated by Django 5.2 on 2025-06-02 10:53
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations
5
+
6
+ import lamindb.base.fields
7
+ import lamindb.base.uids
8
+
9
+
10
+ class Migration(migrations.Migration):
11
+ dependencies = [
12
+ ("lamindb", "0103_remove_writelog_migration_state_and_more"),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.AlterField(
17
+ model_name="branch",
18
+ name="uid",
19
+ field=lamindb.base.fields.CharField(
20
+ blank=True,
21
+ db_index=True,
22
+ default=lamindb.base.uids.base62_12,
23
+ editable=False,
24
+ max_length=12,
25
+ unique=True,
26
+ ),
27
+ ),
28
+ migrations.AlterField(
29
+ model_name="artifact",
30
+ name="branch",
31
+ field=lamindb.base.fields.ForeignKey(
32
+ blank=True,
33
+ db_column="_branch_code",
34
+ db_default=1,
35
+ default=1,
36
+ on_delete=django.db.models.deletion.PROTECT,
37
+ related_name="+",
38
+ to="lamindb.branch",
39
+ ),
40
+ ),
41
+ migrations.AlterField(
42
+ model_name="artifact",
43
+ name="space",
44
+ field=lamindb.base.fields.ForeignKey(
45
+ blank=True,
46
+ db_default=1,
47
+ default=1,
48
+ on_delete=django.db.models.deletion.PROTECT,
49
+ related_name="+",
50
+ to="lamindb.space",
51
+ ),
52
+ ),
53
+ migrations.AlterField(
54
+ model_name="collection",
55
+ name="branch",
56
+ field=lamindb.base.fields.ForeignKey(
57
+ blank=True,
58
+ db_column="_branch_code",
59
+ db_default=1,
60
+ default=1,
61
+ on_delete=django.db.models.deletion.PROTECT,
62
+ related_name="+",
63
+ to="lamindb.branch",
64
+ ),
65
+ ),
66
+ migrations.AlterField(
67
+ model_name="collection",
68
+ name="space",
69
+ field=lamindb.base.fields.ForeignKey(
70
+ blank=True,
71
+ db_default=1,
72
+ default=1,
73
+ on_delete=django.db.models.deletion.PROTECT,
74
+ related_name="+",
75
+ to="lamindb.space",
76
+ ),
77
+ ),
78
+ migrations.AlterField(
79
+ model_name="feature",
80
+ name="branch",
81
+ field=lamindb.base.fields.ForeignKey(
82
+ blank=True,
83
+ db_column="_branch_code",
84
+ db_default=1,
85
+ default=1,
86
+ on_delete=django.db.models.deletion.PROTECT,
87
+ related_name="+",
88
+ to="lamindb.branch",
89
+ ),
90
+ ),
91
+ migrations.AlterField(
92
+ model_name="feature",
93
+ name="space",
94
+ field=lamindb.base.fields.ForeignKey(
95
+ blank=True,
96
+ db_default=1,
97
+ default=1,
98
+ on_delete=django.db.models.deletion.PROTECT,
99
+ related_name="+",
100
+ to="lamindb.space",
101
+ ),
102
+ ),
103
+ migrations.AlterField(
104
+ model_name="featurevalue",
105
+ name="branch",
106
+ field=lamindb.base.fields.ForeignKey(
107
+ blank=True,
108
+ db_column="_branch_code",
109
+ db_default=1,
110
+ default=1,
111
+ on_delete=django.db.models.deletion.PROTECT,
112
+ related_name="+",
113
+ to="lamindb.branch",
114
+ ),
115
+ ),
116
+ migrations.AlterField(
117
+ model_name="featurevalue",
118
+ name="space",
119
+ field=lamindb.base.fields.ForeignKey(
120
+ blank=True,
121
+ db_default=1,
122
+ default=1,
123
+ on_delete=django.db.models.deletion.PROTECT,
124
+ related_name="+",
125
+ to="lamindb.space",
126
+ ),
127
+ ),
128
+ migrations.AlterField(
129
+ model_name="person",
130
+ name="branch",
131
+ field=lamindb.base.fields.ForeignKey(
132
+ blank=True,
133
+ db_column="_branch_code",
134
+ db_default=1,
135
+ default=1,
136
+ on_delete=django.db.models.deletion.PROTECT,
137
+ related_name="+",
138
+ to="lamindb.branch",
139
+ ),
140
+ ),
141
+ migrations.AlterField(
142
+ model_name="person",
143
+ name="space",
144
+ field=lamindb.base.fields.ForeignKey(
145
+ blank=True,
146
+ db_default=1,
147
+ default=1,
148
+ on_delete=django.db.models.deletion.PROTECT,
149
+ related_name="+",
150
+ to="lamindb.space",
151
+ ),
152
+ ),
153
+ migrations.AlterField(
154
+ model_name="project",
155
+ name="branch",
156
+ field=lamindb.base.fields.ForeignKey(
157
+ blank=True,
158
+ db_column="_branch_code",
159
+ db_default=1,
160
+ default=1,
161
+ on_delete=django.db.models.deletion.PROTECT,
162
+ related_name="+",
163
+ to="lamindb.branch",
164
+ ),
165
+ ),
166
+ migrations.AlterField(
167
+ model_name="project",
168
+ name="space",
169
+ field=lamindb.base.fields.ForeignKey(
170
+ blank=True,
171
+ db_default=1,
172
+ default=1,
173
+ on_delete=django.db.models.deletion.PROTECT,
174
+ related_name="+",
175
+ to="lamindb.space",
176
+ ),
177
+ ),
178
+ migrations.AlterField(
179
+ model_name="record",
180
+ name="branch",
181
+ field=lamindb.base.fields.ForeignKey(
182
+ blank=True,
183
+ db_column="_branch_code",
184
+ db_default=1,
185
+ default=1,
186
+ on_delete=django.db.models.deletion.PROTECT,
187
+ related_name="+",
188
+ to="lamindb.branch",
189
+ ),
190
+ ),
191
+ migrations.AlterField(
192
+ model_name="record",
193
+ name="space",
194
+ field=lamindb.base.fields.ForeignKey(
195
+ blank=True,
196
+ db_default=1,
197
+ default=1,
198
+ on_delete=django.db.models.deletion.PROTECT,
199
+ related_name="+",
200
+ to="lamindb.space",
201
+ ),
202
+ ),
203
+ migrations.AlterField(
204
+ model_name="recordrecord",
205
+ name="branch",
206
+ field=lamindb.base.fields.ForeignKey(
207
+ blank=True,
208
+ db_column="_branch_code",
209
+ db_default=1,
210
+ default=1,
211
+ on_delete=django.db.models.deletion.PROTECT,
212
+ related_name="+",
213
+ to="lamindb.branch",
214
+ ),
215
+ ),
216
+ migrations.AlterField(
217
+ model_name="recordrecord",
218
+ name="space",
219
+ field=lamindb.base.fields.ForeignKey(
220
+ blank=True,
221
+ db_default=1,
222
+ default=1,
223
+ on_delete=django.db.models.deletion.PROTECT,
224
+ related_name="+",
225
+ to="lamindb.space",
226
+ ),
227
+ ),
228
+ migrations.AlterField(
229
+ model_name="reference",
230
+ name="branch",
231
+ field=lamindb.base.fields.ForeignKey(
232
+ blank=True,
233
+ db_column="_branch_code",
234
+ db_default=1,
235
+ default=1,
236
+ on_delete=django.db.models.deletion.PROTECT,
237
+ related_name="+",
238
+ to="lamindb.branch",
239
+ ),
240
+ ),
241
+ migrations.AlterField(
242
+ model_name="reference",
243
+ name="space",
244
+ field=lamindb.base.fields.ForeignKey(
245
+ blank=True,
246
+ db_default=1,
247
+ default=1,
248
+ on_delete=django.db.models.deletion.PROTECT,
249
+ related_name="+",
250
+ to="lamindb.space",
251
+ ),
252
+ ),
253
+ migrations.AlterField(
254
+ model_name="run",
255
+ name="branch",
256
+ field=lamindb.base.fields.ForeignKey(
257
+ blank=True,
258
+ db_column="_branch_code",
259
+ db_default=1,
260
+ default=1,
261
+ on_delete=django.db.models.deletion.PROTECT,
262
+ related_name="+",
263
+ to="lamindb.branch",
264
+ ),
265
+ ),
266
+ migrations.AlterField(
267
+ model_name="run",
268
+ name="space",
269
+ field=lamindb.base.fields.ForeignKey(
270
+ blank=True,
271
+ db_default=1,
272
+ default=1,
273
+ on_delete=django.db.models.deletion.PROTECT,
274
+ related_name="+",
275
+ to="lamindb.space",
276
+ ),
277
+ ),
278
+ migrations.AlterField(
279
+ model_name="schema",
280
+ name="branch",
281
+ field=lamindb.base.fields.ForeignKey(
282
+ blank=True,
283
+ db_column="_branch_code",
284
+ db_default=1,
285
+ default=1,
286
+ on_delete=django.db.models.deletion.PROTECT,
287
+ related_name="+",
288
+ to="lamindb.branch",
289
+ ),
290
+ ),
291
+ migrations.AlterField(
292
+ model_name="schema",
293
+ name="space",
294
+ field=lamindb.base.fields.ForeignKey(
295
+ blank=True,
296
+ db_default=1,
297
+ default=1,
298
+ on_delete=django.db.models.deletion.PROTECT,
299
+ related_name="+",
300
+ to="lamindb.space",
301
+ ),
302
+ ),
303
+ migrations.AlterField(
304
+ model_name="sheet",
305
+ name="branch",
306
+ field=lamindb.base.fields.ForeignKey(
307
+ blank=True,
308
+ db_column="_branch_code",
309
+ db_default=1,
310
+ default=1,
311
+ on_delete=django.db.models.deletion.PROTECT,
312
+ related_name="+",
313
+ to="lamindb.branch",
314
+ ),
315
+ ),
316
+ migrations.AlterField(
317
+ model_name="sheet",
318
+ name="space",
319
+ field=lamindb.base.fields.ForeignKey(
320
+ blank=True,
321
+ db_default=1,
322
+ default=1,
323
+ on_delete=django.db.models.deletion.PROTECT,
324
+ related_name="+",
325
+ to="lamindb.space",
326
+ ),
327
+ ),
328
+ migrations.AlterField(
329
+ model_name="storage",
330
+ name="branch",
331
+ field=lamindb.base.fields.ForeignKey(
332
+ blank=True,
333
+ db_column="_branch_code",
334
+ db_default=1,
335
+ default=1,
336
+ on_delete=django.db.models.deletion.PROTECT,
337
+ related_name="+",
338
+ to="lamindb.branch",
339
+ ),
340
+ ),
341
+ migrations.AlterField(
342
+ model_name="storage",
343
+ name="space",
344
+ field=lamindb.base.fields.ForeignKey(
345
+ blank=True,
346
+ db_default=1,
347
+ default=1,
348
+ on_delete=django.db.models.deletion.PROTECT,
349
+ related_name="+",
350
+ to="lamindb.space",
351
+ ),
352
+ ),
353
+ migrations.AlterField(
354
+ model_name="transform",
355
+ name="branch",
356
+ field=lamindb.base.fields.ForeignKey(
357
+ blank=True,
358
+ db_column="_branch_code",
359
+ db_default=1,
360
+ default=1,
361
+ on_delete=django.db.models.deletion.PROTECT,
362
+ related_name="+",
363
+ to="lamindb.branch",
364
+ ),
365
+ ),
366
+ migrations.AlterField(
367
+ model_name="transform",
368
+ name="space",
369
+ field=lamindb.base.fields.ForeignKey(
370
+ blank=True,
371
+ db_default=1,
372
+ default=1,
373
+ on_delete=django.db.models.deletion.PROTECT,
374
+ related_name="+",
375
+ to="lamindb.space",
376
+ ),
377
+ ),
378
+ migrations.AlterField(
379
+ model_name="ulabel",
380
+ name="branch",
381
+ field=lamindb.base.fields.ForeignKey(
382
+ blank=True,
383
+ db_column="_branch_code",
384
+ db_default=1,
385
+ default=1,
386
+ on_delete=django.db.models.deletion.PROTECT,
387
+ related_name="+",
388
+ to="lamindb.branch",
389
+ ),
390
+ ),
391
+ migrations.AlterField(
392
+ model_name="ulabel",
393
+ name="space",
394
+ field=lamindb.base.fields.ForeignKey(
395
+ blank=True,
396
+ db_default=1,
397
+ default=1,
398
+ on_delete=django.db.models.deletion.PROTECT,
399
+ related_name="+",
400
+ to="lamindb.space",
401
+ ),
402
+ ),
403
+ ]
@@ -1,4 +1,4 @@
1
- # Generated by Django 5.2 on 2025-05-29 12:43
1
+ # Generated by Django 5.2 on 2025-06-03 09:49
2
2
 
3
3
  import django.core.validators
4
4
  import django.db.models.deletion
@@ -124,6 +124,7 @@ class Migration(migrations.Migration):
124
124
  ("lamindb", "0101_alter_artifact_hash_alter_feature_name_and_more"),
125
125
  ("lamindb", "0102_remove_writelog_branch_code_and_more"),
126
126
  ("lamindb", "0103_remove_writelog_migration_state_and_more"),
127
+ ("lamindb", "0104_alter_branch_uid"),
127
128
  ]
128
129
 
129
130
  dependencies = [] # type: ignore
@@ -169,9 +170,8 @@ class Migration(migrations.Migration):
169
170
  "uid",
170
171
  lamindb.base.fields.CharField(
171
172
  blank=True,
172
- db_default="M",
173
173
  db_index=True,
174
- default="M",
174
+ default=lamindb.base.uids.base62_12,
175
175
  editable=False,
176
176
  max_length=12,
177
177
  unique=True,
@@ -476,6 +476,7 @@ class Migration(migrations.Migration):
476
476
  db_default=1,
477
477
  default=1,
478
478
  on_delete=django.db.models.deletion.PROTECT,
479
+ related_name="+",
479
480
  to="lamindb.branch",
480
481
  ),
481
482
  ),
@@ -594,6 +595,7 @@ class Migration(migrations.Migration):
594
595
  db_default=1,
595
596
  default=1,
596
597
  on_delete=django.db.models.deletion.PROTECT,
598
+ related_name="+",
597
599
  to="lamindb.branch",
598
600
  ),
599
601
  ),
@@ -822,6 +824,7 @@ class Migration(migrations.Migration):
822
824
  db_default=1,
823
825
  default=1,
824
826
  on_delete=django.db.models.deletion.PROTECT,
827
+ related_name="+",
825
828
  to="lamindb.branch",
826
829
  ),
827
830
  ),
@@ -1008,6 +1011,7 @@ class Migration(migrations.Migration):
1008
1011
  db_default=1,
1009
1012
  default=1,
1010
1013
  on_delete=django.db.models.deletion.PROTECT,
1014
+ related_name="+",
1011
1015
  to="lamindb.branch",
1012
1016
  ),
1013
1017
  ),
@@ -1136,6 +1140,7 @@ class Migration(migrations.Migration):
1136
1140
  db_default=1,
1137
1141
  default=1,
1138
1142
  on_delete=django.db.models.deletion.PROTECT,
1143
+ related_name="+",
1139
1144
  to="lamindb.branch",
1140
1145
  ),
1141
1146
  ),
@@ -1272,6 +1277,7 @@ class Migration(migrations.Migration):
1272
1277
  db_default=1,
1273
1278
  default=1,
1274
1279
  on_delete=django.db.models.deletion.PROTECT,
1280
+ related_name="+",
1275
1281
  to="lamindb.branch",
1276
1282
  ),
1277
1283
  ),
@@ -1440,6 +1446,7 @@ class Migration(migrations.Migration):
1440
1446
  db_default=1,
1441
1447
  default=1,
1442
1448
  on_delete=django.db.models.deletion.PROTECT,
1449
+ related_name="+",
1443
1450
  to="lamindb.branch",
1444
1451
  ),
1445
1452
  ),
@@ -1569,6 +1576,7 @@ class Migration(migrations.Migration):
1569
1576
  db_default=1,
1570
1577
  default=1,
1571
1578
  on_delete=django.db.models.deletion.PROTECT,
1579
+ related_name="+",
1572
1580
  to="lamindb.branch",
1573
1581
  ),
1574
1582
  ),
@@ -1606,6 +1614,7 @@ class Migration(migrations.Migration):
1606
1614
  db_default=1,
1607
1615
  default=1,
1608
1616
  on_delete=django.db.models.deletion.PROTECT,
1617
+ related_name="+",
1609
1618
  to="lamindb.space",
1610
1619
  ),
1611
1620
  ),
@@ -1748,6 +1757,7 @@ class Migration(migrations.Migration):
1748
1757
  db_default=1,
1749
1758
  default=1,
1750
1759
  on_delete=django.db.models.deletion.PROTECT,
1760
+ related_name="+",
1751
1761
  to="lamindb.branch",
1752
1762
  ),
1753
1763
  ),
@@ -1903,6 +1913,7 @@ class Migration(migrations.Migration):
1903
1913
  db_default=1,
1904
1914
  default=1,
1905
1915
  on_delete=django.db.models.deletion.PROTECT,
1916
+ related_name="+",
1906
1917
  to="lamindb.branch",
1907
1918
  ),
1908
1919
  ),
@@ -2465,6 +2476,7 @@ class Migration(migrations.Migration):
2465
2476
  db_default=1,
2466
2477
  default=1,
2467
2478
  on_delete=django.db.models.deletion.PROTECT,
2479
+ related_name="+",
2468
2480
  to="lamindb.branch",
2469
2481
  ),
2470
2482
  ),
@@ -2854,6 +2866,7 @@ class Migration(migrations.Migration):
2854
2866
  db_default=1,
2855
2867
  default=1,
2856
2868
  on_delete=django.db.models.deletion.PROTECT,
2869
+ related_name="+",
2857
2870
  to="lamindb.branch",
2858
2871
  ),
2859
2872
  ),
@@ -2885,6 +2898,7 @@ class Migration(migrations.Migration):
2885
2898
  db_default=1,
2886
2899
  default=1,
2887
2900
  on_delete=django.db.models.deletion.PROTECT,
2901
+ related_name="+",
2888
2902
  to="lamindb.space",
2889
2903
  ),
2890
2904
  ),
@@ -2991,6 +3005,7 @@ class Migration(migrations.Migration):
2991
3005
  db_default=1,
2992
3006
  default=1,
2993
3007
  on_delete=django.db.models.deletion.PROTECT,
3008
+ related_name="+",
2994
3009
  to="lamindb.space",
2995
3010
  ),
2996
3011
  ),
@@ -3002,6 +3017,7 @@ class Migration(migrations.Migration):
3002
3017
  db_default=1,
3003
3018
  default=1,
3004
3019
  on_delete=django.db.models.deletion.PROTECT,
3020
+ related_name="+",
3005
3021
  to="lamindb.space",
3006
3022
  ),
3007
3023
  ),
@@ -3013,6 +3029,7 @@ class Migration(migrations.Migration):
3013
3029
  db_default=1,
3014
3030
  default=1,
3015
3031
  on_delete=django.db.models.deletion.PROTECT,
3032
+ related_name="+",
3016
3033
  to="lamindb.space",
3017
3034
  ),
3018
3035
  ),
@@ -3024,6 +3041,7 @@ class Migration(migrations.Migration):
3024
3041
  db_default=1,
3025
3042
  default=1,
3026
3043
  on_delete=django.db.models.deletion.PROTECT,
3044
+ related_name="+",
3027
3045
  to="lamindb.space",
3028
3046
  ),
3029
3047
  ),
@@ -3035,6 +3053,7 @@ class Migration(migrations.Migration):
3035
3053
  db_default=1,
3036
3054
  default=1,
3037
3055
  on_delete=django.db.models.deletion.PROTECT,
3056
+ related_name="+",
3038
3057
  to="lamindb.space",
3039
3058
  ),
3040
3059
  ),
@@ -3046,6 +3065,7 @@ class Migration(migrations.Migration):
3046
3065
  db_default=1,
3047
3066
  default=1,
3048
3067
  on_delete=django.db.models.deletion.PROTECT,
3068
+ related_name="+",
3049
3069
  to="lamindb.space",
3050
3070
  ),
3051
3071
  ),
@@ -3057,6 +3077,7 @@ class Migration(migrations.Migration):
3057
3077
  db_default=1,
3058
3078
  default=1,
3059
3079
  on_delete=django.db.models.deletion.PROTECT,
3080
+ related_name="+",
3060
3081
  to="lamindb.space",
3061
3082
  ),
3062
3083
  ),
@@ -3068,6 +3089,7 @@ class Migration(migrations.Migration):
3068
3089
  db_default=1,
3069
3090
  default=1,
3070
3091
  on_delete=django.db.models.deletion.PROTECT,
3092
+ related_name="+",
3071
3093
  to="lamindb.space",
3072
3094
  ),
3073
3095
  ),
@@ -3079,6 +3101,7 @@ class Migration(migrations.Migration):
3079
3101
  db_default=1,
3080
3102
  default=1,
3081
3103
  on_delete=django.db.models.deletion.PROTECT,
3104
+ related_name="+",
3082
3105
  to="lamindb.space",
3083
3106
  ),
3084
3107
  ),
@@ -3090,6 +3113,7 @@ class Migration(migrations.Migration):
3090
3113
  db_default=1,
3091
3114
  default=1,
3092
3115
  on_delete=django.db.models.deletion.PROTECT,
3116
+ related_name="+",
3093
3117
  to="lamindb.space",
3094
3118
  ),
3095
3119
  ),
@@ -3186,6 +3210,7 @@ class Migration(migrations.Migration):
3186
3210
  db_default=1,
3187
3211
  default=1,
3188
3212
  on_delete=django.db.models.deletion.PROTECT,
3213
+ related_name="+",
3189
3214
  to="lamindb.branch",
3190
3215
  ),
3191
3216
  ),
@@ -3207,6 +3232,7 @@ class Migration(migrations.Migration):
3207
3232
  db_default=1,
3208
3233
  default=1,
3209
3234
  on_delete=django.db.models.deletion.PROTECT,
3235
+ related_name="+",
3210
3236
  to="lamindb.space",
3211
3237
  ),
3212
3238
  ),
@@ -3371,6 +3397,7 @@ class Migration(migrations.Migration):
3371
3397
  db_default=1,
3372
3398
  default=1,
3373
3399
  on_delete=django.db.models.deletion.PROTECT,
3400
+ related_name="+",
3374
3401
  to="lamindb.branch",
3375
3402
  ),
3376
3403
  ),
@@ -3387,6 +3414,7 @@ class Migration(migrations.Migration):
3387
3414
  db_default=1,
3388
3415
  default=1,
3389
3416
  on_delete=django.db.models.deletion.PROTECT,
3417
+ related_name="+",
3390
3418
  to="lamindb.space",
3391
3419
  ),
3392
3420
  ),
@@ -3630,6 +3658,7 @@ class Migration(migrations.Migration):
3630
3658
  db_default=1,
3631
3659
  default=1,
3632
3660
  on_delete=django.db.models.deletion.PROTECT,
3661
+ related_name="+",
3633
3662
  to="lamindb.branch",
3634
3663
  ),
3635
3664
  ),
@@ -3657,6 +3686,7 @@ class Migration(migrations.Migration):
3657
3686
  db_default=1,
3658
3687
  default=1,
3659
3688
  on_delete=django.db.models.deletion.PROTECT,
3689
+ related_name="+",
3660
3690
  to="lamindb.space",
3661
3691
  ),
3662
3692
  ),
@@ -624,7 +624,10 @@ def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
624
624
  if len(split_key) == 2:
625
625
  comparator = f"__{split_key[1]}"
626
626
  feature = features.get(name=normalized_key)
627
- if not feature.dtype.startswith("cat"):
627
+ # non-categorical features
628
+ if not feature.dtype.startswith("cat") and not feature.dtype.startswith(
629
+ "list[cat"
630
+ ):
628
631
  if comparator == "__isnull":
629
632
  if cls == FeatureManagerArtifact:
630
633
  from .artifact import ArtifactFeatureValue
@@ -653,6 +656,7 @@ def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
653
656
  expression = {feature_param: feature, f"value{comparator}": value}
654
657
  feature_values = value_model.filter(**expression)
655
658
  new_expression[f"_{feature_param}_values__id__in"] = feature_values
659
+ # categorical features
656
660
  elif isinstance(value, (str, SQLRecord, bool)):
657
661
  if comparator == "__isnull":
658
662
  if cls == FeatureManagerArtifact:
@@ -670,22 +674,22 @@ def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
670
674
  # we distinguish cases in which we have multiple label matches vs. one
671
675
  label = None
672
676
  labels = None
677
+ result = parse_dtype(feature.dtype)[0]
678
+ label_registry = result["registry"]
673
679
  if isinstance(value, str):
680
+ field_name = result["field"].field.name
674
681
  # we need the comparator here because users might query like so
675
682
  # ln.Artifact.filter(experiment__contains="Experi")
676
- expression = {f"name{comparator}": value}
677
- labels = ULabel.filter(**expression).all()
683
+ expression = {f"{field_name}{comparator}": value}
684
+ labels = result["registry"].filter(**expression).all()
678
685
  if len(labels) == 0:
679
686
  raise DoesNotExist(
680
- f"Did not find a ULabel matching `name{comparator}={value}`"
687
+ f"Did not find a {label_registry.__name__} matching `{field_name}{comparator}={value}`"
681
688
  )
682
689
  elif len(labels) == 1:
683
690
  label = labels[0]
684
691
  elif isinstance(value, SQLRecord):
685
692
  label = value
686
- label_registry = (
687
- label.__class__ if label is not None else labels[0].__class__
688
- )
689
693
  accessor_name = (
690
694
  label_registry.artifacts.through.artifact.field._related_name
691
695
  )
@@ -129,9 +129,7 @@ def _load_concat_artifacts(
129
129
 
130
130
 
131
131
  class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
132
- """Collections of artifacts.
133
-
134
- Collections provide a simple way of versioning collections of artifacts.
132
+ """Versioned collections of artifacts.
135
133
 
136
134
  Args:
137
135
  artifacts: `list[Artifact]` A list of artifacts.
lamindb/models/project.py CHANGED
@@ -191,14 +191,18 @@ class Reference(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
191
191
 
192
192
 
193
193
  class Project(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
194
- """Projects.
194
+ """Projects to label artifacts, transforms, and runs.
195
+
196
+ Example::
197
+
198
+ project = Project(
199
+ name="My Project Name",
200
+ abbr="MPN",
201
+ url="https://example.com/my_project",
202
+ ).save()
203
+ artifact.projects.add(project) # <-- labels the artifact with the project
204
+ ln.track(project=project) # <-- automtically labels entities during the run
195
205
 
196
- Example:
197
- >>> project = Project(
198
- ... name="My Project Name",
199
- ... abbr="MPN",
200
- ... url="https://example.com/my_project",
201
- ... ).save()
202
206
  """
203
207
 
204
208
  class Meta(SQLRecord.Meta, TracksRun.Meta, TracksUpdates.Meta):
lamindb/models/record.py CHANGED
@@ -31,6 +31,9 @@ class Record(SQLRecord, CanCurate, TracksRun, TracksUpdates):
31
31
 
32
32
  This is currently more convenient to use through the UI.
33
33
 
34
+ A `Record` has a flexible schema: it can store data for arbitrary features.
35
+ Changing the fields of a :class:`~lamindb.models.SQLRecord`, you need to modify the columns of the underlying table in the database.
36
+
34
37
  Args:
35
38
  name: `str` A name.
36
39
  description: `str` A description.
@@ -169,6 +172,48 @@ class Sheet(SQLRecord, TracksRun, TracksUpdates):
169
172
  projects: Project
170
173
  """Linked projects."""
171
174
 
175
+ @overload
176
+ def __init__(
177
+ self,
178
+ name: str,
179
+ schema: Schema | None = None,
180
+ description: str | None = None,
181
+ ): ...
182
+
183
+ @overload
184
+ def __init__(
185
+ self,
186
+ *db_args,
187
+ ): ...
188
+
189
+ def __init__(
190
+ self,
191
+ *args,
192
+ **kwargs,
193
+ ):
194
+ if len(args) == len(self._meta.concrete_fields):
195
+ super().__init__(*args, **kwargs)
196
+ return None
197
+ if len(args) > 0:
198
+ raise ValueError("Only one non-keyword arg allowed")
199
+ name: str = kwargs.pop("name", None)
200
+ schema: Schema | None = kwargs.pop("schema", None)
201
+ description: str | None = kwargs.pop("description", None)
202
+ _skip_validation = kwargs.pop("_skip_validation", True)
203
+ _aux = kwargs.pop("_aux", None)
204
+ if len(kwargs) > 0:
205
+ valid_keywords = ", ".join([val[0] for val in _get_record_kwargs(Record)])
206
+ raise FieldValidationError(
207
+ f"Only {valid_keywords} are valid keyword arguments"
208
+ )
209
+ super().__init__(
210
+ name=name,
211
+ schema=schema,
212
+ description=description,
213
+ _skip_validation=_skip_validation,
214
+ _aux=_aux,
215
+ )
216
+
172
217
 
173
218
  class RecordJson(BaseSQLRecord, IsLink):
174
219
  id: int = models.BigAutoField(primary_key=True)
lamindb/models/run.py CHANGED
@@ -139,8 +139,10 @@ class TracksUpdates(models.Model):
139
139
  class User(BaseSQLRecord, CanCurate):
140
140
  """Users.
141
141
 
142
- All data in this registry is synced from `lamin.ai` to ensure a universal
143
- user identity. There is no need to manually create records.
142
+ Every :class:`~lamindb.models.SQLRecord` has a `created_by` field that links to the creating user.
143
+
144
+ All data in this registry is synchronized from LaminHub to ensure a universal
145
+ user identity.
144
146
 
145
147
  Examples:
146
148
 
@@ -49,6 +49,7 @@ from ..base.fields import (
49
49
  ForeignKey,
50
50
  JSONField,
51
51
  )
52
+ from ..base.ids import base62_12
52
53
  from ..base.types import FieldAttr, StrField
53
54
  from ..errors import (
54
55
  FieldValidationError,
@@ -654,17 +655,23 @@ class BaseSQLRecord(models.Model, metaclass=Registry):
654
655
  def __init__(self, *args, **kwargs):
655
656
  skip_validation = kwargs.pop("_skip_validation", False)
656
657
  if not args:
657
- if (
658
- issubclass(self.__class__, SQLRecord)
659
- and self.__class__.__name__
660
- not in {"Storage", "ULabel", "Feature", "Schema"}
661
- # do not save bionty entities in restricted spaces by default
662
- and self.__class__.__module__ != "bionty.models"
663
- ):
658
+ if self.__class__.__name__ in {
659
+ "Artifact",
660
+ "Collection",
661
+ "Transform",
662
+ "Run",
663
+ }:
664
664
  from lamindb import context as run_context
665
665
 
666
666
  if run_context.space is not None:
667
667
  kwargs["space"] = run_context.space
668
+ if issubclass(
669
+ self.__class__, SQLRecord
670
+ ) and self.__class__.__name__ not in {"Storage", "Source"}:
671
+ from lamindb import context as run_context
672
+
673
+ if run_context.branch is not None:
674
+ kwargs["branch"] = run_context.branch
668
675
  if skip_validation:
669
676
  super().__init__(**kwargs)
670
677
  else:
@@ -887,12 +894,11 @@ class BaseSQLRecord(models.Model, metaclass=Registry):
887
894
 
888
895
 
889
896
  class Space(BaseSQLRecord):
890
- """Spaces to restrict access to records to specific users or teams.
897
+ """Workspaces with managed access for specific users or teams.
891
898
 
892
- You can use spaces to restrict access to records within an instance.
899
+ Guide: :doc:`docs:access`.
893
900
 
894
- All data in this registry is synced from `lamin.ai` to enable re-using spaces across instances.
895
- There is no need to manually create records.
901
+ All data in this registry is synchronized from LaminHub so that spaces can be shared and reused across multiple LaminDB instances.
896
902
  """
897
903
 
898
904
  id: int = models.SmallAutoField(primary_key=True)
@@ -941,7 +947,21 @@ class Space(BaseSQLRecord):
941
947
 
942
948
 
943
949
  class Branch(BaseSQLRecord):
944
- """Branches allow to group changes similar to how git branches group changes."""
950
+ """Branches for change management with archive and trash states.
951
+
952
+ Every `SQLRecord` has a `branch` field, which dictates where a record appears in queries & searches.
953
+ """
954
+
955
+ # below isn't fully implemented but a roadmap
956
+ # - 3: template (hidden in queries & searches)
957
+ # - 2: locked (same as default, but locked for edits except for space admins)
958
+ # - 1: default (visible in queries & searches)
959
+ # - 0: archive (hidden, meant to be kept, locked for edits for everyone)
960
+ # - -1: trash (hidden, scheduled for deletion)
961
+
962
+ # An integer higher than >3 codes a branch that can be used for collaborators to create drafts
963
+ # that can be merged onto the main branch in an experience akin to a Pull Request. The mapping
964
+ # onto a semantic branch name is handled through LaminHub.
945
965
 
946
966
  id: int = models.AutoField(primary_key=True)
947
967
  """An integer id that's synchronized for a family of coupled database instances.
@@ -954,8 +974,7 @@ class Branch(BaseSQLRecord):
954
974
  editable=False,
955
975
  unique=True,
956
976
  max_length=12,
957
- default="M",
958
- db_default="M",
977
+ default=base62_12,
959
978
  db_index=True,
960
979
  )
961
980
  """Universal id.
@@ -1013,33 +1032,16 @@ class SQLRecord(BaseSQLRecord, metaclass=Registry):
1013
1032
  machine learning or biological models.
1014
1033
  """
1015
1034
 
1016
- branch: int = ForeignKey(
1017
- Branch, PROTECT, default=1, db_default=1, db_column="_branch_code"
1035
+ branch: Branch = ForeignKey(
1036
+ Branch,
1037
+ PROTECT,
1038
+ default=1,
1039
+ db_default=1,
1040
+ db_column="_branch_code",
1041
+ related_name="+",
1018
1042
  )
1019
- """Whether record is on a branch or in another "special state".
1020
-
1021
- This dictates where a record appears in exploration, queries & searches,
1022
- whether a record can be edited, and whether a record acts as a template.
1023
-
1024
- Branch name coding is handled through LaminHub. "Special state" coding is as defined below.
1025
-
1026
- One should note that there is no "main" branch as in git, but that all five special codes
1027
- (-1, 0, 1, 2, 3) act as sub-specfications for what git would call the main branch. This also
1028
- means that for records that live on a branch only the "default state" exists. E.g., one can only
1029
- turn a record into a template, lock it, archive it, or trash it once it's merged onto the main
1030
- branch.
1031
-
1032
- - 3: template (hidden in queries & searches)
1033
- - 2: locked (same as default, but locked for edits except for space admins)
1034
- - 1: default (visible in queries & searches)
1035
- - 0: archive (hidden, meant to be kept, locked for edits for everyone)
1036
- - -1: trash (hidden, scheduled for deletion)
1037
-
1038
- An integer higher than >3 codes a branch that can be used for collaborators to create drafts
1039
- that can be merged onto the main branch in an experience akin to a Pull Request. The mapping
1040
- onto a semantic branch name is handled through LaminHub.
1041
- """
1042
- space: Space = ForeignKey(Space, PROTECT, default=1, db_default=1)
1043
+ """Whether record is on a branch or in another "special state"."""
1044
+ space: Space = ForeignKey(Space, PROTECT, default=1, db_default=1, related_name="+")
1043
1045
  """The space in which the record lives."""
1044
1046
  _aux: dict[str, Any] | None = JSONField(default=None, db_default=None, null=True)
1045
1047
  """Auxiliary field for dictionary-like metadata."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamindb
3
- Version: 1.6.0
3
+ Version: 1.6.1
4
4
  Summary: A data framework for biology.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Requires-Python: >=3.10,<3.14
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: 3.11
10
10
  Classifier: Programming Language :: Python :: 3.12
11
11
  Classifier: Programming Language :: Python :: 3.13
12
12
  Requires-Dist: lamin_utils==0.14.0
13
- Requires-Dist: lamin_cli==1.4.1
13
+ Requires-Dist: lamin_cli==1.4.2
14
14
  Requires-Dist: lamindb_setup[aws]==1.6.0
15
15
  Requires-Dist: pyyaml
16
16
  Requires-Dist: pyarrow
@@ -23,7 +23,7 @@ Requires-Dist: anndata>=0.8.0,<=0.11.4
23
23
  Requires-Dist: fsspec
24
24
  Requires-Dist: graphviz
25
25
  Requires-Dist: psycopg2-binary
26
- Requires-Dist: bionty>=1.4a1 ; extra == "bionty"
26
+ Requires-Dist: bionty>=1.5.0 ; extra == "bionty"
27
27
  Requires-Dist: clinicore ; extra == "clinicore"
28
28
  Requires-Dist: tomlkit ; extra == "dev"
29
29
  Requires-Dist: line_profiler ; extra == "dev"
@@ -36,6 +36,7 @@ Requires-Dist: pytest-cov ; extra == "dev"
36
36
  Requires-Dist: mudata ; extra == "dev"
37
37
  Requires-Dist: nbproject_test>=0.6.0 ; extra == "dev"
38
38
  Requires-Dist: faker-biology ; extra == "dev"
39
+ Requires-Dist: pronto ; extra == "dev"
39
40
  Requires-Dist: readfcs>=2.0.1 ; extra == "fcs"
40
41
  Requires-Dist: lamindb_setup[gcp] ; extra == "gcp"
41
42
  Requires-Dist: nbproject==0.11.1 ; extra == "jupyter"
@@ -43,7 +44,7 @@ Requires-Dist: jupytext ; extra == "jupyter"
43
44
  Requires-Dist: nbconvert>=7.2.1 ; extra == "jupyter"
44
45
  Requires-Dist: mistune!=3.1.0 ; extra == "jupyter"
45
46
  Requires-Dist: omop ; extra == "omop"
46
- Requires-Dist: wetlab>=1.3a1 ; extra == "wetlab"
47
+ Requires-Dist: wetlab>=1.3.1 ; extra == "wetlab"
47
48
  Requires-Dist: numcodecs<0.16.0 ; extra == "zarr"
48
49
  Requires-Dist: zarr>=2.16.0,<3.0.0a0 ; extra == "zarr"
49
50
  Project-URL: Home, https://github.com/laminlabs/lamindb
@@ -1,4 +1,4 @@
1
- lamindb/__init__.py,sha256=2pRNdQtclzGygpbEm5WcKu5VRNb4Uc38pB6oMbY59Zg,2928
1
+ lamindb/__init__.py,sha256=Vfp0ESD0n9EQHFmC708KHlCcMUcM0suzVEvIC1sqPM0,2928
2
2
  lamindb/_finish.py,sha256=XVEaFQQDeGvAnW3Fx-COcXCSXAvu-bIS3VkmqBS81Gs,20148
3
3
  lamindb/_tracked.py,sha256=-wK7BJv30nf4v2_nH5qDCyxHvug7ih6duQNGxDrj3UE,4447
4
4
  lamindb/_view.py,sha256=cod1RnZoLyzMVJcjWjytg78Sf4qsR8IAdqpwzsi8FTw,4950
@@ -11,7 +11,7 @@ lamindb/base/uids.py,sha256=cLBi5mIlsf1ltkTb17r1FLzlOjlGmjvsCygoVJHQ-A8,2116
11
11
  lamindb/base/users.py,sha256=8MSmAvCKoUF15YsDE6BGLBXsFWpfoEEg8iDTKZ7kD48,848
12
12
  lamindb/core/__init__.py,sha256=aaBq0UVjNolMynbT1V5hB6UrJm1tK0M6WHu_r6em9_4,604
13
13
  lamindb/core/_compat.py,sha256=NLnKk1qk4xdgMV-QwFDnBnbio02ujjlF86icvhpdv4c,2029
14
- lamindb/core/_context.py,sha256=GT9heAYluabme86oJm4n6SQt0ZShnVuBhJd3o474JVo,36005
14
+ lamindb/core/_context.py,sha256=bmQJPd2UnOQdPkWWMLnG_sZTfXPLuZyXEi3UFmttoYU,36812
15
15
  lamindb/core/_mapped_collection.py,sha256=dxyZ1ZHFn5SBl1xILqN9N6TTUJP0PptVBV-2O0EdZww,25751
16
16
  lamindb/core/_settings.py,sha256=I_h_O06BNlzhHkMiJqDlRhfbRwCWdMDjKdalNIfIZT0,6214
17
17
  lamindb/core/_sync_git.py,sha256=Z7keuyS5X7CAj285sEbZIFExZF9mtjGH8DzKwz3xhHw,5881
@@ -23,7 +23,7 @@ lamindb/core/datasets/__init__.py,sha256=x5zn_vn8D4xMJOJ9hVc8wRwQk5ea81Un2tGHb2U
23
23
  lamindb/core/datasets/_core.py,sha256=uaP0snoKuAE5nDTL_XIgPeEoXSp5sTrNNAyOPDciZRU,20286
24
24
  lamindb/core/datasets/_fake.py,sha256=BZF9R_1iF0HDnvtZNqL2FtsjSMuqDIfuFxnw_LJYIh4,953
25
25
  lamindb/core/datasets/_small.py,sha256=HBzyTporAl-6Cr4DbDDEtzbU2ILKNxxiRM-GeZofqsw,2290
26
- lamindb/core/datasets/mini_immuno.py,sha256=dSOMZYf8yaNK3ZHu4TQtYLgZNdaK5BXWyBVJhAejAyo,5703
26
+ lamindb/core/datasets/mini_immuno.py,sha256=eAtRQ3_4cln5IFzTH0jNufbWcyQKrXmzizbSmvfS-FM,5707
27
27
  lamindb/core/storage/__init__.py,sha256=JOIMu_7unbyhndtH1j0Q-9AvY8knSuc1IJO9sQnyBAQ,498
28
28
  lamindb/core/storage/_anndata_accessor.py,sha256=j7PgAxKL7bumvHja99Ldm6BtWkdGMu2Dh_sYoXocTeQ,26105
29
29
  lamindb/core/storage/_backed_access.py,sha256=LlpRDZ0skseZA5tBFu3-cH1wJwuXm7-NS2RgnTK7wgc,7382
@@ -80,15 +80,16 @@ lamindb/migrations/0097_remove_schemaparam_param_remove_paramvalue_param_and_mor
80
80
  lamindb/migrations/0098_alter_feature_type_alter_project_type_and_more.py,sha256=wy3CZNwE6mVG65AmAUyE-AIjcTQjHLv8jgFDUJCh9h0,23626
81
81
  lamindb/migrations/0099_alter_writelog_seqno.py,sha256=Sg4jbLO3dP69_A53EL2L3rwfMZ0vEZ0dNkBUso8syb4,572
82
82
  lamindb/migrations/0100_branch_alter_artifact__branch_code_and_more.py,sha256=dC1b1ntEVayNxBVEvJVVpVjqjV6qnzZxZ7Ez0qy_9j4,3158
83
- lamindb/migrations/0101_alter_artifact_hash_alter_feature_name_and_more.py,sha256=FgR_1_I3O8Gfpz-kPyl4EwX2R3LrjqdlVt_WUgM8nKk,14275
83
+ lamindb/migrations/0101_alter_artifact_hash_alter_feature_name_and_more.py,sha256=yxnVzVcoRxd-Xc2KIkR07EtlBxd3LyY4C7F8enBHBYY,14154
84
84
  lamindb/migrations/0102_remove_writelog_branch_code_and_more.py,sha256=LkedZIweHHQGytJbo3OhshLFZLMKAbp22EuW-YqoTp0,2222
85
85
  lamindb/migrations/0103_remove_writelog_migration_state_and_more.py,sha256=pipVgTTq6kmsi0ePCmfT2ajbrPrjJ1O6W5nC1DTG614,1195
86
- lamindb/migrations/0103_squashed.py,sha256=kxvlhewpDEvFHD6nREmjgprXS4aEFk-t8P9plFhZtH8,161147
86
+ lamindb/migrations/0104_alter_branch_uid.py,sha256=YHhQHblFoOG5jphqbtPg69gnkiBqw9wdVIFKVrzoRhk,12863
87
+ lamindb/migrations/0104_squashed.py,sha256=H5Yjj2pONWw9DjPjvp8YHsuDGgrofshze9yVElzT3so,162357
87
88
  lamindb/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
89
  lamindb/models/__init__.py,sha256=Pu7ugwrc_xTxaY4ZnjD5lU2RlCVF4cAa-3bKWRNbI8I,2386
89
90
  lamindb/models/_describe.py,sha256=DF_AyjxrkBqKM4E1Ym5crvyYc6oJ-EaeOda9KJKBVAU,5482
90
91
  lamindb/models/_django.py,sha256=bBu1yBJcE7RvPWor1Fp2sU0IEyrgTHxJbrDILDAvVFM,9029
91
- lamindb/models/_feature_manager.py,sha256=6SNY1gu8CX9rHkwqHp1Vwe98w0dApa9vSin3rRcQWvY,52762
92
+ lamindb/models/_feature_manager.py,sha256=8AI3iWFmPBcClbwDqBsoKWSQ8ToWcB2FVM8Ny8Xvo4w,52974
92
93
  lamindb/models/_from_values.py,sha256=cCGPMDlAbBrdhFW-XrIQVZ10q1LNg4MycYPLOkF0fTc,13366
93
94
  lamindb/models/_is_versioned.py,sha256=Th2_cBf9UWh27E6ANxg6LGmjBOumXFy7AjH0GG4FoXA,7601
94
95
  lamindb/models/_label_manager.py,sha256=ZcZuajBX7MRAbXyzkhOHypLeCYAjGJe39cP8I9cVt9M,12304
@@ -96,23 +97,23 @@ lamindb/models/_relations.py,sha256=zHYLujy9vkuB9jVq5844TpzLSP__iYNCQcsl-FzK1Jw,
96
97
  lamindb/models/artifact.py,sha256=eByxq8IpKJqs3OJzMcKqojQ17MmJ7JUQnDKHT5c_LSs,111207
97
98
  lamindb/models/artifact_set.py,sha256=VOZEGDo3m_9Yg_ftx3I2fwdydjHN61X_qV18N6xG4kM,4117
98
99
  lamindb/models/can_curate.py,sha256=ShEva1GGpJcCg7k95t99RzWfz28OFSorPFXLrGoXavE,29266
99
- lamindb/models/collection.py,sha256=Jxr1DzSqa7gYnCzhfUXaHVFMUETSNqBzijTBAgUsyqA,28210
100
+ lamindb/models/collection.py,sha256=BWoSzc5GQDFtMTXl-OjY8WhQgYR6YDe9hctibk96z24,28142
100
101
  lamindb/models/core.py,sha256=BIpqguoZwaoZ8JshHz5dZWM7u3GwObYjmN2_vLaICH8,4030
101
102
  lamindb/models/feature.py,sha256=RZG_82HS20esb8dmCW8VH-j6kiR2A9bMmJmDVaATlo8,29392
102
103
  lamindb/models/has_parents.py,sha256=aqYlCN0P8njmEt5CK5AqS_M5S1ttQz8r6FsT-t3WUTk,20328
103
- lamindb/models/project.py,sha256=FVAG6IZToVJ2PXr03UWKZGhmX4Zx8jq-Kv21tSn6o08,16420
104
+ lamindb/models/project.py,sha256=V_ooZavXIGSq1iwGQMP9zpvbs7Bg5dT_rQ1u6hZSTS4,16614
104
105
  lamindb/models/query_manager.py,sha256=4s0BNB_XaYnNaDNQgk-nzNYq2bOCEr4JsV1e1wLWzoY,10727
105
106
  lamindb/models/query_set.py,sha256=pQ5yRCYB7DkJIXBaUo_oDUTMC4Z8tapiv7sze-yqiNw,31472
106
- lamindb/models/record.py,sha256=o_En6QLcCRJ8ImUjc0n1gdYF0V2aN5nmjcZeUPSR6rE,8073
107
- lamindb/models/run.py,sha256=C92AyGxGAS5Y8Jl7skF_HSjX2DMzrGy1IKIrolb8R3s,15211
107
+ lamindb/models/record.py,sha256=mQKIEEikmbemQjNAwEwlZagQ_Xnuu-OfrUbOhzdeKJE,9518
108
+ lamindb/models/run.py,sha256=Frdcjg9-xROo4KmRaiXczztAST718-rC9aa56b_zh4o,15274
108
109
  lamindb/models/save.py,sha256=JtrEAy1D20EpRm6UmjCfZtCTBeq1RNtqzkq9mfhLFtE,13360
109
110
  lamindb/models/schema.py,sha256=oFXVxQU0GjM4ivbPYSOQaIDoC376_1vlQ-AZoQm39eM,47529
110
- lamindb/models/sqlrecord.py,sha256=yc-CxeIzrJB0tVmjWSvxN5NRSKTqpq4kR-z18AXAlNg,65014
111
+ lamindb/models/sqlrecord.py,sha256=by38XCpnLXlnBR1dqPq9GEqFTnTOXHFnw5IVf2pSAOM,64691
111
112
  lamindb/models/transform.py,sha256=lmBkk20tRoOByX3kd5DEbszT1REhBRm1NMNfQgtziKk,12203
112
113
  lamindb/models/ulabel.py,sha256=b9_wY-nsLDBuLvXdEiChjteDf0DkEQxTiLErd1qTABw,9027
113
114
  lamindb/setup/__init__.py,sha256=OwZpZzPDv5lPPGXZP7-zK6UdO4FHvvuBh439yZvIp3A,410
114
115
  lamindb/setup/core/__init__.py,sha256=SevlVrc2AZWL3uALbE5sopxBnIZPWZ1IB0NBDudiAL8,167
115
- lamindb-1.6.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
116
- lamindb-1.6.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
117
- lamindb-1.6.0.dist-info/METADATA,sha256=hM20HQFQuASx3dEg2dyGb-JTLEq8M_K0hTpdXlB-MBM,2630
118
- lamindb-1.6.0.dist-info/RECORD,,
116
+ lamindb-1.6.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
117
+ lamindb-1.6.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
118
+ lamindb-1.6.1.dist-info/METADATA,sha256=kcfzF8LUHz1Itf4fbJ0MzkZSVeIbHxQWPgMYI0UJEfE,2669
119
+ lamindb-1.6.1.dist-info/RECORD,,