lamindb 0.49.3__py3-none-any.whl → 0.50.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.
@@ -1,5 +1,5 @@
1
1
  import builtins
2
- from typing import Dict, Iterable, List, Literal, NamedTuple, Optional, Set, Union
2
+ from typing import Dict, Iterable, List, NamedTuple, Optional, Union
3
3
 
4
4
  import pandas as pd
5
5
  from django.core.exceptions import FieldDoesNotExist
@@ -9,16 +9,17 @@ from lamin_utils import colors, logger
9
9
  from lamin_utils._lookup import Lookup
10
10
  from lamin_utils._search import search as base_search
11
11
  from lamindb_setup.dev._docs import doc_args
12
- from lnschema_core import ORM
13
- from lnschema_core.models import format_datetime
12
+ from lnschema_core import Registry
13
+ from lnschema_core.models import format_field_value
14
14
  from lnschema_core.types import ListLike, StrField
15
15
 
16
16
  from lamindb.dev.utils import attach_func_to_class_method
17
17
 
18
18
  from . import _TESTING
19
- from ._feature_manager import create_features_df
20
- from ._from_values import _has_species_field, get_or_create_records
19
+ from ._from_values import get_or_create_records
20
+ from .dev._feature_manager import create_features_df
21
21
  from .dev._settings import settings
22
+ from .dev._view_parents import _transform_emoji
22
23
 
23
24
  IPYTHON = getattr(builtins, "__IPYTHON__", False)
24
25
 
@@ -27,7 +28,7 @@ class ValidationError(Exception):
27
28
  pass
28
29
 
29
30
 
30
- def init_self_from_db(self: ORM, existing_record: ORM):
31
+ def init_self_from_db(self: Registry, existing_record: Registry):
31
32
  new_args = [
32
33
  getattr(existing_record, field.attname) for field in self._meta.concrete_fields
33
34
  ]
@@ -36,7 +37,7 @@ def init_self_from_db(self: ORM, existing_record: ORM):
36
37
  self._state.db = "default"
37
38
 
38
39
 
39
- def validate_required_fields(orm: ORM, kwargs):
40
+ def validate_required_fields(orm: Registry, kwargs):
40
41
  required_fields = {
41
42
  k.name for k in orm._meta.fields if not k.null and k.default is None
42
43
  }
@@ -49,7 +50,7 @@ def validate_required_fields(orm: ORM, kwargs):
49
50
  raise TypeError(f"{missing_fields} are required.")
50
51
 
51
52
 
52
- def suggest_objects_with_same_name(orm: ORM, kwargs) -> Optional[str]:
53
+ def suggest_objects_with_same_name(orm: Registry, kwargs) -> Optional[str]:
53
54
  if kwargs.get("name") is None:
54
55
  return None
55
56
  else:
@@ -65,9 +66,10 @@ def suggest_objects_with_same_name(orm: ORM, kwargs) -> Optional[str]:
65
66
  if results.index[0] == kwargs["name"]:
66
67
  return "object-with-same-name-exists"
67
68
  else:
69
+ s = "" if results.shape[0] == 1 else "s"
70
+ it = "it" if results.shape[0] == 1 else "one of them"
68
71
  msg = (
69
- "Records with similar names exist! Did you mean to load one of"
70
- " them?"
72
+ f"record{s} with similar name{s} exist! did you mean to load {it}?"
71
73
  )
72
74
  if IPYTHON:
73
75
  from IPython.display import display
@@ -79,7 +81,7 @@ def suggest_objects_with_same_name(orm: ORM, kwargs) -> Optional[str]:
79
81
  return None
80
82
 
81
83
 
82
- def __init__(orm: ORM, *args, **kwargs):
84
+ def __init__(orm: Registry, *args, **kwargs):
83
85
  if not args:
84
86
  validate_required_fields(orm, kwargs)
85
87
  from .dev._settings import settings
@@ -97,23 +99,23 @@ def __init__(orm: ORM, *args, **kwargs):
97
99
  existing_record = orm.filter(name=kwargs["name"]).one()
98
100
  if existing_record is not None:
99
101
  logger.success(
100
- f"Loaded record with exact same name{version_comment}"
102
+ f"loaded record with exact same name{version_comment}"
101
103
  )
102
104
  init_self_from_db(orm, existing_record)
103
105
  return None
104
- super(ORM, orm).__init__(**kwargs)
106
+ super(Registry, orm).__init__(**kwargs)
105
107
  elif len(args) != len(orm._meta.concrete_fields):
106
- raise ValueError("Please provide keyword arguments, not plain arguments")
108
+ raise ValueError("please provide keyword arguments, not plain arguments")
107
109
  else:
108
110
  # object is loaded from DB (**kwargs could be omitted below, I believe)
109
- super(ORM, orm).__init__(*args, **kwargs)
111
+ super(Registry, orm).__init__(*args, **kwargs)
110
112
 
111
113
 
112
114
  def view_parents(
113
115
  self,
114
116
  field: Optional[StrField] = None,
115
117
  with_children: bool = False,
116
- distance: int = 100,
118
+ distance: int = 5,
117
119
  ):
118
120
  from lamindb.dev._view_parents import view_parents as _view_parents
119
121
 
@@ -128,14 +130,14 @@ def view_parents(
128
130
 
129
131
 
130
132
  @classmethod # type:ignore
131
- @doc_args(ORM.from_values.__doc__)
132
- def from_values(cls, values: ListLike, field: StrField, **kwargs) -> List["ORM"]:
133
+ @doc_args(Registry.from_values.__doc__)
134
+ def from_values(cls, values: ListLike, field: StrField, **kwargs) -> List["Registry"]:
133
135
  """{}"""
134
136
  if isinstance(field, str):
135
137
  field = getattr(cls, field)
136
138
  if not isinstance(field, Field): # field is DeferredAttribute
137
139
  raise TypeError(
138
- "field must be a string or an ORM field, e.g., `CellType.name`!"
140
+ "field must be a string or an Registry field, e.g., `CellType.name`!"
139
141
  )
140
142
  from_bionty = True if cls.__module__.startswith("lnschema_bionty.") else False
141
143
  return get_or_create_records(
@@ -144,7 +146,7 @@ def from_values(cls, values: ListLike, field: StrField, **kwargs) -> List["ORM"]
144
146
 
145
147
 
146
148
  # From: https://stackoverflow.com/a/37648265
147
- def _order_queryset_by_ids(queryset: QuerySet, ids: Iterable):
149
+ def _order_query_set_by_ids(queryset: QuerySet, ids: Iterable):
148
150
  from django.db.models import Case, When
149
151
 
150
152
  preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(ids)])
@@ -228,13 +230,13 @@ def _search(
228
230
  result["__ratio__"] = result.pop("__ratio__")
229
231
 
230
232
  if return_queryset:
231
- return _order_queryset_by_ids(query_set, result.reset_index()["id"])
233
+ return _order_query_set_by_ids(query_set, result.reset_index()["id"])
232
234
  else:
233
235
  return result.fillna("")
234
236
 
235
237
 
236
238
  @classmethod # type: ignore
237
- @doc_args(ORM.search.__doc__)
239
+ @doc_args(Registry.search.__doc__)
238
240
  def search(
239
241
  cls,
240
242
  string: str,
@@ -260,7 +262,10 @@ def search(
260
262
  def _lookup(cls, field: Optional[StrField] = None) -> NamedTuple:
261
263
  """{}"""
262
264
  if field is None:
263
- field = get_default_str_field(cls)
265
+ if cls._meta.model.__name__ == "User":
266
+ field = cls._meta.get_field("handle").name
267
+ else:
268
+ field = get_default_str_field(cls)
264
269
  if not isinstance(field, str):
265
270
  field = field.field.name
266
271
 
@@ -276,131 +281,12 @@ def _lookup(cls, field: Optional[StrField] = None) -> NamedTuple:
276
281
 
277
282
 
278
283
  @classmethod # type: ignore
279
- @doc_args(ORM.lookup.__doc__)
284
+ @doc_args(Registry.lookup.__doc__)
280
285
  def lookup(cls, field: Optional[StrField] = None) -> NamedTuple:
281
286
  """{}"""
282
287
  return _lookup(cls=cls, field=field)
283
288
 
284
289
 
285
- def _inspect(
286
- cls,
287
- identifiers: ListLike,
288
- field: StrField,
289
- *,
290
- case_sensitive: bool = False,
291
- inspect_synonyms: bool = True,
292
- return_df: bool = False,
293
- logging: bool = True,
294
- **kwargs,
295
- ) -> Union["pd.DataFrame", Dict[str, List[str]]]:
296
- """{}"""
297
- from lamin_utils._inspect import inspect
298
-
299
- if not isinstance(field, str):
300
- field = field.field.name
301
-
302
- cls = cls.model if isinstance(cls, QuerySet) else cls
303
-
304
- return inspect(
305
- df=_filter_df_based_on_species(orm=cls, species=kwargs.get("species")),
306
- identifiers=identifiers,
307
- field=str(field),
308
- case_sensitive=case_sensitive,
309
- inspect_synonyms=inspect_synonyms,
310
- return_df=return_df,
311
- logging=logging,
312
- )
313
-
314
-
315
- @classmethod # type: ignore
316
- @doc_args(ORM.inspect.__doc__)
317
- def inspect(
318
- cls,
319
- identifiers: ListLike,
320
- field: StrField,
321
- *,
322
- case_sensitive: bool = False,
323
- inspect_synonyms: bool = True,
324
- return_df: bool = False,
325
- logging: bool = True,
326
- **kwargs,
327
- ) -> Union["pd.DataFrame", Dict[str, List[str]]]:
328
- """{}"""
329
- return _inspect(
330
- cls=cls,
331
- identifiers=identifiers,
332
- field=field,
333
- case_sensitive=case_sensitive,
334
- inspect_synonyms=inspect_synonyms,
335
- return_df=return_df,
336
- logging=logging,
337
- **kwargs,
338
- )
339
-
340
-
341
- def _map_synonyms(
342
- cls,
343
- synonyms: Iterable,
344
- *,
345
- return_mapper: bool = False,
346
- case_sensitive: bool = False,
347
- keep: Literal["first", "last", False] = "first",
348
- synonyms_field: str = "synonyms",
349
- field: Optional[str] = None,
350
- **kwargs,
351
- ) -> Union[List[str], Dict[str, str]]:
352
- """{}"""
353
- from lamin_utils._map_synonyms import map_synonyms
354
-
355
- if field is None:
356
- field = get_default_str_field(cls)
357
- if not isinstance(field, str):
358
- field = field.field.name
359
-
360
- cls = cls.model if isinstance(cls, QuerySet) else cls
361
-
362
- try:
363
- cls._meta.get_field(synonyms_field)
364
- df = _filter_df_based_on_species(orm=cls, species=kwargs.get("species"))
365
- except FieldDoesNotExist:
366
- df = pd.DataFrame()
367
- return map_synonyms(
368
- df=df,
369
- identifiers=synonyms,
370
- field=field,
371
- return_mapper=return_mapper,
372
- case_sensitive=case_sensitive,
373
- keep=keep,
374
- synonyms_field=synonyms_field,
375
- )
376
-
377
-
378
- @classmethod # type: ignore
379
- @doc_args(ORM.map_synonyms.__doc__)
380
- def map_synonyms(
381
- cls,
382
- synonyms: Iterable,
383
- *,
384
- return_mapper: bool = False,
385
- case_sensitive: bool = False,
386
- keep: Literal["first", "last", False] = "first",
387
- synonyms_field: str = "synonyms",
388
- field: Optional[str] = None,
389
- **kwargs,
390
- ) -> Union[List[str], Dict[str, str]]:
391
- """{}"""
392
- return _map_synonyms(
393
- cls=cls,
394
- synonyms=synonyms,
395
- return_mapper=return_mapper,
396
- case_sensitive=case_sensitive,
397
- keep=keep,
398
- synonyms_field=synonyms_field,
399
- field=field,
400
- **kwargs,
401
- )
402
-
403
-
404
290
  def describe(self):
405
291
  model_name = colors.green(self.__class__.__name__)
406
292
  msg = ""
@@ -433,7 +319,12 @@ def describe(self):
433
319
 
434
320
  # Display Provenance
435
321
  # display line by line the foreign key fields
436
- emojis = {"storage": "💾", "created_by": "👤", "transform": "💫", "run": "🚗"}
322
+ emojis = {
323
+ "storage": "🗃️",
324
+ "created_by": "👤",
325
+ "transform": _transform_emoji(self.transform),
326
+ "run": "🚗",
327
+ }
437
328
  if len(foreign_key_fields) > 0:
438
329
  record_msg = f"{model_name}({''.join([f'{i}={self.__getattribute__(i)}, ' for i in direct_fields])})" # noqa
439
330
  msg += f"{record_msg.rstrip(', )')})\n\n"
@@ -448,7 +339,7 @@ def describe(self):
448
339
  msg += related_msg
449
340
  # input of
450
341
  if self.input_of.exists():
451
- values = [format_datetime(i.run_at) for i in self.input_of.all()]
342
+ values = [format_field_value(i.run_at) for i in self.input_of.all()]
452
343
  msg += f"⬇️ input_of ({colors.italic('core.Run')}): {values}\n "
453
344
  msg = msg.rstrip(" ")
454
345
 
@@ -462,21 +353,19 @@ def describe(self):
462
353
  # Display Features by slot
463
354
  msg += f"{colors.green('Features')}:\n"
464
355
  # var
465
- feature_sets = self.feature_sets.exclude(ref_field__startswith="core.Feature")
356
+ feature_sets = self.feature_sets.exclude(registry="core.Feature")
466
357
  if feature_sets.exists():
467
358
  for feature_set in feature_sets.all():
468
- key_split = feature_set.ref_field.split(".")
469
- if len(key_split) != 3:
359
+ key_split = feature_set.registry.split(".")
360
+ if len(key_split) == 3:
470
361
  logger.warning(
471
- "You have a legacy entry in feature_set.field, should be format"
472
- " 'bionty.Gene.symbol'"
362
+ "you have a legacy entry in feature_set.field, should be just"
363
+ " 'bionty.Gene'"
473
364
  )
474
365
  orm_name_with_schema = f"{key_split[0]}.{key_split[1]}"
475
- field_name = key_split[2]
366
+ field_name = "id"
476
367
  related_name = feature_sets_related_models.get(orm_name_with_schema)
477
- values = (
478
- feature_set.__getattribute__(related_name).all()[:5].list(field_name)
479
- )
368
+ values = feature_set.__getattribute__(related_name).all()[:5].list("id")
480
369
  slots = self.feature_sets.through.objects.filter(
481
370
  file=self, feature_set=feature_set
482
371
  ).list("slot")
@@ -491,7 +380,7 @@ def describe(self):
491
380
 
492
381
  # obs
493
382
  # Feature, combine all features into one dataframe
494
- feature_sets = self.feature_sets.filter(ref_field__startswith="core.Feature").all()
383
+ feature_sets = self.feature_sets.filter(registry="core.Feature").all()
495
384
  if feature_sets.exists():
496
385
  features_df = create_features_df(
497
386
  file=self, feature_sets=feature_sets.all(), exclude=True
@@ -502,7 +391,7 @@ def describe(self):
502
391
  slot += " (metadata)"
503
392
  msg += f" 🗺️ {colors.bold(slot)}:\n"
504
393
  for _, row in df_slot.iterrows():
505
- labels = self.features.get_labels(row["name"], mute=True)
394
+ labels = self.get_labels(row["name"], mute=True)
506
395
  indent = ""
507
396
  if isinstance(labels, dict):
508
397
  msg += f" 🔗 {row['name']} ({row.registries})\n"
@@ -523,39 +412,12 @@ def describe(self):
523
412
  msg = msg.rstrip("\n")
524
413
  msg = msg.rstrip("Features:")
525
414
  verbosity = settings.verbosity
526
- settings.verbosity = 2
415
+ settings.verbosity = 3
527
416
  logger.info(msg)
528
417
  settings.verbosity = verbosity
529
418
 
530
419
 
531
- def set_abbr(self, value: str):
532
- try:
533
- self.add_synonym(value, save=False)
534
- except NotImplementedError:
535
- pass
536
- self.abbr = value
537
- if not self._state.adding:
538
- self.save()
539
-
540
-
541
- def _filter_df_based_on_species(
542
- orm: Union[ORM, QuerySet], species: Optional[Union[str, ORM]] = None
543
- ):
544
- import pandas as pd
545
-
546
- records = orm.all() if isinstance(orm, QuerySet) else orm.objects.all()
547
- if _has_species_field(orm):
548
- # here, we can safely import lnschema_bionty
549
- from lnschema_bionty._bionty import create_or_get_species_record
550
-
551
- species_record = create_or_get_species_record(species=species, orm=orm)
552
- if species_record is not None:
553
- records = records.filter(species__name=species_record.name)
554
-
555
- return pd.DataFrame.from_records(records.values())
556
-
557
-
558
- def get_default_str_field(orm: Union[ORM, QuerySet, Manager]) -> str:
420
+ def get_default_str_field(orm: Union[Registry, QuerySet, Manager]) -> str:
559
421
  """Get the 1st char or text field from the orm."""
560
422
  if isinstance(orm, (QuerySet, Manager)):
561
423
  orm = orm.model
@@ -583,115 +445,12 @@ def get_default_str_field(orm: Union[ORM, QuerySet, Manager]) -> str:
583
445
  return field.name
584
446
 
585
447
 
586
- def _add_or_remove_synonyms(
587
- synonym: Union[str, Iterable],
588
- record: ORM,
589
- action: Literal["add", "remove"],
590
- force: bool = False,
591
- save: Optional[bool] = None,
592
- ):
593
- """Add or remove synonyms."""
594
-
595
- def check_synonyms_in_all_records(synonyms: Set[str], record: ORM):
596
- """Errors if input synonym is associated with other records in the DB."""
597
- import pandas as pd
598
- from IPython.display import display
599
-
600
- syns_all = (
601
- record.__class__.objects.exclude(synonyms="").exclude(synonyms=None).all()
602
- )
603
- if len(syns_all) == 0:
604
- return
605
- df = pd.DataFrame(syns_all.values())
606
- df["synonyms"] = df["synonyms"].str.split("|")
607
- df = df.explode("synonyms")
608
- matches_df = df[(df["synonyms"].isin(synonyms)) & (df["id"] != record.id)]
609
- if matches_df.shape[0] > 0:
610
- records_df = pd.DataFrame(syns_all.filter(id__in=matches_df["id"]).values())
611
- logger.error(
612
- f"Input synonyms {matches_df['synonyms'].unique()} already associated"
613
- " with the following records:\n(Pass `force=True` to ignore this error)"
614
- )
615
- display(records_df)
616
- raise SystemExit(AssertionError)
617
-
618
- # passed synonyms
619
- if isinstance(synonym, str):
620
- syn_new_set = set([synonym])
621
- else:
622
- syn_new_set = set(synonym)
623
- # nothing happens when passing an empty string or list
624
- if len(syn_new_set) == 0:
625
- return
626
- # because we use | as the separator
627
- if any(["|" in i for i in syn_new_set]):
628
- raise AssertionError("A synonym can't contain '|'!")
629
-
630
- # existing synonyms
631
- syns_exist = record.synonyms
632
- if syns_exist is None or len(syns_exist) == 0:
633
- syns_exist_set = set()
634
- else:
635
- syns_exist_set = set(syns_exist.split("|"))
636
-
637
- if action == "add":
638
- if not force:
639
- check_synonyms_in_all_records(syn_new_set, record)
640
- syns_exist_set.update(syn_new_set)
641
- elif action == "remove":
642
- syns_exist_set = syns_exist_set.difference(syn_new_set)
643
-
644
- if len(syns_exist_set) == 0:
645
- syns_str = None
646
- else:
647
- syns_str = "|".join(syns_exist_set)
648
-
649
- record.synonyms = syns_str
650
-
651
- if save is None:
652
- # if record is already in DB, save the changes to DB
653
- save = not record._state.adding
654
- if save:
655
- record.save()
656
-
657
-
658
- def _check_synonyms_field_exist(record: ORM):
659
- try:
660
- record.__getattribute__("synonyms")
661
- except AttributeError:
662
- raise NotImplementedError(
663
- f"No synonyms field found in table {record.__class__.__name__}!"
664
- )
665
-
666
-
667
- def add_synonym(
668
- self,
669
- synonym: Union[str, ListLike],
670
- force: bool = False,
671
- save: Optional[bool] = None,
672
- ):
673
- _check_synonyms_field_exist(self)
674
- _add_or_remove_synonyms(
675
- synonym=synonym, record=self, force=force, action="add", save=save
676
- )
677
-
678
-
679
- def remove_synonym(self, synonym: Union[str, ListLike]):
680
- _check_synonyms_field_exist(self)
681
- _add_or_remove_synonyms(synonym=synonym, record=self, action="remove")
682
-
683
-
684
448
  METHOD_NAMES = [
685
449
  "__init__",
686
450
  "search",
687
451
  "lookup",
688
- "map_synonyms",
689
- "inspect",
690
- "add_synonym",
691
- "remove_synonym",
692
452
  "from_values",
693
453
  "describe",
694
- "set_abbr",
695
454
  "view_parents",
696
455
  ]
697
456
 
@@ -699,13 +458,13 @@ if _TESTING: # type: ignore
699
458
  from inspect import signature
700
459
 
701
460
  SIGS = {
702
- name: signature(getattr(ORM, name))
461
+ name: signature(getattr(Registry, name))
703
462
  for name in METHOD_NAMES
704
463
  if not name.startswith("__")
705
464
  }
706
465
 
707
466
  for name in METHOD_NAMES:
708
- attach_func_to_class_method(name, ORM, globals())
467
+ attach_func_to_class_method(name, Registry, globals())
709
468
 
710
469
 
711
470
  @classmethod # type: ignore
@@ -722,7 +481,7 @@ def __get_name_with_schema__(cls) -> str:
722
481
 
723
482
 
724
483
  def select_backward(cls, **expressions):
725
- logger.warning("select() is deprecated! Please rename: ORM.filter()")
484
+ logger.warning("select() is deprecated! please use: Registry.filter()")
726
485
  return cls.filter(**expressions)
727
486
 
728
487
 
@@ -731,6 +490,6 @@ def select(cls, **expressions):
731
490
  return select_backward(cls, **expressions)
732
491
 
733
492
 
734
- setattr(ORM, "__get_schema_name__", __get_schema_name__)
735
- setattr(ORM, "__get_name_with_schema__", __get_name_with_schema__)
736
- setattr(ORM, "select", select) # backward compat
493
+ setattr(Registry, "__get_schema_name__", __get_schema_name__)
494
+ setattr(Registry, "__get_name_with_schema__", __get_name_with_schema__)
495
+ setattr(Registry, "select", select) # backward compat
lamindb/_save.py CHANGED
@@ -9,7 +9,7 @@ from typing import Iterable, List, Optional, Tuple, Union, overload # noqa
9
9
  import lamindb_setup
10
10
  from django.db import transaction
11
11
  from lamin_utils import logger
12
- from lnschema_core.models import ORM, File
12
+ from lnschema_core.models import File, Registry
13
13
 
14
14
  from lamindb.dev.storage import store_object
15
15
  from lamindb.dev.storage.file import (
@@ -26,8 +26,8 @@ except ImportError:
26
26
  raise ImportError("Please install zarr: pip install zarr")
27
27
 
28
28
 
29
- def save(records: Iterable[ORM], **kwargs) -> None: # type: ignore
30
- """Bulk save to database & storage.
29
+ def save(records: Iterable[Registry], **kwargs) -> None: # type: ignore
30
+ """Bulk save to registries & storage.
31
31
 
32
32
  Note:
33
33
 
@@ -36,10 +36,10 @@ def save(records: Iterable[ORM], **kwargs) -> None: # type: ignore
36
36
  Warning:
37
37
 
38
38
  It neither automatically creates related records nor updates existing records!
39
- Use ``ORM.save()`` for these use cases.
39
+ Use ``Registry.save()`` for these use cases.
40
40
 
41
41
  Args:
42
- records: One or multiple ``ORM`` objects.
42
+ records: One or multiple ``Registry`` objects.
43
43
 
44
44
  Examples:
45
45
 
@@ -63,7 +63,7 @@ def save(records: Iterable[ORM], **kwargs) -> None: # type: ignore
63
63
  """
64
64
  if isinstance(records, Iterable):
65
65
  records = set(records)
66
- elif isinstance(records, ORM):
66
+ elif isinstance(records, Registry):
67
67
  records = {records}
68
68
 
69
69
  # we're distinguishing between files and non-files
@@ -86,11 +86,11 @@ def save(records: Iterable[ORM], **kwargs) -> None: # type: ignore
86
86
  ):
87
87
  # save the record with parents one by one
88
88
  logger.warning(
89
- "Now recursing through parents: "
89
+ "now recursing through parents: "
90
90
  "this only happens once, but is much slower than bulk saving"
91
91
  )
92
92
  logger.hint(
93
- "You can switch this off via: lb.settings.auto_save_parents = False"
93
+ "you can switch this off via: lb.settings.auto_save_parents = False"
94
94
  )
95
95
  for record in non_files_with_parents:
96
96
  record._save_ontology_parents()
@@ -107,7 +107,7 @@ def save(records: Iterable[ORM], **kwargs) -> None: # type: ignore
107
107
  return None
108
108
 
109
109
 
110
- def bulk_create(records: Iterable[ORM]):
110
+ def bulk_create(records: Iterable[Registry]):
111
111
  records_by_orm = defaultdict(list)
112
112
  for record in records:
113
113
  records_by_orm[record.__class__].append(record)
@@ -123,7 +123,7 @@ def check_and_attempt_upload(file: File) -> Optional[Exception]:
123
123
  try:
124
124
  upload_data_object(file)
125
125
  except Exception as exception:
126
- logger.warning(f"Could not upload file: {file}")
126
+ logger.warning(f"could not upload file: {file}")
127
127
  return exception
128
128
  # copies (if ob-disk) or moves the temporary file (if in-memory) to the cache
129
129
  copy_or_move_to_cache(file)
@@ -173,7 +173,7 @@ def check_and_attempt_clearing(file: File) -> Optional[Exception]:
173
173
  if file._clear_storagekey is not None:
174
174
  delete_storage_using_key(file, file._clear_storagekey)
175
175
  logger.success(
176
- f"Deleted stale object at storage key {file._clear_storagekey}"
176
+ f"deleted stale object at storage key {file._clear_storagekey}"
177
177
  )
178
178
  file._clear_storagekey = None
179
179
  except Exception as exception:
@@ -238,15 +238,16 @@ def upload_data_object(file) -> None:
238
238
  """Store and add file and its linked entries."""
239
239
  # do NOT hand-craft the storage key!
240
240
  file_storage_key = auto_storage_key_from_file(file)
241
+ msg = f"storing file '{file.id}' with key '{file_storage_key}'"
241
242
  if hasattr(file, "_to_store") and file._to_store and file.suffix != ".zarr":
242
- logger.hint(f"storing file {file.id} with key {file_storage_key}")
243
+ logger.save(msg)
243
244
  store_object(file._local_filepath, file_storage_key)
244
245
  elif (
245
246
  file.suffix in {".zarr", ".zrad"}
246
247
  and hasattr(file, "_memory_rep")
247
248
  and file._memory_rep is not None
248
249
  ):
249
- logger.hint(f"storing file {file.id} with key {file_storage_key}")
250
+ logger.save(msg)
250
251
  storagepath = lamindb_setup.settings.storage.key_to_filepath(file_storage_key)
251
252
  print_progress = partial(
252
253
  print_hook, filepath=file_storage_key, action="uploading"