lamindb 0.76.8__py3-none-any.whl → 0.76.9__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 (61) hide show
  1. lamindb/__init__.py +113 -113
  2. lamindb/_artifact.py +1205 -1205
  3. lamindb/_can_validate.py +579 -579
  4. lamindb/_collection.py +389 -387
  5. lamindb/_curate.py +1601 -1601
  6. lamindb/_feature.py +155 -155
  7. lamindb/_feature_set.py +242 -242
  8. lamindb/_filter.py +23 -23
  9. lamindb/_finish.py +256 -256
  10. lamindb/_from_values.py +382 -382
  11. lamindb/_is_versioned.py +40 -40
  12. lamindb/_parents.py +476 -476
  13. lamindb/_query_manager.py +125 -125
  14. lamindb/_query_set.py +362 -362
  15. lamindb/_record.py +649 -649
  16. lamindb/_run.py +57 -57
  17. lamindb/_save.py +308 -308
  18. lamindb/_storage.py +14 -14
  19. lamindb/_transform.py +127 -127
  20. lamindb/_ulabel.py +56 -56
  21. lamindb/_utils.py +9 -9
  22. lamindb/_view.py +72 -72
  23. lamindb/core/__init__.py +94 -94
  24. lamindb/core/_context.py +574 -574
  25. lamindb/core/_data.py +438 -438
  26. lamindb/core/_feature_manager.py +867 -867
  27. lamindb/core/_label_manager.py +253 -253
  28. lamindb/core/_mapped_collection.py +631 -597
  29. lamindb/core/_settings.py +187 -187
  30. lamindb/core/_sync_git.py +138 -138
  31. lamindb/core/_track_environment.py +27 -27
  32. lamindb/core/datasets/__init__.py +59 -59
  33. lamindb/core/datasets/_core.py +581 -571
  34. lamindb/core/datasets/_fake.py +36 -36
  35. lamindb/core/exceptions.py +90 -90
  36. lamindb/core/fields.py +12 -12
  37. lamindb/core/loaders.py +164 -164
  38. lamindb/core/schema.py +56 -56
  39. lamindb/core/storage/__init__.py +25 -25
  40. lamindb/core/storage/_anndata_accessor.py +740 -740
  41. lamindb/core/storage/_anndata_sizes.py +41 -41
  42. lamindb/core/storage/_backed_access.py +98 -98
  43. lamindb/core/storage/_tiledbsoma.py +204 -204
  44. lamindb/core/storage/_valid_suffixes.py +21 -21
  45. lamindb/core/storage/_zarr.py +110 -110
  46. lamindb/core/storage/objects.py +62 -62
  47. lamindb/core/storage/paths.py +172 -172
  48. lamindb/core/subsettings/__init__.py +12 -12
  49. lamindb/core/subsettings/_creation_settings.py +38 -38
  50. lamindb/core/subsettings/_transform_settings.py +21 -21
  51. lamindb/core/types.py +19 -19
  52. lamindb/core/versioning.py +158 -158
  53. lamindb/integrations/__init__.py +12 -12
  54. lamindb/integrations/_vitessce.py +107 -107
  55. lamindb/setup/__init__.py +14 -14
  56. lamindb/setup/core/__init__.py +4 -4
  57. {lamindb-0.76.8.dist-info → lamindb-0.76.9.dist-info}/LICENSE +201 -201
  58. {lamindb-0.76.8.dist-info → lamindb-0.76.9.dist-info}/METADATA +4 -4
  59. lamindb-0.76.9.dist-info/RECORD +60 -0
  60. {lamindb-0.76.8.dist-info → lamindb-0.76.9.dist-info}/WHEEL +1 -1
  61. lamindb-0.76.8.dist-info/RECORD +0 -60
@@ -1,158 +1,158 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Literal
4
-
5
- from lamin_utils import logger
6
- from lamin_utils._base62 import CHARSET_DEFAULT as BASE62_CHARS
7
- from lamindb_setup.core.upath import LocalPathClasses, UPath
8
- from lnschema_core import ids
9
-
10
- if TYPE_CHECKING:
11
- from lnschema_core.models import IsVersioned
12
-
13
-
14
- def message_update_key_in_version_family(
15
- *,
16
- suid: str,
17
- existing_key: str,
18
- registry: str,
19
- new_key: str,
20
- ) -> str:
21
- return f'Or update key "{existing_key}" in your existing family:\n\nln.{registry}.filter(uid__startswith="{suid}").update(key="{new_key}")'
22
-
23
-
24
- def increment_base62(s: str) -> str:
25
- # we don't need to throw an error for zzzz because uids are enforced to be unique
26
- # on the db level and have an enforced maximum length
27
- value = sum(BASE62_CHARS.index(c) * (62**i) for i, c in enumerate(reversed(s)))
28
- value += 1
29
- result = ""
30
- while value:
31
- value, remainder = divmod(value, 62)
32
- result = BASE62_CHARS[remainder] + result
33
- return result.zfill(len(s))
34
-
35
-
36
- def bump_version(
37
- version: str,
38
- bump_type: str = "minor",
39
- behavior: Literal["prompt", "error", "ignore"] = "error",
40
- ) -> str:
41
- """Bumps the version number by major or minor depending on the bump_type flag.
42
-
43
- Parameters:
44
- version (str): The current version in "MAJOR" or "MAJOR.MINOR" format.
45
- bump_type (str): The type of version bump, either 'major' or 'minor'.
46
-
47
- Returns:
48
- str: The new version string.
49
- """
50
- try:
51
- # Split the version into major and minor parts if possible
52
- parts = version.split(".")
53
- major = int(parts[0])
54
- minor = int(parts[1]) if len(parts) > 1 else 0
55
-
56
- if bump_type == "major":
57
- # Bump the major version and reset the minor version
58
- new_version = f"{major + 1}"
59
- elif bump_type == "minor":
60
- # Bump the minor version
61
- new_version = f"{major}.{minor + 1}"
62
- else:
63
- raise ValueError("bump_type must be 'major' or 'minor'")
64
-
65
- except (ValueError, IndexError):
66
- if behavior == "prompt":
67
- new_version = input(
68
- f"The current version is '{version}' - please type the new version: "
69
- )
70
- elif behavior == "error":
71
- raise ValueError(
72
- "Cannot auto-increment non-integer castable version, please provide"
73
- " manually"
74
- ) from None
75
- else:
76
- logger.warning("could not auto-increment version, fix '?' manually")
77
- new_version = "?"
78
- return new_version
79
-
80
-
81
- def set_version(version: str | None = None, previous_version: str | None = None):
82
- """(Auto-) set version.
83
-
84
- If `version` is `None`, returns the stored version.
85
- Otherwise sets the version to the passed version.
86
-
87
- Args:
88
- version: Version string.
89
- previous_version: Previous version string.
90
- """
91
- if version is None and previous_version is not None:
92
- version = bump_version(previous_version, bump_type="major")
93
- return version
94
-
95
-
96
- def create_uid(
97
- *,
98
- version: str | None = None,
99
- n_full_id: int = 20,
100
- revises: IsVersioned | None = None,
101
- ) -> tuple[str, IsVersioned | None]:
102
- """This also updates revises in case it's not the latest version.
103
-
104
- This is why it returns revises.
105
- """
106
- if revises is not None:
107
- if not revises.is_latest:
108
- # need one more request
109
- revises = revises.__class__.objects.get(
110
- is_latest=True, uid__startswith=revises.stem_uid
111
- )
112
- logger.warning(
113
- f"didn't pass the latest version in `revises`, retrieved it: {revises}"
114
- )
115
- suid = revises.stem_uid
116
- vuid = increment_base62(revises.uid[-4:])
117
- else:
118
- suid = ids.base62(n_full_id - 4)
119
- vuid = "0000"
120
- if version is not None:
121
- if not isinstance(version, str):
122
- raise ValueError(
123
- "`version` parameter must be `None` or `str`, e.g., '0.1', '1', '2',"
124
- " etc."
125
- )
126
- if revises is not None:
127
- if version == revises.version:
128
- raise ValueError(
129
- f"Please increment the previous version: '{revises.version}'"
130
- )
131
- return suid + vuid, revises
132
-
133
-
134
- def get_new_path_from_uid(old_path: UPath, old_uid: str, new_uid: str):
135
- if isinstance(old_path, LocalPathClasses):
136
- # for local path, the rename target must be full path
137
- new_path = old_path.as_posix().replace(old_uid, new_uid)
138
- else:
139
- # for cloud path, the rename target must be the last part of the path
140
- new_path = old_path.name.replace(old_uid, new_uid)
141
- return new_path
142
-
143
-
144
- def process_revises(
145
- revises: IsVersioned | None,
146
- version: str | None,
147
- name: str | None,
148
- type: type[IsVersioned],
149
- ) -> tuple[str, str, str, IsVersioned | None]:
150
- if revises is not None and not isinstance(revises, type):
151
- raise TypeError(f"`revises` has to be of type `{type.__name__}`")
152
- uid, revises = create_uid(
153
- revises=revises, version=version, n_full_id=type._len_full_uid
154
- )
155
- if revises is not None:
156
- if name is None:
157
- name = revises.name
158
- return uid, version, name, revises
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Literal
4
+
5
+ from lamin_utils import logger
6
+ from lamin_utils._base62 import CHARSET_DEFAULT as BASE62_CHARS
7
+ from lamindb_setup.core.upath import LocalPathClasses, UPath
8
+ from lnschema_core import ids
9
+
10
+ if TYPE_CHECKING:
11
+ from lnschema_core.models import IsVersioned
12
+
13
+
14
+ def message_update_key_in_version_family(
15
+ *,
16
+ suid: str,
17
+ existing_key: str,
18
+ registry: str,
19
+ new_key: str,
20
+ ) -> str:
21
+ return f'Or update key "{existing_key}" to "{new_key}":\n\nln.{registry}.filter(uid__startswith="{suid}").update(key="{new_key}")\n'
22
+
23
+
24
+ def increment_base62(s: str) -> str:
25
+ # we don't need to throw an error for zzzz because uids are enforced to be unique
26
+ # on the db level and have an enforced maximum length
27
+ value = sum(BASE62_CHARS.index(c) * (62**i) for i, c in enumerate(reversed(s)))
28
+ value += 1
29
+ result = ""
30
+ while value:
31
+ value, remainder = divmod(value, 62)
32
+ result = BASE62_CHARS[remainder] + result
33
+ return result.zfill(len(s))
34
+
35
+
36
+ def bump_version(
37
+ version: str,
38
+ bump_type: str = "minor",
39
+ behavior: Literal["prompt", "error", "ignore"] = "error",
40
+ ) -> str:
41
+ """Bumps the version number by major or minor depending on the bump_type flag.
42
+
43
+ Parameters:
44
+ version (str): The current version in "MAJOR" or "MAJOR.MINOR" format.
45
+ bump_type (str): The type of version bump, either 'major' or 'minor'.
46
+
47
+ Returns:
48
+ str: The new version string.
49
+ """
50
+ try:
51
+ # Split the version into major and minor parts if possible
52
+ parts = version.split(".")
53
+ major = int(parts[0])
54
+ minor = int(parts[1]) if len(parts) > 1 else 0
55
+
56
+ if bump_type == "major":
57
+ # Bump the major version and reset the minor version
58
+ new_version = f"{major + 1}"
59
+ elif bump_type == "minor":
60
+ # Bump the minor version
61
+ new_version = f"{major}.{minor + 1}"
62
+ else:
63
+ raise ValueError("bump_type must be 'major' or 'minor'")
64
+
65
+ except (ValueError, IndexError):
66
+ if behavior == "prompt":
67
+ new_version = input(
68
+ f"The current version is '{version}' - please type the new version: "
69
+ )
70
+ elif behavior == "error":
71
+ raise ValueError(
72
+ "Cannot auto-increment non-integer castable version, please provide"
73
+ " manually"
74
+ ) from None
75
+ else:
76
+ logger.warning("could not auto-increment version, fix '?' manually")
77
+ new_version = "?"
78
+ return new_version
79
+
80
+
81
+ def set_version(version: str | None = None, previous_version: str | None = None):
82
+ """(Auto-) set version.
83
+
84
+ If `version` is `None`, returns the stored version.
85
+ Otherwise sets the version to the passed version.
86
+
87
+ Args:
88
+ version: Version string.
89
+ previous_version: Previous version string.
90
+ """
91
+ if version is None and previous_version is not None:
92
+ version = bump_version(previous_version, bump_type="major")
93
+ return version
94
+
95
+
96
+ def create_uid(
97
+ *,
98
+ version: str | None = None,
99
+ n_full_id: int = 20,
100
+ revises: IsVersioned | None = None,
101
+ ) -> tuple[str, IsVersioned | None]:
102
+ """This also updates revises in case it's not the latest version.
103
+
104
+ This is why it returns revises.
105
+ """
106
+ if revises is not None:
107
+ if not revises.is_latest:
108
+ # need one more request
109
+ revises = revises.__class__.objects.get(
110
+ is_latest=True, uid__startswith=revises.stem_uid
111
+ )
112
+ logger.warning(
113
+ f"didn't pass the latest version in `revises`, retrieved it: {revises}"
114
+ )
115
+ suid = revises.stem_uid
116
+ vuid = increment_base62(revises.uid[-4:])
117
+ else:
118
+ suid = ids.base62(n_full_id - 4)
119
+ vuid = "0000"
120
+ if version is not None:
121
+ if not isinstance(version, str):
122
+ raise ValueError(
123
+ "`version` parameter must be `None` or `str`, e.g., '0.1', '1', '2',"
124
+ " etc."
125
+ )
126
+ if revises is not None:
127
+ if version == revises.version:
128
+ raise ValueError(
129
+ f"Please increment the previous version: '{revises.version}'"
130
+ )
131
+ return suid + vuid, revises
132
+
133
+
134
+ def get_new_path_from_uid(old_path: UPath, old_uid: str, new_uid: str):
135
+ if isinstance(old_path, LocalPathClasses):
136
+ # for local path, the rename target must be full path
137
+ new_path = old_path.as_posix().replace(old_uid, new_uid)
138
+ else:
139
+ # for cloud path, the rename target must be the last part of the path
140
+ new_path = old_path.name.replace(old_uid, new_uid)
141
+ return new_path
142
+
143
+
144
+ def process_revises(
145
+ revises: IsVersioned | None,
146
+ version: str | None,
147
+ name: str | None,
148
+ type: type[IsVersioned],
149
+ ) -> tuple[str, str, str, IsVersioned | None]:
150
+ if revises is not None and not isinstance(revises, type):
151
+ raise TypeError(f"`revises` has to be of type `{type.__name__}`")
152
+ uid, revises = create_uid(
153
+ revises=revises, version=version, n_full_id=type._len_full_uid
154
+ )
155
+ if revises is not None:
156
+ if name is None:
157
+ name = revises.name
158
+ return uid, version, name, revises
@@ -1,12 +1,12 @@
1
- """Integrations.
2
-
3
- .. autosummary::
4
- :toctree: .
5
-
6
- save_vitessce_config
7
- save_tiledbsoma_experiment
8
- """
9
-
10
- from lamindb.core.storage import save_tiledbsoma_experiment
11
-
12
- from ._vitessce import save_vitessce_config
1
+ """Integrations.
2
+
3
+ .. autosummary::
4
+ :toctree: .
5
+
6
+ save_vitessce_config
7
+ save_tiledbsoma_experiment
8
+ """
9
+
10
+ from lamindb.core.storage import save_tiledbsoma_experiment
11
+
12
+ from ._vitessce import save_vitessce_config
@@ -1,107 +1,107 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from datetime import datetime, timezone
5
- from typing import TYPE_CHECKING
6
-
7
- import lamindb_setup as ln_setup
8
- from lamin_utils import logger
9
-
10
- from lamindb._artifact import Artifact
11
- from lamindb._run import Run
12
- from lamindb._transform import Transform
13
-
14
- if TYPE_CHECKING:
15
- from vitessce import VitessceConfig
16
-
17
-
18
- # "unit test": https://github.com/laminlabs/lamindb/blob/main/docs/storage/vitessce.ipynb
19
- # integration test & context: https://github.com/laminlabs/lamin-spatial/blob/main/docs/vitessce.ipynb
20
- def save_vitessce_config(
21
- vitessce_config: VitessceConfig, description: str | None = None
22
- ) -> Artifact:
23
- """Validates and saves a ``VitessceConfig`` object.
24
-
25
- Guide: :doc:`docs:vitessce`.
26
-
27
- Args:
28
- vitessce_config (``VitessceConfig``): A `VitessceConfig` object.
29
- description: A description for the `VitessceConfig` artifact.
30
-
31
- .. versionchanged:: 0.75.1
32
- Now displays the "Vitessce button" on the hub next to the dataset. It additionally keeps displaying it next to the configuration file.
33
- .. versionchanged:: 0.70.2
34
- No longer saves the dataset. It only saves the `VitessceConfig` object.
35
- """
36
- # can only import here because vitessce is not a dependency
37
- from vitessce import VitessceConfig
38
-
39
- from lamindb.core.storage import VALID_SUFFIXES
40
-
41
- assert isinstance(vitessce_config, VitessceConfig) # noqa: S101
42
- vc_dict = vitessce_config.to_dict()
43
- valid_composite_zarr_suffixes = [
44
- suffix for suffix in VALID_SUFFIXES.COMPOSITE if suffix.endswith(".zarr")
45
- ]
46
- # validate
47
- dataset_artifacts = []
48
- assert vc_dict["datasets"] # noqa: S101
49
- for vitessce_dataset in vc_dict["datasets"]:
50
- # didn't find good ways to violate the below, hence using plain asserts
51
- # without user feedback
52
- assert "files" in vitessce_dataset # noqa: S101
53
- assert vitessce_dataset["files"] # noqa: S101
54
- for file in vitessce_dataset["files"]:
55
- if "url" not in file:
56
- raise ValueError("Each file must have a 'url' key.")
57
- s3_path = file["url"]
58
- s3_path_last_element = s3_path.split("/")[-1]
59
- # now start with attempting to strip the composite suffix candidates
60
- for suffix in valid_composite_zarr_suffixes:
61
- s3_path_last_element = s3_path_last_element.replace(suffix, "")
62
- # in case there was no hit, strip plain ".zarr"
63
- artifact_stem_uid = s3_path_last_element.replace(".zarr", "")
64
- # if there is still a "." in string, raise an error
65
- if "." in artifact_stem_uid:
66
- raise ValueError(
67
- f"Suffix should be '.zarr' or one of {valid_composite_zarr_suffixes}. Inspect your path {s3_path}"
68
- )
69
- artifact = Artifact.filter(uid__startswith=artifact_stem_uid).one_or_none()
70
- if artifact is None:
71
- raise ValueError(
72
- f"Could not find dataset with stem uid '{artifact_stem_uid}' in lamindb: {vitessce_dataset}. Did you follow https://docs.lamin.ai/vitessce? It appears the AWS S3 path doesn't encode a lamindb uid."
73
- )
74
- else:
75
- dataset_artifacts.append(artifact)
76
- # the below will be replaced with a `ln.tracked()` decorator soon
77
- with logger.mute():
78
- transform = Transform(
79
- uid="kup03MJBsIVa0001",
80
- name="save_vitessce_config",
81
- type="function",
82
- version="2",
83
- ).save()
84
- run = Run(transform=transform).save()
85
- if len(dataset_artifacts) > 1:
86
- # if we have more datasets, we should create a collection
87
- # and attach an action to the collection
88
- raise NotImplementedError
89
- run.input_artifacts.set(dataset_artifacts)
90
- # create a JSON export
91
- config_file_local_path = (
92
- ln_setup.settings.storage.cache_dir / "config.vitessce.json"
93
- )
94
- with open(config_file_local_path, "w") as file:
95
- json.dump(vc_dict, file)
96
- vitessce_config_artifact = Artifact(
97
- config_file_local_path, description=description, run=run
98
- ).save()
99
- # we have one and only one dataset artifact, hence the following line is OK
100
- dataset_artifacts[0]._actions.add(vitessce_config_artifact)
101
- slug = ln_setup.settings.instance.slug
102
- logger.important(
103
- f"go to: https://lamin.ai/{slug}/artifact/{vitessce_config_artifact.uid}"
104
- )
105
- run.finished_at = datetime.now(timezone.utc)
106
- run.save()
107
- return vitessce_config_artifact
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from datetime import datetime, timezone
5
+ from typing import TYPE_CHECKING
6
+
7
+ import lamindb_setup as ln_setup
8
+ from lamin_utils import logger
9
+
10
+ from lamindb._artifact import Artifact
11
+ from lamindb._run import Run
12
+ from lamindb._transform import Transform
13
+
14
+ if TYPE_CHECKING:
15
+ from vitessce import VitessceConfig
16
+
17
+
18
+ # "unit test": https://github.com/laminlabs/lamindb/blob/main/docs/storage/vitessce.ipynb
19
+ # integration test & context: https://github.com/laminlabs/lamin-spatial/blob/main/docs/vitessce.ipynb
20
+ def save_vitessce_config(
21
+ vitessce_config: VitessceConfig, description: str | None = None
22
+ ) -> Artifact:
23
+ """Validates and saves a ``VitessceConfig`` object.
24
+
25
+ Guide: :doc:`docs:vitessce`.
26
+
27
+ Args:
28
+ vitessce_config (``VitessceConfig``): A `VitessceConfig` object.
29
+ description: A description for the `VitessceConfig` artifact.
30
+
31
+ .. versionchanged:: 0.75.1
32
+ Now displays the "Vitessce button" on the hub next to the dataset. It additionally keeps displaying it next to the configuration file.
33
+ .. versionchanged:: 0.70.2
34
+ No longer saves the dataset. It only saves the `VitessceConfig` object.
35
+ """
36
+ # can only import here because vitessce is not a dependency
37
+ from vitessce import VitessceConfig
38
+
39
+ from lamindb.core.storage import VALID_SUFFIXES
40
+
41
+ assert isinstance(vitessce_config, VitessceConfig) # noqa: S101
42
+ vc_dict = vitessce_config.to_dict()
43
+ valid_composite_zarr_suffixes = [
44
+ suffix for suffix in VALID_SUFFIXES.COMPOSITE if suffix.endswith(".zarr")
45
+ ]
46
+ # validate
47
+ dataset_artifacts = []
48
+ assert vc_dict["datasets"] # noqa: S101
49
+ for vitessce_dataset in vc_dict["datasets"]:
50
+ # didn't find good ways to violate the below, hence using plain asserts
51
+ # without user feedback
52
+ assert "files" in vitessce_dataset # noqa: S101
53
+ assert vitessce_dataset["files"] # noqa: S101
54
+ for file in vitessce_dataset["files"]:
55
+ if "url" not in file:
56
+ raise ValueError("Each file must have a 'url' key.")
57
+ s3_path = file["url"]
58
+ s3_path_last_element = s3_path.split("/")[-1]
59
+ # now start with attempting to strip the composite suffix candidates
60
+ for suffix in valid_composite_zarr_suffixes:
61
+ s3_path_last_element = s3_path_last_element.replace(suffix, "")
62
+ # in case there was no hit, strip plain ".zarr"
63
+ artifact_stem_uid = s3_path_last_element.replace(".zarr", "")
64
+ # if there is still a "." in string, raise an error
65
+ if "." in artifact_stem_uid:
66
+ raise ValueError(
67
+ f"Suffix should be '.zarr' or one of {valid_composite_zarr_suffixes}. Inspect your path {s3_path}"
68
+ )
69
+ artifact = Artifact.filter(uid__startswith=artifact_stem_uid).one_or_none()
70
+ if artifact is None:
71
+ raise ValueError(
72
+ f"Could not find dataset with stem uid '{artifact_stem_uid}' in lamindb: {vitessce_dataset}. Did you follow https://docs.lamin.ai/vitessce? It appears the AWS S3 path doesn't encode a lamindb uid."
73
+ )
74
+ else:
75
+ dataset_artifacts.append(artifact)
76
+ # the below will be replaced with a `ln.tracked()` decorator soon
77
+ with logger.mute():
78
+ transform = Transform(
79
+ uid="kup03MJBsIVa0001",
80
+ name="save_vitessce_config",
81
+ type="function",
82
+ version="2",
83
+ ).save()
84
+ run = Run(transform=transform).save()
85
+ if len(dataset_artifacts) > 1:
86
+ # if we have more datasets, we should create a collection
87
+ # and attach an action to the collection
88
+ raise NotImplementedError
89
+ run.input_artifacts.set(dataset_artifacts)
90
+ # create a JSON export
91
+ config_file_local_path = (
92
+ ln_setup.settings.storage.cache_dir / "config.vitessce.json"
93
+ )
94
+ with open(config_file_local_path, "w") as file:
95
+ json.dump(vc_dict, file)
96
+ vitessce_config_artifact = Artifact(
97
+ config_file_local_path, description=description, run=run
98
+ ).save()
99
+ # we have one and only one dataset artifact, hence the following line is OK
100
+ dataset_artifacts[0]._actions.add(vitessce_config_artifact)
101
+ slug = ln_setup.settings.instance.slug
102
+ logger.important(
103
+ f"go to: https://lamin.ai/{slug}/artifact/{vitessce_config_artifact.uid}"
104
+ )
105
+ run.finished_at = datetime.now(timezone.utc)
106
+ run.save()
107
+ return vitessce_config_artifact
lamindb/setup/__init__.py CHANGED
@@ -1,14 +1,14 @@
1
- import lamindb_setup as _lamindb_setup
2
- from lamindb_setup import * # noqa: F403
3
- from lamindb_setup import (
4
- connect,
5
- delete,
6
- init,
7
- settings,
8
- )
9
-
10
- from . import core
11
-
12
- del connect # we have this at the root level, hence, we don't want it here
13
- __doc__ = _lamindb_setup.__doc__.replace("lamindb_setup", "lamindb.setup")
14
- settings.__doc__ = settings.__doc__.replace("lamindb_setup", "lamindb.setup")
1
+ import lamindb_setup as _lamindb_setup
2
+ from lamindb_setup import * # noqa: F403
3
+ from lamindb_setup import (
4
+ connect,
5
+ delete,
6
+ init,
7
+ settings,
8
+ )
9
+
10
+ from . import core
11
+
12
+ del connect # we have this at the root level, hence, we don't want it here
13
+ __doc__ = _lamindb_setup.__doc__.replace("lamindb_setup", "lamindb.setup")
14
+ settings.__doc__ = settings.__doc__.replace("lamindb_setup", "lamindb.setup")
@@ -1,4 +1,4 @@
1
- import lamindb_setup as _lamindb_setup
2
- from lamindb_setup.core import * # noqa: F403
3
-
4
- __doc__ = _lamindb_setup.core.__doc__.replace("lamindb_setup", "lamindb.setup")
1
+ import lamindb_setup as _lamindb_setup
2
+ from lamindb_setup.core import * # noqa: F403
3
+
4
+ __doc__ = _lamindb_setup.core.__doc__.replace("lamindb_setup", "lamindb.setup")