lamindb_setup 1.19.0__py3-none-any.whl → 1.19.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.
Files changed (49) hide show
  1. lamindb_setup/__init__.py +1 -1
  2. lamindb_setup/_cache.py +87 -87
  3. lamindb_setup/_check.py +7 -7
  4. lamindb_setup/_check_setup.py +131 -131
  5. lamindb_setup/_connect_instance.py +443 -441
  6. lamindb_setup/_delete.py +155 -155
  7. lamindb_setup/_disconnect.py +38 -38
  8. lamindb_setup/_django.py +39 -39
  9. lamindb_setup/_entry_points.py +19 -19
  10. lamindb_setup/_init_instance.py +423 -423
  11. lamindb_setup/_migrate.py +331 -331
  12. lamindb_setup/_register_instance.py +32 -32
  13. lamindb_setup/_schema.py +27 -27
  14. lamindb_setup/_schema_metadata.py +451 -451
  15. lamindb_setup/_set_managed_storage.py +81 -81
  16. lamindb_setup/_setup_user.py +198 -198
  17. lamindb_setup/_silence_loggers.py +46 -46
  18. lamindb_setup/core/__init__.py +25 -34
  19. lamindb_setup/core/_aws_options.py +276 -276
  20. lamindb_setup/core/_aws_storage.py +57 -57
  21. lamindb_setup/core/_clone.py +50 -50
  22. lamindb_setup/core/_deprecated.py +62 -62
  23. lamindb_setup/core/_docs.py +14 -14
  24. lamindb_setup/core/_hub_client.py +288 -288
  25. lamindb_setup/core/_hub_crud.py +247 -247
  26. lamindb_setup/core/_hub_utils.py +100 -100
  27. lamindb_setup/core/_private_django_api.py +80 -80
  28. lamindb_setup/core/_settings.py +440 -434
  29. lamindb_setup/core/_settings_instance.py +22 -1
  30. lamindb_setup/core/_settings_load.py +162 -162
  31. lamindb_setup/core/_settings_save.py +108 -108
  32. lamindb_setup/core/_settings_storage.py +433 -433
  33. lamindb_setup/core/_settings_store.py +162 -162
  34. lamindb_setup/core/_settings_user.py +55 -55
  35. lamindb_setup/core/_setup_bionty_sources.py +44 -44
  36. lamindb_setup/core/cloud_sqlite_locker.py +240 -240
  37. lamindb_setup/core/django.py +414 -413
  38. lamindb_setup/core/exceptions.py +1 -1
  39. lamindb_setup/core/hashing.py +134 -134
  40. lamindb_setup/core/types.py +1 -1
  41. lamindb_setup/core/upath.py +1031 -1028
  42. lamindb_setup/errors.py +72 -72
  43. lamindb_setup/io.py +423 -423
  44. lamindb_setup/types.py +17 -17
  45. {lamindb_setup-1.19.0.dist-info → lamindb_setup-1.19.1.dist-info}/METADATA +3 -2
  46. lamindb_setup-1.19.1.dist-info/RECORD +51 -0
  47. {lamindb_setup-1.19.0.dist-info → lamindb_setup-1.19.1.dist-info}/WHEEL +1 -1
  48. {lamindb_setup-1.19.0.dist-info → lamindb_setup-1.19.1.dist-info/licenses}/LICENSE +201 -201
  49. lamindb_setup-1.19.0.dist-info/RECORD +0 -51
@@ -1,162 +1,162 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- from dataclasses import MISSING, dataclass, fields
5
- from pathlib import Path
6
- from typing import Any, get_args, get_type_hints
7
-
8
- from dotenv import dotenv_values
9
- from lamin_utils import logger
10
- from platformdirs import site_config_dir
11
-
12
- if "LAMIN_SETTINGS_DIR" in os.environ:
13
- # Needed for AWS Lambda, as only tmp/ has write access
14
- settings_dir = Path(f"{os.environ['LAMIN_SETTINGS_DIR']}/.lamin")
15
- else:
16
- settings_dir = Path.home() / ".lamin"
17
-
18
- try:
19
- settings_dir.mkdir(parents=True, exist_ok=True)
20
- except Exception as e:
21
- logger.warning(f"Failed to create lamin settings directory at {settings_dir}: {e}")
22
-
23
- system_settings_dir = Path(site_config_dir(appname="lamindb", appauthor="laminlabs"))
24
-
25
-
26
- def get_settings_file_name_prefix():
27
- if "LAMIN_ENV" in os.environ:
28
- if os.environ["LAMIN_ENV"] != "prod":
29
- return f"{os.environ['LAMIN_ENV']}--"
30
- return ""
31
-
32
-
33
- def current_instance_settings_file():
34
- return settings_dir / f"{get_settings_file_name_prefix()}current_instance.env"
35
-
36
-
37
- def current_user_settings_file():
38
- return settings_dir / f"{get_settings_file_name_prefix()}current_user.env"
39
-
40
-
41
- def instance_settings_file(name: str, owner: str):
42
- return (
43
- settings_dir / f"{get_settings_file_name_prefix()}instance--{owner}--{name}.env"
44
- )
45
-
46
-
47
- def user_settings_file_email(email: str):
48
- return settings_dir / f"{get_settings_file_name_prefix()}user--{email}.env"
49
-
50
-
51
- def user_settings_file_handle(handle: str):
52
- return settings_dir / f"{get_settings_file_name_prefix()}user--{handle}.env"
53
-
54
-
55
- def platform_user_storage_settings_file():
56
- return settings_dir / "storage.env"
57
-
58
-
59
- def system_settings_file():
60
- return system_settings_dir / "system.env"
61
-
62
-
63
- def _load_env_to_kwargs(
64
- cls: type,
65
- path: Path | str,
66
- prefix: str,
67
- ) -> dict[str, Any]:
68
- path = Path(path) if isinstance(path, str) else path
69
- raw = dotenv_values(path)
70
- type_hints = get_type_hints(cls)
71
- flds = {f.name: f for f in fields(cls)}
72
- optional = {
73
- n
74
- for n, f in flds.items()
75
- if f.default is not MISSING or f.default_factory is not MISSING
76
- }
77
-
78
- kwargs: dict[str, Any] = {}
79
- for store_key in type_hints:
80
- if store_key.startswith("__"):
81
- continue
82
- env_key = f"{prefix}{store_key}"
83
- has_key = env_key in raw
84
- raw_val = raw.get(env_key) if has_key else None
85
- is_opt = store_key in optional
86
-
87
- if not has_key:
88
- if not is_opt:
89
- raise ValueError(f"Missing required key {env_key!r} in env file {path}")
90
- kwargs[store_key] = None
91
- continue
92
- if raw_val is None or raw_val == "" or raw_val == "null":
93
- kwargs[store_key] = None
94
- continue
95
- type_ = type_hints[store_key]
96
- args = get_args(type_) or ()
97
- if type_ is bool:
98
- kwargs[store_key] = raw_val.lower() in ("true", "1", "yes")
99
- elif type(None) in args:
100
- non_none = next((a for a in args if a is not type(None)), type_)
101
- if non_none is bool:
102
- kwargs[store_key] = raw_val.lower() in ("true", "1", "yes")
103
- else:
104
- kwargs[store_key] = raw_val
105
- else:
106
- kwargs[store_key] = raw_val
107
- return kwargs
108
-
109
-
110
- @dataclass
111
- class InstanceSettingsStore:
112
- # Required (no default) — must come first
113
- owner: str
114
- name: str
115
- storage_root: str
116
- storage_region: str | None
117
- db: str | None
118
- schema_str: str | None
119
- id: str
120
- git_repo: str | None
121
- keep_artifacts_local: bool | None
122
- # Optional
123
- api_url: str | None = None
124
- schema_id: str | None = None
125
- fine_grained_access: bool = False
126
- db_permissions: str | None = None
127
- is_clone: bool = False
128
-
129
- @classmethod
130
- def from_env_file(cls, path: Path | str, prefix: str) -> InstanceSettingsStore:
131
- kwargs = _load_env_to_kwargs(cls, path, prefix)
132
- return cls(**kwargs)
133
-
134
-
135
- @dataclass
136
- class UserSettingsStore:
137
- # Required (no default)
138
- email: str
139
- password: str
140
- access_token: str
141
- uid: str
142
- uuid: str
143
- handle: str
144
- name: str
145
- # Optional
146
- api_key: str | None = None
147
-
148
- @classmethod
149
- def from_env_file(cls, path: Path | str, prefix: str) -> UserSettingsStore:
150
- kwargs = _load_env_to_kwargs(cls, path, prefix)
151
- return cls(**kwargs)
152
-
153
-
154
- @dataclass
155
- class Connector:
156
- url: str
157
- key: str
158
-
159
- @classmethod
160
- def from_env_file(cls, path: Path | str, prefix: str) -> Connector:
161
- kwargs = _load_env_to_kwargs(cls, path, prefix)
162
- return cls(**kwargs)
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from dataclasses import MISSING, dataclass, fields
5
+ from pathlib import Path
6
+ from typing import Any, get_args, get_type_hints
7
+
8
+ from dotenv import dotenv_values
9
+ from lamin_utils import logger
10
+ from platformdirs import site_config_dir
11
+
12
+ if "LAMIN_SETTINGS_DIR" in os.environ:
13
+ # Needed for AWS Lambda, as only tmp/ has write access
14
+ settings_dir = Path(f"{os.environ['LAMIN_SETTINGS_DIR']}/.lamin")
15
+ else:
16
+ settings_dir = Path.home() / ".lamin"
17
+
18
+ try:
19
+ settings_dir.mkdir(parents=True, exist_ok=True)
20
+ except Exception as e:
21
+ logger.warning(f"Failed to create lamin settings directory at {settings_dir}: {e}")
22
+
23
+ system_settings_dir = Path(site_config_dir(appname="lamindb", appauthor="laminlabs"))
24
+
25
+
26
+ def get_settings_file_name_prefix():
27
+ if "LAMIN_ENV" in os.environ:
28
+ if os.environ["LAMIN_ENV"] != "prod":
29
+ return f"{os.environ['LAMIN_ENV']}--"
30
+ return ""
31
+
32
+
33
+ def current_instance_settings_file():
34
+ return settings_dir / f"{get_settings_file_name_prefix()}current_instance.env"
35
+
36
+
37
+ def current_user_settings_file():
38
+ return settings_dir / f"{get_settings_file_name_prefix()}current_user.env"
39
+
40
+
41
+ def instance_settings_file(name: str, owner: str):
42
+ return (
43
+ settings_dir / f"{get_settings_file_name_prefix()}instance--{owner}--{name}.env"
44
+ )
45
+
46
+
47
+ def user_settings_file_email(email: str):
48
+ return settings_dir / f"{get_settings_file_name_prefix()}user--{email}.env"
49
+
50
+
51
+ def user_settings_file_handle(handle: str):
52
+ return settings_dir / f"{get_settings_file_name_prefix()}user--{handle}.env"
53
+
54
+
55
+ def platform_user_storage_settings_file():
56
+ return settings_dir / "storage.env"
57
+
58
+
59
+ def system_settings_file():
60
+ return system_settings_dir / "system.env"
61
+
62
+
63
+ def _load_env_to_kwargs(
64
+ cls: type,
65
+ path: Path | str,
66
+ prefix: str,
67
+ ) -> dict[str, Any]:
68
+ path = Path(path) if isinstance(path, str) else path
69
+ raw = dotenv_values(path)
70
+ type_hints = get_type_hints(cls)
71
+ flds = {f.name: f for f in fields(cls)}
72
+ optional = {
73
+ n
74
+ for n, f in flds.items()
75
+ if f.default is not MISSING or f.default_factory is not MISSING
76
+ }
77
+
78
+ kwargs: dict[str, Any] = {}
79
+ for store_key in type_hints:
80
+ if store_key.startswith("__"):
81
+ continue
82
+ env_key = f"{prefix}{store_key}"
83
+ has_key = env_key in raw
84
+ raw_val = raw.get(env_key) if has_key else None
85
+ is_opt = store_key in optional
86
+
87
+ if not has_key:
88
+ if not is_opt:
89
+ raise ValueError(f"Missing required key {env_key!r} in env file {path}")
90
+ kwargs[store_key] = None
91
+ continue
92
+ if raw_val is None or raw_val == "" or raw_val == "null":
93
+ kwargs[store_key] = None
94
+ continue
95
+ type_ = type_hints[store_key]
96
+ args = get_args(type_) or ()
97
+ if type_ is bool:
98
+ kwargs[store_key] = raw_val.lower() in ("true", "1", "yes")
99
+ elif type(None) in args:
100
+ non_none = next((a for a in args if a is not type(None)), type_)
101
+ if non_none is bool:
102
+ kwargs[store_key] = raw_val.lower() in ("true", "1", "yes")
103
+ else:
104
+ kwargs[store_key] = raw_val
105
+ else:
106
+ kwargs[store_key] = raw_val
107
+ return kwargs
108
+
109
+
110
+ @dataclass
111
+ class InstanceSettingsStore:
112
+ # Required (no default) — must come first
113
+ owner: str
114
+ name: str
115
+ storage_root: str
116
+ storage_region: str | None
117
+ db: str | None
118
+ schema_str: str | None
119
+ id: str
120
+ git_repo: str | None
121
+ keep_artifacts_local: bool | None
122
+ # Optional
123
+ api_url: str | None = None
124
+ schema_id: str | None = None
125
+ fine_grained_access: bool = False
126
+ db_permissions: str | None = None
127
+ is_clone: bool = False
128
+
129
+ @classmethod
130
+ def from_env_file(cls, path: Path | str, prefix: str) -> InstanceSettingsStore:
131
+ kwargs = _load_env_to_kwargs(cls, path, prefix)
132
+ return cls(**kwargs)
133
+
134
+
135
+ @dataclass
136
+ class UserSettingsStore:
137
+ # Required (no default)
138
+ email: str
139
+ password: str
140
+ access_token: str
141
+ uid: str
142
+ uuid: str
143
+ handle: str
144
+ name: str
145
+ # Optional
146
+ api_key: str | None = None
147
+
148
+ @classmethod
149
+ def from_env_file(cls, path: Path | str, prefix: str) -> UserSettingsStore:
150
+ kwargs = _load_env_to_kwargs(cls, path, prefix)
151
+ return cls(**kwargs)
152
+
153
+
154
+ @dataclass
155
+ class Connector:
156
+ url: str
157
+ key: str
158
+
159
+ @classmethod
160
+ def from_env_file(cls, path: Path | str, prefix: str) -> Connector:
161
+ kwargs = _load_env_to_kwargs(cls, path, prefix)
162
+ return cls(**kwargs)
@@ -1,55 +1,55 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import TYPE_CHECKING
5
-
6
- if TYPE_CHECKING:
7
- from uuid import UUID
8
-
9
-
10
- class user_description:
11
- email = """User email."""
12
- password = """API key or legacy password."""
13
- uid = """Universal user ID."""
14
- handle = "Unique handle."
15
- name = "Full name."
16
-
17
-
18
- @dataclass
19
- class UserSettings:
20
- """User data. All synched from cloud."""
21
-
22
- handle: str = "anonymous"
23
- """Unique handle."""
24
- email: str | None = None
25
- """User email."""
26
- api_key: str | None = None
27
- """API key."""
28
- password: str | None = None
29
- """legacy API key or legacy password."""
30
- access_token: str | None = None
31
- """User access token."""
32
- uid: str = "null"
33
- """Universal user ID."""
34
- _uuid: UUID | None = None
35
- """Lamin's internal user ID."""
36
- name: str | None = None
37
- """Full name."""
38
-
39
- def __repr__(self) -> str:
40
- """Rich string representation."""
41
- representation = "Current user:"
42
- attrs = ["handle", "uid"]
43
- for attr in attrs:
44
- value = getattr(self, attr)
45
- representation += f"\n - {attr}: {value}"
46
- return representation
47
-
48
- @property
49
- def id(self):
50
- """Integer id valid in current instance."""
51
- from lamindb.base.users import current_user_id
52
-
53
- # there is no cache needed here because current_user_id()
54
- # has its own cache
55
- return current_user_id()
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from uuid import UUID
8
+
9
+
10
+ class user_description:
11
+ email = """User email."""
12
+ password = """API key or legacy password."""
13
+ uid = """Universal user ID."""
14
+ handle = "Unique handle."
15
+ name = "Full name."
16
+
17
+
18
+ @dataclass
19
+ class UserSettings:
20
+ """User data. All synched from cloud."""
21
+
22
+ handle: str = "anonymous"
23
+ """Unique handle."""
24
+ email: str | None = None
25
+ """User email."""
26
+ api_key: str | None = None
27
+ """API key."""
28
+ password: str | None = None
29
+ """Legacy password."""
30
+ access_token: str | None = None
31
+ """User access token."""
32
+ uid: str = "null"
33
+ """Universal user ID."""
34
+ _uuid: UUID | None = None
35
+ """Lamin's internal user ID."""
36
+ name: str | None = None
37
+ """Full name."""
38
+
39
+ def __repr__(self) -> str:
40
+ """Rich string representation."""
41
+ representation = "Current user:"
42
+ attrs = ["handle", "uid"]
43
+ for attr in attrs:
44
+ value = getattr(self, attr)
45
+ representation += f"\n - {attr}: {value}"
46
+ return representation
47
+
48
+ @property
49
+ def id(self):
50
+ """Integer id valid in current instance."""
51
+ from lamindb.base.users import current_user_id
52
+
53
+ # there is no cache needed here because current_user_id()
54
+ # has its own cache
55
+ return current_user_id()
@@ -1,44 +1,44 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- if TYPE_CHECKING:
6
- from ._settings_instance import InstanceSettings
7
-
8
-
9
- def write_bionty_sources(isettings: InstanceSettings) -> None:
10
- """Write public bionty sources to bt.Source table."""
11
- if "bionty" not in isettings.modules:
12
- return None
13
-
14
- import bionty
15
- import bionty.base as bionty_base
16
- from bionty._biorecord import list_biorecord_models
17
- from bionty.base.dev._handle_sources import parse_sources_yaml
18
- from bionty.models import Source
19
-
20
- bionty_models = list_biorecord_models(bionty)
21
-
22
- all_sources = parse_sources_yaml(bionty_base.settings.public_sources)
23
- all_sources_dict = all_sources.to_dict(orient="records")
24
-
25
- currently_used = (
26
- bionty_base.display_currently_used_sources(mute=True)
27
- .reset_index()
28
- .set_index(["entity", "organism"])
29
- )
30
-
31
- all_records = []
32
- for kwargs in all_sources_dict:
33
- act = currently_used.loc[(kwargs["entity"], kwargs["organism"])].to_dict()
34
- if (act["name"] == kwargs["name"]) and (act["version"] == kwargs["version"]):
35
- kwargs["currently_used"] = True
36
-
37
- kwargs["run"] = None # can't yet access tracking information
38
- kwargs["in_db"] = False
39
- if kwargs["entity"] in bionty_models:
40
- kwargs["entity"] = f"bionty.{kwargs['entity']}"
41
- record = Source(**kwargs)
42
- all_records.append(record)
43
-
44
- Source.objects.bulk_create(all_records, ignore_conflicts=True)
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from ._settings_instance import InstanceSettings
7
+
8
+
9
+ def write_bionty_sources(isettings: InstanceSettings) -> None:
10
+ """Write public bionty sources to bt.Source table."""
11
+ if "bionty" not in isettings.modules:
12
+ return None
13
+
14
+ import bionty
15
+ import bionty.base as bionty_base
16
+ from bionty._biorecord import list_biorecord_models
17
+ from bionty.base.dev._handle_sources import parse_sources_yaml
18
+ from bionty.models import Source
19
+
20
+ bionty_models = list_biorecord_models(bionty)
21
+
22
+ all_sources = parse_sources_yaml(bionty_base.settings.public_sources)
23
+ all_sources_dict = all_sources.to_dict(orient="records")
24
+
25
+ currently_used = (
26
+ bionty_base.display_currently_used_sources(mute=True)
27
+ .reset_index()
28
+ .set_index(["entity", "organism"])
29
+ )
30
+
31
+ all_records = []
32
+ for kwargs in all_sources_dict:
33
+ act = currently_used.loc[(kwargs["entity"], kwargs["organism"])].to_dict()
34
+ if (act["name"] == kwargs["name"]) and (act["version"] == kwargs["version"]):
35
+ kwargs["currently_used"] = True
36
+
37
+ kwargs["run"] = None # can't yet access tracking information
38
+ kwargs["in_db"] = False
39
+ if kwargs["entity"] in bionty_models:
40
+ kwargs["entity"] = f"bionty.{kwargs['entity']}"
41
+ record = Source(**kwargs)
42
+ all_records.append(record)
43
+
44
+ Source.objects.bulk_create(all_records, ignore_conflicts=True)