lamindb 1.1.1__py3-none-any.whl → 1.2a2__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 (64) hide show
  1. lamindb/__init__.py +28 -25
  2. lamindb/_tracked.py +1 -1
  3. lamindb/_view.py +2 -3
  4. lamindb/base/__init__.py +1 -1
  5. lamindb/base/ids.py +1 -10
  6. lamindb/core/__init__.py +7 -65
  7. lamindb/core/_context.py +34 -8
  8. lamindb/core/_settings.py +6 -6
  9. lamindb/core/_sync_git.py +1 -1
  10. lamindb/core/loaders.py +9 -8
  11. lamindb/core/storage/_backed_access.py +4 -2
  12. lamindb/core/storage/_tiledbsoma.py +6 -4
  13. lamindb/core/storage/_zarr.py +32 -11
  14. lamindb/core/storage/objects.py +59 -26
  15. lamindb/core/storage/paths.py +4 -1
  16. lamindb/curators/__init__.py +97 -81
  17. lamindb/errors.py +1 -1
  18. lamindb/integrations/_vitessce.py +4 -4
  19. lamindb/migrations/0089_subsequent_runs.py +159 -0
  20. lamindb/migrations/0090_runproject_project_runs.py +73 -0
  21. lamindb/migrations/{0088_squashed.py → 0090_squashed.py} +245 -177
  22. lamindb/models/__init__.py +79 -0
  23. lamindb/{core → models}/_describe.py +3 -3
  24. lamindb/{core → models}/_django.py +8 -5
  25. lamindb/{core → models}/_feature_manager.py +103 -87
  26. lamindb/{_from_values.py → models/_from_values.py} +5 -2
  27. lamindb/{core/versioning.py → models/_is_versioned.py} +94 -6
  28. lamindb/{core → models}/_label_manager.py +10 -17
  29. lamindb/{core/relations.py → models/_relations.py} +8 -1
  30. lamindb/models/artifact.py +2601 -0
  31. lamindb/{_can_curate.py → models/can_curate.py} +349 -180
  32. lamindb/models/collection.py +683 -0
  33. lamindb/models/core.py +135 -0
  34. lamindb/models/feature.py +643 -0
  35. lamindb/models/flextable.py +163 -0
  36. lamindb/{_parents.py → models/has_parents.py} +55 -49
  37. lamindb/models/project.py +384 -0
  38. lamindb/{_query_manager.py → models/query_manager.py} +10 -8
  39. lamindb/{_query_set.py → models/query_set.py} +28 -24
  40. lamindb/models/record.py +1757 -0
  41. lamindb/models/run.py +563 -0
  42. lamindb/{_save.py → models/save.py} +9 -7
  43. lamindb/models/schema.py +732 -0
  44. lamindb/models/transform.py +360 -0
  45. lamindb/models/ulabel.py +249 -0
  46. {lamindb-1.1.1.dist-info → lamindb-1.2a2.dist-info}/METADATA +5 -5
  47. {lamindb-1.1.1.dist-info → lamindb-1.2a2.dist-info}/RECORD +49 -50
  48. lamindb/_artifact.py +0 -1379
  49. lamindb/_collection.py +0 -440
  50. lamindb/_feature.py +0 -316
  51. lamindb/_is_versioned.py +0 -40
  52. lamindb/_record.py +0 -1064
  53. lamindb/_run.py +0 -60
  54. lamindb/_schema.py +0 -347
  55. lamindb/_storage.py +0 -15
  56. lamindb/_transform.py +0 -170
  57. lamindb/_ulabel.py +0 -56
  58. lamindb/_utils.py +0 -9
  59. lamindb/base/validation.py +0 -63
  60. lamindb/core/_data.py +0 -491
  61. lamindb/core/fields.py +0 -12
  62. lamindb/models.py +0 -4475
  63. {lamindb-1.1.1.dist-info → lamindb-1.2a2.dist-info}/LICENSE +0 -0
  64. {lamindb-1.1.1.dist-info → lamindb-1.2a2.dist-info}/WHEEL +0 -0
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pathlib import PurePosixPath
4
- from typing import TYPE_CHECKING
4
+ from typing import TYPE_CHECKING, TypeAlias, TypeVar
5
5
 
6
6
  from anndata import AnnData
7
7
  from pandas import DataFrame
@@ -9,54 +9,87 @@ from pandas import DataFrame
9
9
  if TYPE_CHECKING:
10
10
  from lamindb_setup.core.types import UPathStr
11
11
 
12
+ SpatialData = TypeVar("SpatialData")
13
+ MuData = TypeVar("MuData")
12
14
 
13
- def _mudata_is_installed():
14
- try:
15
- import mudata # noqa: F401c
16
- except ImportError:
17
- return False
18
- return True
15
+ SupportedDataTypes: TypeAlias = AnnData | DataFrame | MuData | SpatialData
19
16
 
20
17
 
21
- def infer_suffix(dmem, adata_format: str | None = None):
18
+ def is_package_installed(package_name):
19
+ import importlib.util
20
+
21
+ spec = importlib.util.find_spec(package_name)
22
+ return spec is not None
23
+
24
+
25
+ def infer_suffix(dmem: SupportedDataTypes, format: str | None = None):
22
26
  """Infer LaminDB storage file suffix from a data object."""
23
27
  if isinstance(dmem, AnnData):
24
- if adata_format is not None:
25
- if adata_format not in {"h5ad", "zarr", "anndata.zarr"}:
28
+ if format is not None:
29
+ if format not in {"h5ad", "zarr", "anndata.zarr"}:
26
30
  raise ValueError(
27
31
  "Error when specifying AnnData storage format, it should be"
28
- f" 'h5ad', 'zarr', not '{adata_format}'. Check 'format'"
32
+ f" 'h5ad', 'zarr', not '{format}'. Check 'format'"
29
33
  " or the suffix of 'key'."
30
34
  )
31
- return "." + adata_format
35
+ return "." + format
32
36
  return ".h5ad"
33
- elif isinstance(dmem, DataFrame):
37
+
38
+ if isinstance(dmem, DataFrame):
34
39
  return ".parquet"
35
- else:
36
- if _mudata_is_installed():
37
- from mudata import MuData
38
40
 
39
- if isinstance(dmem, MuData):
40
- return ".h5mu"
41
+ if is_package_installed("mudata"):
42
+ from mudata import MuData
43
+
44
+ if isinstance(dmem, MuData):
45
+ return ".h5mu"
46
+
47
+ if is_package_installed("spatialdata"):
48
+ from spatialdata import SpatialData
49
+
50
+ if isinstance(dmem, SpatialData):
51
+ if format is not None:
52
+ if format not in {"spatialdata.zarr"}:
53
+ raise ValueError(
54
+ "Error when specifying SpatialData storage format, it should be"
55
+ f" 'zarr', 'spatialdata.zarr', not '{format}'. Check 'format'"
56
+ " or the suffix of 'key'."
57
+ )
58
+ return "." + format
59
+ return ".zarr"
60
+ else:
41
61
  raise NotImplementedError
42
62
 
43
63
 
44
- def write_to_disk(dmem, filepath: UPathStr):
64
+ def write_to_disk(dmem: SupportedDataTypes, filepath: UPathStr) -> None:
65
+ """Writes the passed in memory data to disk to a specified path."""
45
66
  if isinstance(dmem, AnnData):
46
67
  suffix = PurePosixPath(filepath).suffix
47
68
  if suffix == ".h5ad":
48
69
  dmem.write_h5ad(filepath)
70
+ return
49
71
  elif suffix == ".zarr":
50
72
  dmem.write_zarr(filepath)
73
+ return
51
74
  else:
52
75
  raise NotImplementedError
53
- elif isinstance(dmem, DataFrame):
76
+
77
+ if isinstance(dmem, DataFrame):
54
78
  dmem.to_parquet(filepath)
55
- else:
56
- if _mudata_is_installed():
57
- from mudata import MuData
79
+ return
80
+
81
+ if is_package_installed("mudata"):
82
+ from mudata import MuData
58
83
 
59
- if isinstance(dmem, MuData):
60
- dmem.write(filepath)
61
- return
84
+ if isinstance(dmem, MuData):
85
+ dmem.write(filepath)
86
+ return
87
+
88
+ if is_package_installed("spatialdata"):
89
+ from spatialdata import SpatialData
90
+
91
+ if isinstance(dmem, SpatialData):
92
+ dmem.write(filepath, overwrite=True)
93
+ return
94
+ else:
62
95
  raise NotImplementedError
@@ -11,13 +11,14 @@ from lamindb_setup.core.upath import (
11
11
  )
12
12
 
13
13
  from lamindb.core._settings import settings
14
- from lamindb.models import Artifact, Storage
15
14
 
16
15
  if TYPE_CHECKING:
17
16
  from pathlib import Path
18
17
 
19
18
  from lamindb_setup.core.types import UPathStr
20
19
 
20
+ from lamindb.models.artifact import Artifact
21
+
21
22
 
22
23
  AUTO_KEY_PREFIX = ".lamindb/"
23
24
 
@@ -70,6 +71,8 @@ def attempt_accessing_path(
70
71
  ) -> tuple[UPath, StorageSettings]:
71
72
  # check whether the file is in the default db and whether storage
72
73
  # matches default storage
74
+ from lamindb.models import Storage
75
+
73
76
  if (
74
77
  artifact._state.db in ("default", None)
75
78
  and artifact.storage_id == settings._storage_settings.id
@@ -9,12 +9,23 @@
9
9
  DataFrameCurator
10
10
  AnnDataCurator
11
11
 
12
+ CatManager:
13
+
14
+ .. autosummary::
15
+ :toctree: .
16
+
17
+ CatManager
18
+ DataFrameCatManager
19
+ AnnDataCatManager
20
+ MuDataCatManager
21
+ TiledbsomaCatManager
22
+ CurateLookup
23
+
12
24
  """
13
25
 
14
26
  from __future__ import annotations
15
27
 
16
28
  import copy
17
- import random
18
29
  import re
19
30
  from importlib import resources
20
31
  from itertools import chain
@@ -40,14 +51,10 @@ if TYPE_CHECKING:
40
51
 
41
52
  from lamindb.base.types import FieldAttr
42
53
  from lamindb.models import Record
43
- from lamindb._feature import parse_dtype, parse_dtype_single_cat
44
54
  from lamindb.base.types import FieldAttr # noqa
45
- from lamindb.core._data import add_labels
46
- from lamindb.core._feature_manager import parse_staged_feature_sets_from_anndata
47
55
  from lamindb.core._settings import settings
48
56
  from lamindb.models import (
49
57
  Artifact,
50
- CanCurate,
51
58
  Collection,
52
59
  Feature,
53
60
  Record,
@@ -55,9 +62,11 @@ from lamindb.models import (
55
62
  Schema,
56
63
  ULabel,
57
64
  )
65
+ from lamindb.models._feature_manager import parse_staged_feature_sets_from_anndata
66
+ from lamindb.models.artifact import add_labels, data_is_anndata
67
+ from lamindb.models.feature import parse_dtype, parse_dtype_single_cat
68
+ from lamindb.models._from_values import _format_values
58
69
 
59
- from .._artifact import data_is_anndata
60
- from .._from_values import _format_values
61
70
  from ..errors import InvalidArgument, ValidationError
62
71
 
63
72
  if TYPE_CHECKING:
@@ -68,7 +77,7 @@ if TYPE_CHECKING:
68
77
  from mudata import MuData
69
78
  from spatialdata import SpatialData
70
79
 
71
- from lamindb._query_set import RecordList
80
+ from lamindb.models.query_set import RecordList
72
81
 
73
82
 
74
83
  def strip_ansi_codes(text):
@@ -453,24 +462,31 @@ class AnnDataCurator(Curator):
453
462
  raise InvalidArgument("dataset must be AnnData-like.")
454
463
  if schema.otype != "AnnData":
455
464
  raise InvalidArgument("Schema otype must be 'AnnData'.")
456
- self._obs_curator = DataFrameCurator(
457
- self._dataset.obs, schema._get_component("obs")
458
- )
459
- self._var_curator = DataFrameCurator(
460
- self._dataset.var.T, schema._get_component("var")
461
- )
465
+ # TODO: also support slots other than obs and var
466
+ self._slots = {
467
+ slot: DataFrameCurator(
468
+ (
469
+ self._dataset.__getattribute__(slot).T
470
+ if slot == "var"
471
+ else self._dataset.__getattribute__(slot)
472
+ ),
473
+ slot_schema,
474
+ )
475
+ for slot, slot_schema in schema.slots.items()
476
+ if slot in {"obs", "var"}
477
+ }
462
478
 
463
479
  @property
464
480
  @doc_args(SLOTS_DOCSTRING)
465
481
  def slots(self) -> dict[str, DataFrameCurator]:
466
482
  """{}""" # noqa: D415
467
- return {"obs": self._obs_curator, "var": self._var_curator}
483
+ return self._slots
468
484
 
469
485
  @doc_args(VALIDATE_DOCSTRING)
470
486
  def validate(self) -> None:
471
487
  """{}""" # noqa: D415
472
- self._obs_curator.validate()
473
- self._var_curator.validate()
488
+ for _, curator in self._slots.items():
489
+ curator.validate()
474
490
 
475
491
  @doc_args(SAVE_ARTIFACT_DOCSTRING)
476
492
  def save_artifact(
@@ -483,13 +499,18 @@ class AnnDataCurator(Curator):
483
499
  ):
484
500
  """{}""" # noqa: D415
485
501
  if not self._is_validated:
486
- self.validate() # raises ValidationError if doesn't validate
487
- result = parse_dtype_single_cat(self._var_curator._schema.itype, is_itype=True)
502
+ self.validate()
488
503
  return save_artifact( # type: ignore
489
504
  self._dataset,
490
505
  description=description,
491
- fields=self._obs_curator._cat_manager.categoricals,
492
- columns_field=result["field"],
506
+ fields=self.slots["obs"]._cat_manager.categoricals,
507
+ columns_field=(
508
+ parse_dtype_single_cat(self.slots["var"]._schema.itype, is_itype=True)[
509
+ "field"
510
+ ]
511
+ if "var" in self._slots
512
+ else None
513
+ ),
493
514
  key=key,
494
515
  artifact=self._artifact,
495
516
  revises=revises,
@@ -519,8 +540,8 @@ class CatManager:
519
540
 
520
541
  If you find non-validated values, you have several options:
521
542
 
522
- - new values found in the data can be registered using :meth:`~lamindb.core.DataFrameCatManager.add_new_from`
523
- - non-validated values can be accessed using :meth:`~lamindb.core.DataFrameCatManager.non_validated` and addressed manually
543
+ - new values found in the data can be registered using :meth:`~lamindb.curators.DataFrameCatManager.add_new_from`
544
+ - non-validated values can be accessed using :meth:`~lamindb.curators.DataFrameCatManager.non_validated` and addressed manually
524
545
  """
525
546
 
526
547
  def __init__(
@@ -891,7 +912,7 @@ class AnnDataCatManager(CatManager):
891
912
  def __init__(
892
913
  self,
893
914
  data: ad.AnnData | Artifact,
894
- var_index: FieldAttr,
915
+ var_index: FieldAttr | None = None,
895
916
  categoricals: dict[str, FieldAttr] | None = None,
896
917
  obs_columns: FieldAttr = Feature.name,
897
918
  verbosity: str = "hint",
@@ -960,15 +981,16 @@ class AnnDataCatManager(CatManager):
960
981
  validated_only: bool = True,
961
982
  ):
962
983
  """Save variable records."""
963
- update_registry(
964
- values=list(self._adata.var.index),
965
- field=self.var_index,
966
- key="var_index",
967
- validated_only=validated_only,
968
- organism=self._organism,
969
- source=self._sources.get("var_index"),
970
- exclude=self._exclude.get("var_index"),
971
- )
984
+ if self.var_index is not None:
985
+ update_registry(
986
+ values=list(self._adata.var.index),
987
+ field=self.var_index,
988
+ key="var_index",
989
+ validated_only=validated_only,
990
+ organism=self._organism,
991
+ source=self._sources.get("var_index"),
992
+ exclude=self._exclude.get("var_index"),
993
+ )
972
994
 
973
995
  def add_new_from(self, key: str, **kwargs):
974
996
  """Add validated & new categories.
@@ -1004,15 +1026,19 @@ class AnnDataCatManager(CatManager):
1004
1026
 
1005
1027
  # add all validated records to the current instance
1006
1028
  self._save_from_var_index(validated_only=True)
1007
- validated_var, non_validated_var = validate_categories(
1008
- self._adata.var.index,
1009
- field=self._var_field,
1010
- key="var_index",
1011
- source=self._sources.get("var_index"),
1012
- hint_print=".add_new_from_var_index()",
1013
- exclude=self._exclude.get("var_index"),
1014
- organism=self._organism, # type: ignore
1015
- )
1029
+ if self.var_index is not None:
1030
+ validated_var, non_validated_var = validate_categories(
1031
+ self._adata.var.index,
1032
+ field=self._var_field,
1033
+ key="var_index",
1034
+ source=self._sources.get("var_index"),
1035
+ hint_print=".add_new_from_var_index()",
1036
+ exclude=self._exclude.get("var_index"),
1037
+ organism=self._organism, # type: ignore
1038
+ )
1039
+ else:
1040
+ validated_var = True
1041
+ non_validated_var = []
1016
1042
  validated_obs = self._obs_df_curator.validate()
1017
1043
  self._non_validated = self._obs_df_curator._non_validated # type: ignore
1018
1044
  if len(non_validated_var) > 0:
@@ -1711,7 +1737,7 @@ class TiledbsomaCatManager(CatManager):
1711
1737
  Returns:
1712
1738
  A saved artifact record.
1713
1739
  """
1714
- from lamindb.core._data import add_labels
1740
+ from lamindb.models.artifact import add_labels
1715
1741
 
1716
1742
  if not self._is_validated:
1717
1743
  self.validate()
@@ -1853,6 +1879,7 @@ class SpatialDataCatManager(CatManager):
1853
1879
  else:
1854
1880
  self._sdata = self._dataset
1855
1881
  self._sample_metadata_key = sample_metadata_key
1882
+ self._write_path = None
1856
1883
  self._var_fields = var_index
1857
1884
  self._verify_accessor_exists(self._var_fields.keys())
1858
1885
  self._categoricals = categoricals
@@ -2134,26 +2161,14 @@ class SpatialDataCatManager(CatManager):
2134
2161
  try:
2135
2162
  settings.verbosity = "warning"
2136
2163
 
2137
- if self._artifact is None:
2138
- # Write the SpatialData object to a random path in tmp directory
2139
- # The Artifact constructor will move it to the cache
2140
- write_path = (
2141
- f"{settings.cache_dir}/{random.randint(10**7, 10**8 - 1)}.zarr"
2142
- )
2143
- self._sdata.write(write_path)
2144
-
2145
- # Create the Artifact and associate Artifact metadata
2146
- self._artifact = Artifact(
2147
- write_path,
2148
- description=description,
2149
- key=key,
2150
- revises=revises,
2151
- run=run,
2152
- )
2153
- # According to Tim it is not easy to calculate the number of observations.
2154
- # We would have to write custom code to iterate over labels (which might not even exist at that point)
2155
- self._artifact.otype = "spatialdata"
2156
- self._artifact.save()
2164
+ self._artifact = Artifact.from_spatialdata(
2165
+ self._sdata,
2166
+ key=key,
2167
+ description=description,
2168
+ revises=revises,
2169
+ run=run,
2170
+ )
2171
+ self._artifact.save()
2157
2172
 
2158
2173
  # Link schemas
2159
2174
  feature_kwargs = check_registry_organism(
@@ -2171,7 +2186,7 @@ class SpatialDataCatManager(CatManager):
2171
2186
  """Add Schemas from SpatialData."""
2172
2187
  if obs_fields is None:
2173
2188
  obs_fields = {}
2174
- assert host.otype == "spatialdata" # noqa: S101
2189
+ assert host.otype == "SpatialData" # noqa: S101
2175
2190
 
2176
2191
  feature_sets = {}
2177
2192
 
@@ -2799,7 +2814,7 @@ class DoseHandler:
2799
2814
  return cls.UNIT_MAP.get(unit, unit)
2800
2815
 
2801
2816
  @classmethod
2802
- def validate_values(cls, values: pd.Series) -> list:
2817
+ def validate_values(cls, values: pd.Series) -> list[str]:
2803
2818
  """Validate pert_dose values with strict case checking."""
2804
2819
  errors = []
2805
2820
 
@@ -2843,7 +2858,7 @@ class TimeHandler:
2843
2858
  return unit[0].lower()
2844
2859
 
2845
2860
  @classmethod
2846
- def validate_values(cls, values: pd.Series) -> list:
2861
+ def validate_values(cls, values: pd.Series) -> list[str]:
2847
2862
  """Validate pert_time values."""
2848
2863
  errors = []
2849
2864
 
@@ -3197,8 +3212,8 @@ def validate_categories(
3197
3212
  exclude: str | list | None = None,
3198
3213
  hint_print: str | None = None,
3199
3214
  curator: CatManager | None = None,
3200
- ) -> tuple[bool, list]:
3201
- """Validate ontology terms in a pandas series using LaminDB registries.
3215
+ ) -> tuple[bool, list[str]]:
3216
+ """Validate ontology terms using LaminDB registries.
3202
3217
 
3203
3218
  Args:
3204
3219
  values: The values to validate.
@@ -3210,8 +3225,8 @@ def validate_categories(
3210
3225
  standardize: Whether to standardize the values.
3211
3226
  hint_print: The hint to print that suggests fixing non-validated values.
3212
3227
  """
3213
- from lamindb._from_values import _format_values
3214
3228
  from lamindb.core._settings import settings
3229
+ from lamindb.models._from_values import _format_values
3215
3230
 
3216
3231
  model_field = f"{field.field.model.__name__}.{field.field.name}"
3217
3232
 
@@ -3346,7 +3361,7 @@ def validate_categories_in_df(
3346
3361
  def save_artifact(
3347
3362
  data: pd.DataFrame | ad.AnnData | MuData,
3348
3363
  fields: dict[str, FieldAttr] | dict[str, dict[str, FieldAttr]],
3349
- columns_field: FieldAttr | dict[str, FieldAttr],
3364
+ columns_field: FieldAttr | dict[str, FieldAttr] | None = None,
3350
3365
  description: str | None = None,
3351
3366
  organism: str | None = None,
3352
3367
  key: str | None = None,
@@ -3372,8 +3387,7 @@ def save_artifact(
3372
3387
  Returns:
3373
3388
  The saved Artifact.
3374
3389
  """
3375
- from .._artifact import data_is_anndata, data_is_mudata
3376
- from ..core._data import add_labels
3390
+ from ..models.artifact import add_labels, data_is_anndata, data_is_mudata
3377
3391
 
3378
3392
  if artifact is None:
3379
3393
  if data_is_anndata(data):
@@ -3395,7 +3409,7 @@ def save_artifact(
3395
3409
  artifact.schema = schema
3396
3410
  artifact.save()
3397
3411
 
3398
- if organism is not None:
3412
+ if organism is not None and columns_field is not None:
3399
3413
  feature_kwargs = check_registry_organism(
3400
3414
  (
3401
3415
  list(columns_field.values())[0].field.model
@@ -3532,8 +3546,8 @@ def update_registry(
3532
3546
  exclude: Values to exclude from inspect.
3533
3547
  kwargs: Additional keyword arguments to pass to the registry model to create new records.
3534
3548
  """
3535
- from lamindb._save import save as ln_save
3536
3549
  from lamindb.core._settings import settings
3550
+ from lamindb.models.save import save as ln_save
3537
3551
 
3538
3552
  registry = field.field.model
3539
3553
  filter_kwargs = check_registry_organism(registry, organism)
@@ -3621,7 +3635,7 @@ def log_saved_labels(
3621
3635
  validated_only: bool = True,
3622
3636
  ) -> None:
3623
3637
  """Log the saved labels."""
3624
- from .._from_values import _format_values
3638
+ from ..models._from_values import _format_values
3625
3639
 
3626
3640
  model_field = colors.italic(model_field)
3627
3641
  for k, labels in labels_saved.items():
@@ -3667,12 +3681,14 @@ def _save_organism(name: str):
3667
3681
  return organism
3668
3682
 
3669
3683
 
3670
- def _ref_is_name(field: FieldAttr) -> bool | None:
3684
+ def _ref_is_name(field: FieldAttr | None) -> bool | None:
3671
3685
  """Check if the reference field is a name field."""
3672
- from .._can_curate import get_name_field
3686
+ from ..models.can_curate import get_name_field
3673
3687
 
3674
- name_field = get_name_field(field.field.model)
3675
- return field.field.name == name_field
3688
+ if field is not None:
3689
+ name_field = get_name_field(field.field.model)
3690
+ return field.field.name == name_field
3691
+ return None
3676
3692
 
3677
3693
 
3678
3694
  # backward compat constructors ------------------
@@ -3721,7 +3737,7 @@ def from_anndata(
3721
3737
  @classmethod # type: ignore
3722
3738
  def from_mudata(
3723
3739
  cls,
3724
- mdata: MuData,
3740
+ mdata: MuData | UPathStr,
3725
3741
  var_index: dict[str, dict[str, FieldAttr]],
3726
3742
  categoricals: dict[str, FieldAttr] | None = None,
3727
3743
  verbosity: str = "hint",
@@ -3761,7 +3777,7 @@ def from_tiledbsoma(
3761
3777
  @classmethod # type: ignore
3762
3778
  def from_spatialdata(
3763
3779
  cls,
3764
- sdata,
3780
+ sdata: SpatialData | UPathStr,
3765
3781
  var_index: dict[str, FieldAttr],
3766
3782
  categoricals: dict[str, dict[str, FieldAttr]] | None = None,
3767
3783
  organism: str | None = None,
lamindb/errors.py CHANGED
@@ -1,4 +1,4 @@
1
- """Exceptions.
1
+ """Errors.
2
2
 
3
3
  .. autosummary::
4
4
  :toctree: .
@@ -7,10 +7,10 @@ from typing import TYPE_CHECKING
7
7
  import lamindb_setup as ln_setup
8
8
  from lamin_utils import logger
9
9
 
10
- from lamindb._artifact import Artifact
11
- from lamindb._collection import Collection
12
- from lamindb._run import Run
13
- from lamindb._transform import Transform
10
+ from lamindb.models.artifact import Artifact
11
+ from lamindb.models.collection import Collection
12
+ from lamindb.models.run import Run
13
+ from lamindb.models.transform import Transform
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from vitessce import VitessceConfig