lamindb_setup 1.9.1__py3-none-any.whl → 1.10.0__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 (40) hide show
  1. lamindb_setup/__init__.py +107 -107
  2. lamindb_setup/_cache.py +87 -87
  3. lamindb_setup/_check_setup.py +192 -166
  4. lamindb_setup/_connect_instance.py +415 -328
  5. lamindb_setup/_delete.py +144 -141
  6. lamindb_setup/_disconnect.py +35 -32
  7. lamindb_setup/_init_instance.py +430 -440
  8. lamindb_setup/_migrate.py +278 -266
  9. lamindb_setup/_register_instance.py +32 -35
  10. lamindb_setup/_schema_metadata.py +441 -441
  11. lamindb_setup/_set_managed_storage.py +69 -70
  12. lamindb_setup/_setup_user.py +172 -133
  13. lamindb_setup/core/__init__.py +21 -21
  14. lamindb_setup/core/_aws_options.py +223 -223
  15. lamindb_setup/core/_aws_storage.py +9 -1
  16. lamindb_setup/core/_hub_client.py +248 -248
  17. lamindb_setup/core/_hub_core.py +728 -665
  18. lamindb_setup/core/_hub_crud.py +227 -227
  19. lamindb_setup/core/_private_django_api.py +83 -83
  20. lamindb_setup/core/_settings.py +384 -377
  21. lamindb_setup/core/_settings_instance.py +577 -569
  22. lamindb_setup/core/_settings_load.py +141 -141
  23. lamindb_setup/core/_settings_save.py +95 -95
  24. lamindb_setup/core/_settings_storage.py +427 -429
  25. lamindb_setup/core/_settings_store.py +91 -91
  26. lamindb_setup/core/_settings_user.py +55 -55
  27. lamindb_setup/core/_setup_bionty_sources.py +44 -44
  28. lamindb_setup/core/cloud_sqlite_locker.py +240 -240
  29. lamindb_setup/core/django.py +315 -305
  30. lamindb_setup/core/exceptions.py +1 -1
  31. lamindb_setup/core/hashing.py +134 -134
  32. lamindb_setup/core/types.py +1 -1
  33. lamindb_setup/core/upath.py +1013 -1013
  34. lamindb_setup/errors.py +80 -70
  35. lamindb_setup/types.py +20 -20
  36. {lamindb_setup-1.9.1.dist-info → lamindb_setup-1.10.0.dist-info}/METADATA +3 -3
  37. lamindb_setup-1.10.0.dist-info/RECORD +50 -0
  38. lamindb_setup-1.9.1.dist-info/RECORD +0 -50
  39. {lamindb_setup-1.9.1.dist-info → lamindb_setup-1.10.0.dist-info}/LICENSE +0 -0
  40. {lamindb_setup-1.9.1.dist-info → lamindb_setup-1.10.0.dist-info}/WHEEL +0 -0
@@ -1,70 +1,69 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from lamin_utils import logger
6
-
7
- from ._init_instance import register_storage_in_instance
8
- from .core._hub_core import delete_storage_record
9
- from .core._settings import settings
10
- from .core._settings_storage import StorageSettings, init_storage
11
-
12
- if TYPE_CHECKING:
13
- from lamindb_setup.types import UPathStr
14
-
15
-
16
- def set_managed_storage(root: UPathStr, host: str | None = None, **fs_kwargs):
17
- """Add or switch to another managed storage location.
18
-
19
- Args:
20
- root: `UPathStr` - The new storage root, e.g., an S3 bucket.
21
- host: `str | None = None` For a shared local storage location, pass a globally unique host identifier, e.g. `"my-institute-cluster-1"`, `"my-server-abcd"`, ...
22
- Discuss the naming convention with an admin.
23
- **fs_kwargs: Additional fsspec arguments for cloud root, e.g., profile.
24
-
25
- """
26
- if settings.instance.dialect == "sqlite":
27
- raise ValueError(
28
- "Can't add additional managed storage locations for sqlite instances."
29
- )
30
- if not settings.instance.is_on_hub:
31
- raise ValueError(
32
- "Can't add additional managed storage locations for instances that aren't managed through the hub."
33
- )
34
-
35
- # we do not just query the instance storage table because
36
- # we might need some information from the hub
37
- if not StorageSettings(root).type_is_cloud and host is None:
38
- host = "unspecified-host"
39
- logger.warning(
40
- "setting local storage locations with a single path is deprecated, "
41
- "use a tuple of (local_root, host) instead"
42
- )
43
-
44
- # here the storage is registered in the hub
45
- # hub_record_status="hub-record-created" if a new record is created
46
- # "hub-record-retrieved" if the storage is in the hub already
47
- ssettings, hub_record_status = init_storage(
48
- root=root,
49
- instance_id=settings.instance._id,
50
- instance_slug=settings.instance.slug,
51
- register_hub=settings.instance.is_on_hub,
52
- prevent_register_hub=not settings.instance.is_on_hub,
53
- region=host,
54
- )
55
- if ssettings._instance_id is None:
56
- raise ValueError(
57
- f"Cannot manage storage without write access: {ssettings.root}"
58
- )
59
- # here the storage is saved in the instance
60
- # if any error happens the record in the hub is deleted
61
- # if it was created earlier and not retrieved
62
- try:
63
- register_storage_in_instance(ssettings)
64
- except Exception as e:
65
- if hub_record_status == "hub-record-created" and ssettings._uuid is not None:
66
- delete_storage_record(ssettings)
67
- raise e
68
-
69
- settings.instance._storage = ssettings
70
- settings.storage._set_fs_kwargs(**fs_kwargs)
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from lamin_utils import logger
6
+
7
+ from ._init_instance import register_storage_in_instance
8
+ from .core._hub_core import delete_storage_record
9
+ from .core._settings import settings
10
+ from .core._settings_storage import StorageSettings, init_storage
11
+
12
+ if TYPE_CHECKING:
13
+ from lamindb_setup.types import UPathStr
14
+
15
+
16
+ def set_managed_storage(root: UPathStr, host: str | None = None, **fs_kwargs):
17
+ """Add or switch to another managed storage location.
18
+
19
+ Args:
20
+ root: `UPathStr` - The new storage root, e.g., an S3 bucket.
21
+ host: `str | None = None` For a shared local storage location, pass a globally unique host identifier, e.g. `"my-institute-cluster-1"`, `"my-server-abcd"`, ...
22
+ Discuss the naming convention with an admin.
23
+ **fs_kwargs: Additional fsspec arguments for cloud root, e.g., profile.
24
+
25
+ """
26
+ if settings.instance.dialect == "sqlite":
27
+ raise ValueError(
28
+ "Can't add additional managed storage locations for sqlite instances."
29
+ )
30
+ if not settings.instance.is_on_hub:
31
+ raise ValueError(
32
+ "Can't add additional managed storage locations for instances that aren't managed through the hub."
33
+ )
34
+
35
+ # we do not just query the instance storage table because
36
+ # we might need some information from the hub
37
+ if not StorageSettings(root).type_is_cloud and host is None:
38
+ host = "unspecified-host"
39
+ logger.warning(
40
+ "setting local storage locations with a single path is deprecated, "
41
+ "use a tuple of (local_root, host) instead"
42
+ )
43
+
44
+ # here the storage is registered in the hub
45
+ # hub_record_status="hub-record-created" if a new record is created
46
+ # "hub-record-retrieved" if the storage is in the hub already
47
+ ssettings, hub_record_status = init_storage(
48
+ root=root,
49
+ instance_id=settings.instance._id,
50
+ instance_slug=settings.instance.slug,
51
+ register_hub=settings.instance.is_on_hub,
52
+ region=host,
53
+ )
54
+ if ssettings._instance_id is None:
55
+ raise ValueError(
56
+ f"Cannot manage storage without write access: {ssettings.root}"
57
+ )
58
+ # here the storage is saved in the instance
59
+ # if any error happens the record in the hub is deleted
60
+ # if it was created earlier and not retrieved
61
+ try:
62
+ register_storage_in_instance(ssettings)
63
+ except Exception as e:
64
+ if hub_record_status == "hub-record-created" and ssettings._uuid is not None:
65
+ delete_storage_record(ssettings)
66
+ raise e
67
+
68
+ settings.instance._storage = ssettings
69
+ settings.storage._set_fs_kwargs(**fs_kwargs)
@@ -1,133 +1,172 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- from typing import TYPE_CHECKING
5
-
6
- from lamin_utils import logger
7
-
8
- from ._check_setup import _check_instance_setup
9
- from ._init_instance import register_user
10
- from .core._settings import settings
11
- from .core._settings_load import load_user_settings
12
- from .core._settings_save import save_user_settings
13
- from .core._settings_store import (
14
- current_user_settings_file,
15
- user_settings_file_email,
16
- user_settings_file_handle,
17
- )
18
- from .core._settings_user import UserSettings
19
-
20
-
21
- def load_user(email: str | None = None, handle: str | None = None) -> UserSettings:
22
- if email is not None:
23
- settings_file = user_settings_file_email(email)
24
- if handle is not None:
25
- settings_file = user_settings_file_handle(handle)
26
- if settings_file.exists():
27
- user_settings = load_user_settings(settings_file)
28
- save_user_settings(user_settings) # needed to save to current_user.env
29
- assert user_settings.email is not None or user_settings.api_key is not None
30
- else:
31
- if email is None:
32
- raise SystemExit(
33
- "✗ Use your email for your first login in a compute environment. "
34
- "After that, you can use your handle."
35
- )
36
- user_settings = UserSettings(handle=handle, email=email, uid="null") # type: ignore
37
-
38
- from .core._settings import settings
39
-
40
- settings._user_settings = None # this is to refresh a settings instance
41
-
42
- return user_settings
43
-
44
-
45
- def login(
46
- user: str | None = None, *, api_key: str | None = None, key: str | None = None
47
- ) -> UserSettings:
48
- """Log in user.
49
-
50
- Args:
51
- user: handle or email
52
- api_key: API key
53
- key: legacy API key
54
- """
55
- if user is None and api_key is None:
56
- if "LAMIN_API_KEY" in os.environ:
57
- api_key = os.environ["LAMIN_API_KEY"]
58
- else:
59
- raise ValueError("Both `user` and `api_key` should not be `None`.")
60
-
61
- if api_key is None:
62
- if "@" in user: # type: ignore
63
- email, handle = user, None
64
- else:
65
- email, handle = None, user
66
- user_settings = load_user(email, handle)
67
-
68
- if key is not None:
69
- # within UserSettings, we still call it "password" for a while
70
- user_settings.password = key
71
-
72
- if user_settings.password is None:
73
- api_key = user_settings.api_key
74
- if api_key is None:
75
- raise SystemExit(
76
- " No stored API key, please call: "
77
- "`lamin login` or `lamin login <your-email> --key <API-key>`"
78
- )
79
- elif user_settings.email is None:
80
- raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
81
- else:
82
- user_settings = UserSettings(handle="temporary", uid="null")
83
-
84
- from .core._hub_core import sign_in_hub, sign_in_hub_api_key
85
-
86
- if api_key is None:
87
- response = sign_in_hub(
88
- user_settings.email, # type: ignore
89
- user_settings.password, # type: ignore
90
- user_settings.handle,
91
- )
92
- else:
93
- response = sign_in_hub_api_key(api_key)
94
- user_settings.password = None
95
-
96
- if isinstance(response, Exception):
97
- raise response
98
- elif isinstance(response, str):
99
- raise SystemExit(f"✗ Unsuccessful login: {response}.")
100
- else:
101
- user_uuid, user_id, user_handle, user_name, access_token = response
102
-
103
- if api_key is not None:
104
- logger.success(f"logged in {user_handle} (uid: {user_id})")
105
- else: # legacy flow
106
- logger.success(f"logged in with email {user_settings.email} (uid: {user_id})")
107
-
108
- user_settings.uid = user_id
109
- user_settings.handle = user_handle
110
- user_settings.name = user_name
111
- user_settings._uuid = user_uuid
112
- user_settings.access_token = access_token
113
- user_settings.api_key = api_key
114
- save_user_settings(user_settings)
115
-
116
- if settings._instance_exists and _check_instance_setup():
117
- register_user(user_settings)
118
-
119
- settings._user_settings = None
120
- return user_settings
121
-
122
-
123
- def logout():
124
- if current_user_settings_file().exists():
125
- current_user_settings_file().unlink()
126
- settings._user_settings = None
127
- logger.success("logged out")
128
- else:
129
- logger.important("already logged out")
130
- if os.environ.get("LAMIN_API_KEY") is not None:
131
- logger.warning(
132
- "LAMIN_API_KEY is still set in your environment and will automatically log you in"
133
- )
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from typing import TYPE_CHECKING
5
+
6
+ from lamin_utils import logger
7
+
8
+ from ._check_setup import _check_instance_setup
9
+ from ._init_instance import register_user
10
+ from .core._settings import settings
11
+ from .core._settings_load import load_user_settings
12
+ from .core._settings_save import save_user_settings
13
+ from .core._settings_store import (
14
+ current_user_settings_file,
15
+ user_settings_file_email,
16
+ user_settings_file_handle,
17
+ )
18
+ from .core._settings_user import UserSettings
19
+
20
+
21
+ def load_user(email: str | None = None, handle: str | None = None) -> UserSettings:
22
+ if email is not None:
23
+ settings_file = user_settings_file_email(email)
24
+ if handle is not None:
25
+ settings_file = user_settings_file_handle(handle)
26
+ if settings_file.exists():
27
+ user_settings = load_user_settings(settings_file)
28
+ save_user_settings(user_settings) # needed to save to current_user.env
29
+ assert user_settings.email is not None or user_settings.api_key is not None
30
+ else:
31
+ if email is None:
32
+ raise SystemExit(
33
+ "✗ Use your email for your first login in a compute environment. "
34
+ "After that, you can use your handle."
35
+ )
36
+ user_settings = UserSettings(handle=handle, email=email, uid="null") # type: ignore
37
+
38
+ from .core._settings import settings
39
+
40
+ settings._user_settings = None # this is to refresh a settings instance
41
+
42
+ return user_settings
43
+
44
+
45
+ def login(
46
+ user: str | None = None, *, api_key: str | None = None, **kwargs
47
+ ) -> UserSettings:
48
+ # note that the docstring needs to be synced with lamin login
49
+ """Log into LaminHub.
50
+
51
+ `login()` prompts for your API key unless you set it via the `LAMIN_API_KEY` environment variable or pass it as an argument.
52
+
53
+ You can create your API key in your account settings on LaminHub (top right corner).
54
+
55
+ Args:
56
+ user: User handle.
57
+ api_key: API key.
58
+
59
+ See Also:
60
+ Login via the CLI command `lamin login`, see `here <https://docs.lamin.ai/cli#login>`__.
61
+
62
+ Examples:
63
+
64
+ Logging in the first time::
65
+
66
+ import lamindb as ln
67
+
68
+ ln.setup.login() # prompts for API key
69
+
70
+ After authenticating multiple users, you can switch between user profiles::
71
+
72
+ ln.setup.login("myhandle") # pass your user handle
73
+ """
74
+ if user is None:
75
+ if api_key is None:
76
+ if "LAMIN_API_KEY" in os.environ:
77
+ api_key = os.environ["LAMIN_API_KEY"]
78
+ else:
79
+ api_key = input("Your API key: ")
80
+ elif api_key is not None:
81
+ raise ValueError("Please provide either 'user' or 'api_key', not both.")
82
+
83
+ for kwarg in kwargs:
84
+ if kwarg != "key":
85
+ raise TypeError(f"login() got unexpected keyword argument '{kwarg}'")
86
+ key: str | None = kwargs.get("key", None) # legacy API key aka password
87
+ if key is not None:
88
+ logger.warning(
89
+ "the legacy API key is deprecated and will likely be removed in a future version"
90
+ )
91
+
92
+ if api_key is None:
93
+ if "@" in user: # type: ignore
94
+ email, handle = user, None
95
+ else:
96
+ email, handle = None, user
97
+ user_settings = load_user(email, handle)
98
+
99
+ if key is not None:
100
+ user_settings.password = key
101
+
102
+ if user_settings.password is None:
103
+ api_key = user_settings.api_key
104
+ if api_key is None:
105
+ raise SystemExit(
106
+ " No stored API key, please call: "
107
+ "`lamin login` or `lamin login <your-email> --key <API-key>`"
108
+ )
109
+ elif user_settings.email is None:
110
+ raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
111
+ else:
112
+ user_settings = UserSettings(handle="temporary", uid="null")
113
+
114
+ from .core._hub_core import sign_in_hub, sign_in_hub_api_key
115
+
116
+ if api_key is None:
117
+ response = sign_in_hub(
118
+ user_settings.email, # type: ignore
119
+ user_settings.password, # type: ignore
120
+ user_settings.handle,
121
+ )
122
+ else:
123
+ response = sign_in_hub_api_key(api_key)
124
+ user_settings.password = None
125
+
126
+ if isinstance(response, Exception):
127
+ raise response
128
+ elif isinstance(response, str):
129
+ raise SystemExit(f" Unsuccessful login: {response}.")
130
+ else:
131
+ user_uuid, user_id, user_handle, user_name, access_token = response
132
+
133
+ if api_key is not None:
134
+ logger.success(f"logged in {user_handle}")
135
+ else: # legacy flow
136
+ logger.success(f"logged in with email {user_settings.email}")
137
+
138
+ user_settings.uid = user_id
139
+ user_settings.handle = user_handle
140
+ user_settings.name = user_name
141
+ user_settings._uuid = user_uuid
142
+ user_settings.access_token = access_token
143
+ user_settings.api_key = api_key
144
+ save_user_settings(user_settings)
145
+
146
+ if settings._instance_exists and _check_instance_setup():
147
+ register_user(user_settings)
148
+
149
+ settings._user_settings = None
150
+ return user_settings
151
+
152
+
153
+ def logout():
154
+ """Log out the current user.
155
+
156
+ This deletes the `~/.lamin/current_user.env` so that you'll no longer be automatically authenticated in the environment.
157
+
158
+ It keeps a copy as `~/.lamin/user--<user_handle>.env` so you can easily switch between user profiles.
159
+
160
+ See Also:
161
+ Logout via the CLI command `lamin logout`, see `here <https://docs.lamin.ai/cli#logout>`__.
162
+ """
163
+ if current_user_settings_file().exists():
164
+ current_user_settings_file().unlink()
165
+ settings._user_settings = None
166
+ logger.success("logged out")
167
+ else:
168
+ logger.important("already logged out")
169
+ if os.environ.get("LAMIN_API_KEY") is not None:
170
+ logger.warning(
171
+ "LAMIN_API_KEY is still set in your environment and will automatically log you in"
172
+ )
@@ -1,21 +1,21 @@
1
- """Core setup library.
2
-
3
- Settings:
4
-
5
- .. autosummary::
6
- :toctree:
7
-
8
- SetupSettings
9
- UserSettings
10
- InstanceSettings
11
- StorageSettings
12
-
13
- """
14
-
15
- from . import django, upath
16
- from ._deprecated import deprecated
17
- from ._docs import doc_args
18
- from ._settings import SetupSettings
19
- from ._settings_instance import InstanceSettings
20
- from ._settings_storage import StorageSettings
21
- from ._settings_user import UserSettings
1
+ """Core setup library.
2
+
3
+ Settings:
4
+
5
+ .. autosummary::
6
+ :toctree:
7
+
8
+ SetupSettings
9
+ UserSettings
10
+ InstanceSettings
11
+ StorageSettings
12
+
13
+ """
14
+
15
+ from . import django, upath
16
+ from ._deprecated import deprecated
17
+ from ._docs import doc_args
18
+ from ._settings import SetupSettings
19
+ from ._settings_instance import InstanceSettings
20
+ from ._settings_storage import StorageSettings
21
+ from ._settings_user import UserSettings