lamindb_setup 1.9.0__py3-none-any.whl → 1.9.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 (39) hide show
  1. lamindb_setup/__init__.py +107 -107
  2. lamindb_setup/_cache.py +87 -87
  3. lamindb_setup/_check_setup.py +166 -166
  4. lamindb_setup/_connect_instance.py +328 -342
  5. lamindb_setup/_delete.py +141 -141
  6. lamindb_setup/_disconnect.py +32 -32
  7. lamindb_setup/_init_instance.py +440 -440
  8. lamindb_setup/_migrate.py +266 -266
  9. lamindb_setup/_register_instance.py +35 -35
  10. lamindb_setup/_schema_metadata.py +441 -441
  11. lamindb_setup/_set_managed_storage.py +70 -70
  12. lamindb_setup/_setup_user.py +133 -133
  13. lamindb_setup/core/__init__.py +21 -21
  14. lamindb_setup/core/_aws_options.py +223 -223
  15. lamindb_setup/core/_hub_client.py +248 -248
  16. lamindb_setup/core/_hub_core.py +665 -665
  17. lamindb_setup/core/_hub_crud.py +227 -227
  18. lamindb_setup/core/_private_django_api.py +83 -83
  19. lamindb_setup/core/_settings.py +377 -377
  20. lamindb_setup/core/_settings_instance.py +569 -569
  21. lamindb_setup/core/_settings_load.py +141 -141
  22. lamindb_setup/core/_settings_save.py +95 -95
  23. lamindb_setup/core/_settings_storage.py +429 -429
  24. lamindb_setup/core/_settings_store.py +91 -91
  25. lamindb_setup/core/_settings_user.py +55 -55
  26. lamindb_setup/core/_setup_bionty_sources.py +44 -44
  27. lamindb_setup/core/cloud_sqlite_locker.py +240 -240
  28. lamindb_setup/core/django.py +305 -296
  29. lamindb_setup/core/exceptions.py +1 -1
  30. lamindb_setup/core/hashing.py +134 -134
  31. lamindb_setup/core/types.py +1 -1
  32. lamindb_setup/core/upath.py +1013 -1013
  33. lamindb_setup/errors.py +70 -70
  34. lamindb_setup/types.py +20 -20
  35. {lamindb_setup-1.9.0.dist-info → lamindb_setup-1.9.1.dist-info}/METADATA +1 -1
  36. lamindb_setup-1.9.1.dist-info/RECORD +50 -0
  37. lamindb_setup-1.9.0.dist-info/RECORD +0 -50
  38. {lamindb_setup-1.9.0.dist-info → lamindb_setup-1.9.1.dist-info}/LICENSE +0 -0
  39. {lamindb_setup-1.9.0.dist-info → lamindb_setup-1.9.1.dist-info}/WHEEL +0 -0
@@ -1,342 +1,328 @@
1
- from __future__ import annotations
2
-
3
- import importlib
4
- import os
5
- from typing import TYPE_CHECKING, Any
6
- from uuid import UUID
7
-
8
- from lamin_utils import logger
9
-
10
- from ._check_setup import _check_instance_setup, _get_current_instance_settings
11
- from ._disconnect import disconnect
12
- from ._init_instance import (
13
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
14
- load_from_isettings,
15
- )
16
- from ._silence_loggers import silence_loggers
17
- from .core._hub_core import connect_instance_hub
18
- from .core._hub_utils import (
19
- LaminDsn,
20
- LaminDsnModel,
21
- )
22
- from .core._settings import settings
23
- from .core._settings_instance import InstanceSettings
24
- from .core._settings_load import load_instance_settings
25
- from .core._settings_storage import StorageSettings
26
- from .core._settings_store import instance_settings_file, settings_dir
27
- from .core.cloud_sqlite_locker import unlock_cloud_sqlite_upon_exception
28
- from .errors import CannotSwitchDefaultInstance
29
-
30
- if TYPE_CHECKING:
31
- from pathlib import Path
32
-
33
- from .core._settings_user import UserSettings
34
- from .types import UPathStr
35
-
36
- # this is for testing purposes only
37
- # set to True only to test failed load
38
- _TEST_FAILED_LOAD = False
39
-
40
-
41
- INSTANCE_NOT_FOUND_MESSAGE = (
42
- "'{owner}/{name}' not found:"
43
- " '{hub_result}'\nCheck your permissions:"
44
- " https://lamin.ai/{owner}/{name}"
45
- )
46
-
47
-
48
- class InstanceNotFoundError(SystemExit):
49
- pass
50
-
51
-
52
- def check_db_dsn_equal_up_to_credentials(db_dsn_hub, db_dsn_local):
53
- return (
54
- db_dsn_hub.scheme == db_dsn_local.scheme
55
- and db_dsn_hub.host == db_dsn_local.host
56
- and db_dsn_hub.database == db_dsn_local.database
57
- and db_dsn_hub.port == db_dsn_local.port
58
- )
59
-
60
-
61
- def update_db_using_local(
62
- hub_instance_result: dict[str, str],
63
- settings_file: Path,
64
- db: str | None = None,
65
- raise_permission_error=True,
66
- ) -> str | None:
67
- db_updated = None
68
- # check if postgres
69
- if hub_instance_result["db_scheme"] == "postgresql":
70
- if db is not None:
71
- # use only the provided db if it is set
72
- db_dsn_hub = LaminDsnModel(db=db)
73
- db_dsn_local = db_dsn_hub
74
- else:
75
- db_dsn_hub = LaminDsnModel(db=hub_instance_result["db"])
76
- # read directly from the environment
77
- if os.getenv("LAMINDB_INSTANCE_DB") is not None:
78
- logger.important("loading db URL from env variable LAMINDB_INSTANCE_DB")
79
- db_dsn_local = LaminDsnModel(db=os.getenv("LAMINDB_INSTANCE_DB"))
80
- # read from a cached settings file in case the hub result is only
81
- # read level or inexistent
82
- elif settings_file.exists() and (
83
- db_dsn_hub.db.user in {None, "none"} or "read" in db_dsn_hub.db.user # type:ignore
84
- ):
85
- isettings = load_instance_settings(settings_file)
86
- db_dsn_local = LaminDsnModel(db=isettings.db)
87
- else:
88
- # just take the default hub result and ensure there is actually a user
89
- if (
90
- db_dsn_hub.db.user in {None, "none"}
91
- and db_dsn_hub.db.password in {None, "none"}
92
- and raise_permission_error
93
- ):
94
- raise PermissionError(
95
- "No database access, please ask your admin to provide you with"
96
- " a DB URL and pass it via --db <db_url>"
97
- )
98
- db_dsn_local = db_dsn_hub
99
- if not check_db_dsn_equal_up_to_credentials(db_dsn_hub.db, db_dsn_local.db):
100
- raise ValueError(
101
- "The local differs from the hub database information:\n"
102
- "did your database get updated by an admin?\n"
103
- "Consider deleting your cached database environment:\nrm"
104
- f" {settings_file.as_posix()}"
105
- )
106
- db_updated = LaminDsn.build(
107
- scheme=db_dsn_hub.db.scheme,
108
- user=db_dsn_local.db.user,
109
- password=db_dsn_local.db.password,
110
- host=db_dsn_hub.db.host, # type: ignore
111
- port=db_dsn_hub.db.port,
112
- database=db_dsn_hub.db.database,
113
- )
114
- return db_updated
115
-
116
-
117
- def _connect_instance(
118
- owner: str,
119
- name: str,
120
- *,
121
- db: str | None = None,
122
- raise_permission_error: bool = True,
123
- access_token: str | None = None,
124
- ) -> InstanceSettings:
125
- settings_file = instance_settings_file(name, owner)
126
- make_hub_request = True
127
- if settings_file.exists():
128
- isettings = load_instance_settings(settings_file)
129
- # skip hub request for a purely local instance
130
- make_hub_request = isettings.is_remote
131
- if make_hub_request:
132
- # the following will return a string if the instance does not exist
133
- # on the hub
134
- # do not call hub if the user is anonymous
135
- if owner != "anonymous":
136
- hub_result = connect_instance_hub(
137
- owner=owner, name=name, access_token=access_token
138
- )
139
- else:
140
- hub_result = "anonymous-user"
141
- # if hub_result is not a string, it means it made a request
142
- # that successfully returned metadata
143
- if not isinstance(hub_result, str):
144
- instance_result, storage_result = hub_result
145
- db_updated = update_db_using_local(
146
- instance_result,
147
- settings_file,
148
- db=db,
149
- raise_permission_error=raise_permission_error,
150
- )
151
- ssettings = StorageSettings(
152
- root=storage_result["root"],
153
- region=storage_result["region"],
154
- uid=storage_result["lnid"],
155
- uuid=UUID(storage_result["id"]),
156
- instance_id=UUID(instance_result["id"]),
157
- )
158
- isettings = InstanceSettings(
159
- id=UUID(instance_result["id"]),
160
- owner=owner,
161
- name=instance_result["name"],
162
- storage=ssettings,
163
- db=db_updated,
164
- modules=instance_result["schema_str"],
165
- git_repo=instance_result["git_repo"],
166
- keep_artifacts_local=bool(instance_result["keep_artifacts_local"]),
167
- is_on_hub=True,
168
- api_url=instance_result["api_url"],
169
- schema_id=None
170
- if (schema_id := instance_result["schema_id"]) is None
171
- else UUID(schema_id),
172
- fine_grained_access=instance_result.get("fine_grained_access", False),
173
- db_permissions=instance_result.get("db_permissions", None),
174
- )
175
- else:
176
- if hub_result != "anonymous-user":
177
- message = INSTANCE_NOT_FOUND_MESSAGE.format(
178
- owner=owner, name=name, hub_result=hub_result
179
- )
180
- else:
181
- message = "It is not possible to load an anonymous-owned instance from the hub"
182
- if settings_file.exists():
183
- isettings = load_instance_settings(settings_file)
184
- if isettings.is_remote:
185
- raise InstanceNotFoundError(message)
186
- else:
187
- raise InstanceNotFoundError(message)
188
- return isettings
189
-
190
-
191
- def _connect_cli(instance: str) -> None:
192
- from lamindb_setup import settings as settings_
193
-
194
- settings_.auto_connect = True
195
- owner, name = get_owner_name_from_identifier(instance)
196
- isettings = _connect_instance(owner, name)
197
- isettings._persist(write_to_disk=True)
198
- if not isettings.is_on_hub or isettings._is_cloud_sqlite:
199
- # there are two reasons to call the full-blown connect
200
- # (1) if the instance is not on the hub, we need to register
201
- # potential users through register_user()
202
- # (2) if the instance is cloud sqlite, we need to lock it
203
- connect(_write_settings=False, _reload_lamindb=False)
204
- else:
205
- logger.important(f"connected lamindb: {isettings.slug}")
206
- return None
207
-
208
-
209
- @unlock_cloud_sqlite_upon_exception(ignore_prev_locker=True)
210
- def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
211
- """Connect to an instance.
212
-
213
- Args:
214
- instance: Pass a slug (`account/name`) or URL (`https://lamin.ai/account/name`).
215
- If `None`, looks for an environment variable `LAMIN_CURRENT_INSTANCE` to get the instance identifier.
216
- If it doesn't find this variable, it connects to the instance that was connected with `lamin connect` through the CLI.
217
- """
218
- # validate kwargs
219
- valid_kwargs = {
220
- "_db",
221
- "_write_settings",
222
- "_raise_not_found_error",
223
- "_reload_lamindb",
224
- "_test",
225
- "_user",
226
- }
227
- for kwarg in kwargs:
228
- if kwarg not in valid_kwargs:
229
- raise TypeError(f"connect() got unexpected keyword argument '{kwarg}'")
230
- isettings: InstanceSettings = None # type: ignore
231
- # _db is still needed because it is called in init
232
- _db: str | None = kwargs.get("_db", None)
233
- _write_settings: bool = kwargs.get("_write_settings", False)
234
- _raise_not_found_error: bool = kwargs.get("_raise_not_found_error", True)
235
- _reload_lamindb: bool = kwargs.get("_reload_lamindb", True)
236
- _test: bool = kwargs.get("_test", False)
237
-
238
- access_token: str | None = None
239
- _user: UserSettings | None = kwargs.get("_user", None)
240
- if _user is not None:
241
- access_token = _user.access_token
242
- if instance is None:
243
- instance = os.environ.get("LAMIN_CURRENT_INSTANCE")
244
-
245
- try:
246
- if instance is None:
247
- isettings_or_none = _get_current_instance_settings()
248
- if isettings_or_none is None:
249
- raise ValueError(
250
- "No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
251
- )
252
- isettings = isettings_or_none
253
- else:
254
- owner, name = get_owner_name_from_identifier(instance)
255
- if _check_instance_setup() and not _test:
256
- if (
257
- settings._instance_exists
258
- and f"{owner}/{name}" == settings.instance.slug
259
- ):
260
- logger.important(f"connected lamindb: {settings.instance.slug}")
261
- return None
262
- else:
263
- raise CannotSwitchDefaultInstance(
264
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
265
- )
266
- elif (
267
- _write_settings
268
- and settings._instance_exists
269
- and f"{owner}/{name}" != settings.instance.slug
270
- ):
271
- disconnect(mute=True)
272
-
273
- try:
274
- isettings = _connect_instance(
275
- owner, name, db=_db, access_token=access_token
276
- )
277
- except InstanceNotFoundError as e:
278
- if _raise_not_found_error:
279
- raise e
280
- else:
281
- return "instance-not-found"
282
- if isinstance(isettings, str):
283
- return isettings
284
- # at this point we have checked already that isettings is not a string
285
- # _user is passed to lock cloud sqlite for this user in isettings._load_db()
286
- # has no effect if _user is None or if not cloud sqlite instance
287
- isettings._locker_user = _user
288
- isettings._persist(write_to_disk=_write_settings)
289
- if _test:
290
- return None
291
- silence_loggers()
292
- check, msg = isettings._load_db()
293
- if not check:
294
- local_db = (
295
- isettings._is_cloud_sqlite and isettings._sqlite_file_local.exists()
296
- )
297
- if local_db:
298
- logger.warning(
299
- "SQLite file does not exist in the cloud, but exists locally:"
300
- f" {isettings._sqlite_file_local}\nTo push the file to the cloud,"
301
- " call: lamin disconnect"
302
- )
303
- elif _raise_not_found_error:
304
- raise SystemExit(msg)
305
- else:
306
- logger.warning(
307
- f"instance exists with id {isettings._id.hex}, but database is not"
308
- " loadable: re-initializing"
309
- )
310
- return "instance-corrupted-or-deleted"
311
- # this is for testing purposes only
312
- if _TEST_FAILED_LOAD:
313
- raise RuntimeError("Technical testing error.")
314
-
315
- load_from_isettings(isettings, user=_user, write_settings=_write_settings)
316
- if _reload_lamindb:
317
- importlib.reload(importlib.import_module("lamindb"))
318
- logger.important(f"connected lamindb: {isettings.slug}")
319
- except Exception as e:
320
- if isettings is not None:
321
- if _write_settings:
322
- isettings._get_settings_file().unlink(missing_ok=True) # type: ignore
323
- settings._instance_settings = None
324
- raise e
325
- return None
326
-
327
-
328
- def get_owner_name_from_identifier(identifier: str):
329
- if "/" in identifier:
330
- if identifier.startswith("https://lamin.ai/"):
331
- identifier = identifier.replace("https://lamin.ai/", "")
332
- split = identifier.split("/")
333
- if len(split) > 2:
334
- raise ValueError(
335
- "The instance identifier needs to be 'owner/name', the instance name"
336
- " (owner is current user) or the URL: https://lamin.ai/owner/name."
337
- )
338
- owner, name = split
339
- else:
340
- owner = settings.user.handle
341
- name = identifier
342
- return owner, name
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import os
5
+ from typing import TYPE_CHECKING, Any
6
+ from uuid import UUID
7
+
8
+ from lamin_utils import logger
9
+
10
+ from ._check_setup import _check_instance_setup, _get_current_instance_settings
11
+ from ._disconnect import disconnect
12
+ from ._init_instance import (
13
+ MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
14
+ load_from_isettings,
15
+ )
16
+ from ._silence_loggers import silence_loggers
17
+ from .core._hub_core import connect_instance_hub
18
+ from .core._hub_utils import LaminDsnModel
19
+ from .core._settings import settings
20
+ from .core._settings_instance import InstanceSettings
21
+ from .core._settings_load import load_instance_settings
22
+ from .core._settings_storage import StorageSettings
23
+ from .core._settings_store import instance_settings_file, settings_dir
24
+ from .core.cloud_sqlite_locker import unlock_cloud_sqlite_upon_exception
25
+ from .errors import CannotSwitchDefaultInstance
26
+
27
+ if TYPE_CHECKING:
28
+ from pathlib import Path
29
+
30
+ from .core._settings_user import UserSettings
31
+ from .types import UPathStr
32
+
33
+ # this is for testing purposes only
34
+ # set to True only to test failed load
35
+ _TEST_FAILED_LOAD = False
36
+
37
+
38
+ INSTANCE_NOT_FOUND_MESSAGE = (
39
+ "'{owner}/{name}' not found:"
40
+ " '{hub_result}'\nCheck your permissions:"
41
+ " https://lamin.ai/{owner}/{name}"
42
+ )
43
+
44
+
45
+ class InstanceNotFoundError(SystemExit):
46
+ pass
47
+
48
+
49
+ def check_db_dsn_equal_up_to_credentials(db_dsn_hub, db_dsn_local):
50
+ return (
51
+ db_dsn_hub.scheme == db_dsn_local.scheme
52
+ and db_dsn_hub.host == db_dsn_local.host
53
+ and db_dsn_hub.database == db_dsn_local.database
54
+ and db_dsn_hub.port == db_dsn_local.port
55
+ )
56
+
57
+
58
+ def update_db_using_local(
59
+ hub_instance_result: dict[str, str],
60
+ settings_file: Path,
61
+ db: str | None = None,
62
+ raise_permission_error=True,
63
+ ) -> str | None:
64
+ db_updated = None
65
+ # check if postgres
66
+ if hub_instance_result["db_scheme"] == "postgresql":
67
+ if db is not None:
68
+ # use only the provided db if it is set
69
+ db_updated = db
70
+ elif (db_env := os.getenv("LAMINDB_INSTANCE_DB")) is not None:
71
+ logger.important("loading db URL from env variable LAMINDB_INSTANCE_DB")
72
+ # read directly from the environment
73
+ db_updated = db_env
74
+ else:
75
+ db_hub = hub_instance_result["db"]
76
+ db_dsn_hub = LaminDsnModel(db=db_hub)
77
+ # read from a cached settings file in case the hub result is inexistent
78
+ if db_dsn_hub.db.user in {None, "none"} and settings_file.exists():
79
+ isettings = load_instance_settings(settings_file)
80
+ db_updated = isettings.db
81
+ else:
82
+ # just take the default hub result and ensure there is actually a user
83
+ if (
84
+ db_dsn_hub.db.user in {None, "none"}
85
+ and db_dsn_hub.db.password in {None, "none"}
86
+ and raise_permission_error
87
+ ):
88
+ raise PermissionError(
89
+ "No database access, please ask your admin to provide you with"
90
+ " a DB URL and pass it via --db <db_url>"
91
+ )
92
+ db_updated = db_hub
93
+ return db_updated
94
+
95
+
96
+ def _connect_instance(
97
+ owner: str,
98
+ name: str,
99
+ *,
100
+ db: str | None = None,
101
+ raise_permission_error: bool = True,
102
+ access_token: str | None = None,
103
+ ) -> InstanceSettings:
104
+ settings_file = instance_settings_file(name, owner)
105
+ make_hub_request = True
106
+ if settings_file.exists():
107
+ isettings = load_instance_settings(settings_file)
108
+ # skip hub request for a purely local instance
109
+ if isettings.is_remote:
110
+ make_hub_request = True
111
+ else:
112
+ make_hub_request = False
113
+ if db is not None and isettings.dialect == "postgresql":
114
+ isettings._db = db
115
+ if make_hub_request:
116
+ # the following will return a string if the instance does not exist
117
+ # on the hub
118
+ # do not call hub if the user is anonymous
119
+ if owner != "anonymous":
120
+ hub_result = connect_instance_hub(
121
+ owner=owner, name=name, access_token=access_token
122
+ )
123
+ else:
124
+ hub_result = "anonymous-user"
125
+ # if hub_result is not a string, it means it made a request
126
+ # that successfully returned metadata
127
+ if not isinstance(hub_result, str):
128
+ instance_result, storage_result = hub_result
129
+ db_updated = update_db_using_local(
130
+ instance_result,
131
+ settings_file,
132
+ db=db,
133
+ raise_permission_error=raise_permission_error,
134
+ )
135
+ ssettings = StorageSettings(
136
+ root=storage_result["root"],
137
+ region=storage_result["region"],
138
+ uid=storage_result["lnid"],
139
+ uuid=UUID(storage_result["id"]),
140
+ instance_id=UUID(instance_result["id"]),
141
+ )
142
+ isettings = InstanceSettings(
143
+ id=UUID(instance_result["id"]),
144
+ owner=owner,
145
+ name=instance_result["name"],
146
+ storage=ssettings,
147
+ db=db_updated,
148
+ modules=instance_result["schema_str"],
149
+ git_repo=instance_result["git_repo"],
150
+ keep_artifacts_local=bool(instance_result["keep_artifacts_local"]),
151
+ is_on_hub=True,
152
+ api_url=instance_result["api_url"],
153
+ schema_id=None
154
+ if (schema_id := instance_result["schema_id"]) is None
155
+ else UUID(schema_id),
156
+ fine_grained_access=instance_result.get("fine_grained_access", False),
157
+ db_permissions=instance_result.get("db_permissions", None),
158
+ )
159
+ else:
160
+ if hub_result != "anonymous-user":
161
+ message = INSTANCE_NOT_FOUND_MESSAGE.format(
162
+ owner=owner, name=name, hub_result=hub_result
163
+ )
164
+ else:
165
+ message = "It is not possible to load an anonymous-owned instance from the hub"
166
+ if settings_file.exists():
167
+ isettings = load_instance_settings(settings_file)
168
+ if isettings.is_remote:
169
+ raise InstanceNotFoundError(message)
170
+ else:
171
+ raise InstanceNotFoundError(message)
172
+ return isettings
173
+
174
+
175
+ def _connect_cli(instance: str) -> None:
176
+ from lamindb_setup import settings as settings_
177
+
178
+ settings_.auto_connect = True
179
+ owner, name = get_owner_name_from_identifier(instance)
180
+ isettings = _connect_instance(owner, name)
181
+ isettings._persist(write_to_disk=True)
182
+ if not isettings.is_on_hub or isettings._is_cloud_sqlite:
183
+ # there are two reasons to call the full-blown connect
184
+ # (1) if the instance is not on the hub, we need to register
185
+ # potential users through register_user()
186
+ # (2) if the instance is cloud sqlite, we need to lock it
187
+ connect(_write_settings=False, _reload_lamindb=False)
188
+ else:
189
+ logger.important(f"connected lamindb: {isettings.slug}")
190
+ return None
191
+
192
+
193
+ @unlock_cloud_sqlite_upon_exception(ignore_prev_locker=True)
194
+ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
195
+ """Connect to an instance.
196
+
197
+ Args:
198
+ instance: Pass a slug (`account/name`) or URL (`https://lamin.ai/account/name`).
199
+ If `None`, looks for an environment variable `LAMIN_CURRENT_INSTANCE` to get the instance identifier.
200
+ If it doesn't find this variable, it connects to the instance that was connected with `lamin connect` through the CLI.
201
+ """
202
+ # validate kwargs
203
+ valid_kwargs = {
204
+ "_db",
205
+ "_write_settings",
206
+ "_raise_not_found_error",
207
+ "_reload_lamindb",
208
+ "_test",
209
+ "_user",
210
+ }
211
+ for kwarg in kwargs:
212
+ if kwarg not in valid_kwargs:
213
+ raise TypeError(f"connect() got unexpected keyword argument '{kwarg}'")
214
+ isettings: InstanceSettings = None # type: ignore
215
+ # _db is still needed because it is called in init
216
+ _db: str | None = kwargs.get("_db", None)
217
+ _write_settings: bool = kwargs.get("_write_settings", False)
218
+ _raise_not_found_error: bool = kwargs.get("_raise_not_found_error", True)
219
+ _reload_lamindb: bool = kwargs.get("_reload_lamindb", True)
220
+ _test: bool = kwargs.get("_test", False)
221
+
222
+ access_token: str | None = None
223
+ _user: UserSettings | None = kwargs.get("_user", None)
224
+ if _user is not None:
225
+ access_token = _user.access_token
226
+ if instance is None:
227
+ instance = os.environ.get("LAMIN_CURRENT_INSTANCE")
228
+
229
+ try:
230
+ if instance is None:
231
+ isettings_or_none = _get_current_instance_settings()
232
+ if isettings_or_none is None:
233
+ raise ValueError(
234
+ "No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
235
+ )
236
+ isettings = isettings_or_none
237
+ if _db is not None and isettings.dialect == "postgresql":
238
+ isettings._db = _db
239
+ else:
240
+ owner, name = get_owner_name_from_identifier(instance)
241
+ if _check_instance_setup() and not _test:
242
+ if (
243
+ settings._instance_exists
244
+ and f"{owner}/{name}" == settings.instance.slug
245
+ ):
246
+ logger.important(f"connected lamindb: {settings.instance.slug}")
247
+ return None
248
+ else:
249
+ raise CannotSwitchDefaultInstance(
250
+ MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
251
+ )
252
+ elif (
253
+ _write_settings
254
+ and settings._instance_exists
255
+ and f"{owner}/{name}" != settings.instance.slug
256
+ ):
257
+ disconnect(mute=True)
258
+
259
+ try:
260
+ isettings = _connect_instance(
261
+ owner, name, db=_db, access_token=access_token
262
+ )
263
+ except InstanceNotFoundError as e:
264
+ if _raise_not_found_error:
265
+ raise e
266
+ else:
267
+ return "instance-not-found"
268
+ if isinstance(isettings, str):
269
+ return isettings
270
+ # at this point we have checked already that isettings is not a string
271
+ # _user is passed to lock cloud sqlite for this user in isettings._load_db()
272
+ # has no effect if _user is None or if not cloud sqlite instance
273
+ isettings._locker_user = _user
274
+ isettings._persist(write_to_disk=_write_settings)
275
+ if _test:
276
+ return None
277
+ silence_loggers()
278
+ check, msg = isettings._load_db()
279
+ if not check:
280
+ local_db = (
281
+ isettings._is_cloud_sqlite and isettings._sqlite_file_local.exists()
282
+ )
283
+ if local_db:
284
+ logger.warning(
285
+ "SQLite file does not exist in the cloud, but exists locally:"
286
+ f" {isettings._sqlite_file_local}\nTo push the file to the cloud,"
287
+ " call: lamin disconnect"
288
+ )
289
+ elif _raise_not_found_error:
290
+ raise SystemExit(msg)
291
+ else:
292
+ logger.warning(
293
+ f"instance exists with id {isettings._id.hex}, but database is not"
294
+ " loadable: re-initializing"
295
+ )
296
+ return "instance-corrupted-or-deleted"
297
+ # this is for testing purposes only
298
+ if _TEST_FAILED_LOAD:
299
+ raise RuntimeError("Technical testing error.")
300
+
301
+ load_from_isettings(isettings, user=_user, write_settings=_write_settings)
302
+ if _reload_lamindb:
303
+ importlib.reload(importlib.import_module("lamindb"))
304
+ logger.important(f"connected lamindb: {isettings.slug}")
305
+ except Exception as e:
306
+ if isettings is not None:
307
+ if _write_settings:
308
+ isettings._get_settings_file().unlink(missing_ok=True) # type: ignore
309
+ settings._instance_settings = None
310
+ raise e
311
+ return None
312
+
313
+
314
+ def get_owner_name_from_identifier(identifier: str):
315
+ if "/" in identifier:
316
+ if identifier.startswith("https://lamin.ai/"):
317
+ identifier = identifier.replace("https://lamin.ai/", "")
318
+ split = identifier.split("/")
319
+ if len(split) > 2:
320
+ raise ValueError(
321
+ "The instance identifier needs to be 'owner/name', the instance name"
322
+ " (owner is current user) or the URL: https://lamin.ai/owner/name."
323
+ )
324
+ owner, name = split
325
+ else:
326
+ owner = settings.user.handle
327
+ name = identifier
328
+ return owner, name