lamindb_setup 0.78.0__tar.gz → 0.80.0__tar.gz
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.
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/PKG-INFO +1 -1
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -23
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/08-test-multi-session.ipynb +7 -3
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-cloud-sync.ipynb +13 -13
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/__init__.py +1 -1
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_connect_instance.py +8 -2
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_init_instance.py +21 -9
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_setup_user.py +3 -3
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_hub_client.py +9 -4
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings.py +41 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_storage.py +12 -16
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_user.py +2 -2
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/django.py +11 -1
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/upath.py +2 -6
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_edge_request.py +1 -1
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_init_instance.py +6 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-local/test_all.py +6 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/.github/workflows/build.yml +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/.gitignore +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/.pre-commit-config.yaml +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/LICENSE +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/README.md +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/changelog.md +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/index.md +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/notebooks.md +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/reference.md +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_close.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_delete.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_entry_points.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_migrate.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_schema_metadata.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_aws_credentials.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_hub_core.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_instance.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_load.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_save.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_settings_store.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/noxfile.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/pyproject.toml +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_connect_instance.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_migrate.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-local/conftest.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-local/test_update_schema_in_hub.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_entry_point.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/storage/test_to_url.py +0 -0
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/02-connect-local-instance.ipynb
RENAMED
|
@@ -85,29 +85,6 @@
|
|
|
85
85
|
")"
|
|
86
86
|
]
|
|
87
87
|
},
|
|
88
|
-
{
|
|
89
|
-
"cell_type": "markdown",
|
|
90
|
-
"id": "0986a5f3",
|
|
91
|
-
"metadata": {},
|
|
92
|
-
"source": [
|
|
93
|
-
"You cannot load another instance in the same Python session:"
|
|
94
|
-
]
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"cell_type": "code",
|
|
98
|
-
"execution_count": null,
|
|
99
|
-
"id": "bc3568ae",
|
|
100
|
-
"metadata": {},
|
|
101
|
-
"outputs": [],
|
|
102
|
-
"source": [
|
|
103
|
-
"import pytest\n",
|
|
104
|
-
"\n",
|
|
105
|
-
"with pytest.raises(RuntimeError):\n",
|
|
106
|
-
" ln_setup.connect(\"testuser2/mydata\")\n",
|
|
107
|
-
"\n",
|
|
108
|
-
"assert ln_setup.settings.instance.slug == \"testuser1/mydata\""
|
|
109
|
-
]
|
|
110
|
-
},
|
|
111
88
|
{
|
|
112
89
|
"cell_type": "markdown",
|
|
113
90
|
"id": "e3701120",
|
|
@@ -113,14 +113,18 @@
|
|
|
113
113
|
"metadata": {},
|
|
114
114
|
"outputs": [],
|
|
115
115
|
"source": [
|
|
116
|
-
"
|
|
116
|
+
"from lamindb_setup._init_instance import CannotSwitchDefaultInstance\n",
|
|
117
|
+
"\n",
|
|
118
|
+
"with pytest.raises(CannotSwitchDefaultInstance):\n",
|
|
117
119
|
" ln_setup.init(storage=\"./testsetup2\")\n",
|
|
118
|
-
"with pytest.raises(
|
|
120
|
+
"with pytest.raises(CannotSwitchDefaultInstance):\n",
|
|
119
121
|
" ln_setup.connect(\"testsetup\")\n",
|
|
120
122
|
"with pytest.raises(RuntimeError):\n",
|
|
121
123
|
" ln_setup.migrate.create()\n",
|
|
122
124
|
"with pytest.raises(RuntimeError):\n",
|
|
123
|
-
" ln_setup.migrate.deploy()"
|
|
125
|
+
" ln_setup.migrate.deploy()\n",
|
|
126
|
+
"\n",
|
|
127
|
+
"assert ln_setup.settings.instance.slug == \"testuser1/testsetup\""
|
|
124
128
|
]
|
|
125
129
|
},
|
|
126
130
|
{
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"metadata": {},
|
|
83
83
|
"outputs": [],
|
|
84
84
|
"source": [
|
|
85
|
-
"dir_sync_local = settings.
|
|
85
|
+
"dir_sync_local = settings.paths.cloud_to_local_no_update(dir_sync)\n",
|
|
86
86
|
"if dir_sync_local.is_dir():\n",
|
|
87
87
|
" for file in dir_sync_local.iterdir():\n",
|
|
88
88
|
" file.unlink()\n",
|
|
@@ -118,9 +118,9 @@
|
|
|
118
118
|
"outputs": [],
|
|
119
119
|
"source": [
|
|
120
120
|
"test_local_path = UPath(\"./some/local/path\")\n",
|
|
121
|
-
"assert settings.
|
|
122
|
-
"assert settings.
|
|
123
|
-
"assert settings.
|
|
121
|
+
"assert settings.paths.cloud_to_local_no_update(test_local_path) == test_local_path\n",
|
|
122
|
+
"assert settings.paths.cloud_to_local_no_update(test_local_path.as_posix()) == test_local_path\n",
|
|
123
|
+
"assert settings.paths.cloud_to_local_no_update(test_local_path, cache_key=\"some/cache/key\") == test_local_path"
|
|
124
124
|
]
|
|
125
125
|
},
|
|
126
126
|
{
|
|
@@ -130,8 +130,8 @@
|
|
|
130
130
|
"metadata": {},
|
|
131
131
|
"outputs": [],
|
|
132
132
|
"source": [
|
|
133
|
-
"assert settings.
|
|
134
|
-
"assert settings.
|
|
133
|
+
"assert settings.paths.cloud_to_local_no_update(dir_sync) == settings.cache_dir / f\"lamindb-ci/{instance_name}/dir_sync\"\n",
|
|
134
|
+
"assert settings.paths.cloud_to_local_no_update(dir_sync, cache_key=\"dir_cache/key\") == settings.cache_dir / \"dir_cache/key\""
|
|
135
135
|
]
|
|
136
136
|
},
|
|
137
137
|
{
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"metadata": {},
|
|
150
150
|
"outputs": [],
|
|
151
151
|
"source": [
|
|
152
|
-
"dir_sync_local = settings.
|
|
152
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync, cache_key=\"dir_cache/key\")"
|
|
153
153
|
]
|
|
154
154
|
},
|
|
155
155
|
{
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"metadata": {},
|
|
192
192
|
"outputs": [],
|
|
193
193
|
"source": [
|
|
194
|
-
"dir_sync_local = settings.
|
|
194
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync)"
|
|
195
195
|
]
|
|
196
196
|
},
|
|
197
197
|
{
|
|
@@ -238,7 +238,7 @@
|
|
|
238
238
|
"metadata": {},
|
|
239
239
|
"outputs": [],
|
|
240
240
|
"source": [
|
|
241
|
-
"dir_sync_local = settings.
|
|
241
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync)\n",
|
|
242
242
|
"assert local_file.exists()\n",
|
|
243
243
|
"assert num_files(dir_sync_local) == 2"
|
|
244
244
|
]
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
"metadata": {},
|
|
268
268
|
"outputs": [],
|
|
269
269
|
"source": [
|
|
270
|
-
"dir_sync_local = settings.
|
|
270
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync)\n",
|
|
271
271
|
"\n",
|
|
272
272
|
"for file in (\"file1\", \"file2\"):\n",
|
|
273
273
|
" assert (dir_sync_local / file).stat().st_mtime == (\n",
|
|
@@ -298,7 +298,7 @@
|
|
|
298
298
|
"metadata": {},
|
|
299
299
|
"outputs": [],
|
|
300
300
|
"source": [
|
|
301
|
-
"dir_sync_local = settings.
|
|
301
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync)\n",
|
|
302
302
|
"assert num_files(dir_sync_local) == 2\n",
|
|
303
303
|
"assert local_file_new.exists()"
|
|
304
304
|
]
|
|
@@ -325,7 +325,7 @@
|
|
|
325
325
|
"metadata": {},
|
|
326
326
|
"outputs": [],
|
|
327
327
|
"source": [
|
|
328
|
-
"dir_sync_local = settings.
|
|
328
|
+
"dir_sync_local = settings.paths.cloud_to_local(dir_sync)\n",
|
|
329
329
|
"\n",
|
|
330
330
|
"assert num_files(dir_sync_local) == 2\n",
|
|
331
331
|
"assert not local_file_new.exists()\n",
|
|
@@ -430,7 +430,7 @@
|
|
|
430
430
|
"metadata": {},
|
|
431
431
|
"outputs": [],
|
|
432
432
|
"source": [
|
|
433
|
-
"cache_file = settings.
|
|
433
|
+
"cache_file = settings.paths.cloud_to_local_no_update(sqlite_file)"
|
|
434
434
|
]
|
|
435
435
|
},
|
|
436
436
|
{
|
|
@@ -9,7 +9,11 @@ from lamin_utils import logger
|
|
|
9
9
|
|
|
10
10
|
from ._check_setup import _check_instance_setup
|
|
11
11
|
from ._close import close as close_instance
|
|
12
|
-
from ._init_instance import
|
|
12
|
+
from ._init_instance import (
|
|
13
|
+
MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
|
|
14
|
+
CannotSwitchDefaultInstance,
|
|
15
|
+
load_from_isettings,
|
|
16
|
+
)
|
|
13
17
|
from ._silence_loggers import silence_loggers
|
|
14
18
|
from .core._hub_core import connect_instance_hub
|
|
15
19
|
from .core._hub_utils import (
|
|
@@ -224,7 +228,9 @@ def connect(slug: str, **kwargs) -> str | tuple | None:
|
|
|
224
228
|
logger.info(f"connected lamindb: {settings.instance.slug}")
|
|
225
229
|
return None
|
|
226
230
|
else:
|
|
227
|
-
raise
|
|
231
|
+
raise CannotSwitchDefaultInstance(
|
|
232
|
+
MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
|
|
233
|
+
)
|
|
228
234
|
elif (
|
|
229
235
|
_write_settings
|
|
230
236
|
and settings._instance_exists
|
|
@@ -26,7 +26,7 @@ if TYPE_CHECKING:
|
|
|
26
26
|
from .core.types import UPathStr
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def get_schema_module_name(schema_name) -> str:
|
|
29
|
+
def get_schema_module_name(schema_name, raise_import_error: bool = True) -> str | None:
|
|
30
30
|
import importlib.util
|
|
31
31
|
|
|
32
32
|
name_attempts = [f"lnschema_{schema_name.replace('-', '_')}", schema_name]
|
|
@@ -34,9 +34,11 @@ def get_schema_module_name(schema_name) -> str:
|
|
|
34
34
|
module_spec = importlib.util.find_spec(name)
|
|
35
35
|
if module_spec is not None:
|
|
36
36
|
return name
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
message = f"Schema module '{schema_name}' is not installed → no access to its labels & registries (resolve via `pip install {schema_name}`)"
|
|
38
|
+
if raise_import_error:
|
|
39
|
+
raise ImportError(message)
|
|
40
|
+
logger.warning(message.lower())
|
|
41
|
+
return None
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
def register_storage_in_instance(ssettings: StorageSettings):
|
|
@@ -180,6 +182,8 @@ def validate_init_args(
|
|
|
180
182
|
validate_schema_arg,
|
|
181
183
|
)
|
|
182
184
|
|
|
185
|
+
if storage is None:
|
|
186
|
+
raise SystemExit("✗ `storage` argument can't be `None`")
|
|
183
187
|
# should be called as the first thing
|
|
184
188
|
name_str = infer_instance_name(storage=storage, name=name, db=db)
|
|
185
189
|
owner_str = settings.user.handle if _user is None else _user.handle
|
|
@@ -206,10 +210,18 @@ def validate_init_args(
|
|
|
206
210
|
return name_str, instance_id, instance_state, instance_slug
|
|
207
211
|
|
|
208
212
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
class CannotSwitchDefaultInstance(SystemExit):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE = """
|
|
218
|
+
You cannot write to different instances in the same Python session.
|
|
219
|
+
|
|
220
|
+
Do you want to read from another instance via `Record.using()`? For example:
|
|
221
|
+
|
|
222
|
+
ln.Artifact.using("laminlabs/cellxgene").filter()
|
|
223
|
+
|
|
224
|
+
Or do you want to switch off auto-connect via `lamin settings set auto-connect false`?
|
|
213
225
|
"""
|
|
214
226
|
|
|
215
227
|
|
|
@@ -248,7 +260,7 @@ def init(
|
|
|
248
260
|
from ._check_setup import _check_instance_setup
|
|
249
261
|
|
|
250
262
|
if _check_instance_setup() and not _test:
|
|
251
|
-
raise
|
|
263
|
+
raise CannotSwitchDefaultInstance(MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE)
|
|
252
264
|
elif _write_settings:
|
|
253
265
|
close_instance(mute=True)
|
|
254
266
|
from .core._hub_core import init_instance as init_instance_hub
|
|
@@ -48,14 +48,14 @@ def load_user(email: str | None = None, handle: str | None = None) -> UserSettin
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def login(
|
|
51
|
-
user: str | None = None, *,
|
|
51
|
+
user: str | None = None, *, api_key: str | None = None, key: str | None = None
|
|
52
52
|
) -> None:
|
|
53
53
|
"""Log in user.
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
56
|
user: handle or email
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
api_key: API key
|
|
58
|
+
key: legacy API key
|
|
59
59
|
"""
|
|
60
60
|
if user is None and api_key is None:
|
|
61
61
|
if "LAMIN_API_KEY" in os.environ:
|
|
@@ -10,6 +10,8 @@ from pydantic_settings import BaseSettings
|
|
|
10
10
|
from supabase import Client, create_client # type: ignore
|
|
11
11
|
from supabase.lib.client_options import ClientOptions
|
|
12
12
|
|
|
13
|
+
from ._settings_save import save_user_settings
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
class Connector(BaseSettings):
|
|
15
17
|
url: str
|
|
@@ -129,14 +131,17 @@ def call_with_fallback_auth(
|
|
|
129
131
|
|
|
130
132
|
for renew_token, fallback_env in [(False, False), (True, False), (False, True)]:
|
|
131
133
|
try:
|
|
132
|
-
if renew_token:
|
|
133
|
-
logger.warning(
|
|
134
|
-
"renewing expired lamin token: call `lamin login <your-handle>` to avoid this"
|
|
135
|
-
)
|
|
136
134
|
client = connect_hub_with_auth(
|
|
137
135
|
renew_token=renew_token, fallback_env=fallback_env
|
|
138
136
|
)
|
|
139
137
|
result = callable(**kwargs, client=client)
|
|
138
|
+
# we update access_token here
|
|
139
|
+
# because at this point the call has been successfully resolved
|
|
140
|
+
if renew_token:
|
|
141
|
+
from lamindb_setup import settings
|
|
142
|
+
|
|
143
|
+
# here settings.user contains an updated access_token
|
|
144
|
+
save_user_settings(settings.user)
|
|
140
145
|
break
|
|
141
146
|
# we use Exception here as the ways in which the client fails upon 401
|
|
142
147
|
# are not consistent and keep changing
|
|
@@ -161,6 +161,15 @@ class SetupSettings:
|
|
|
161
161
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
162
162
|
return cache_dir
|
|
163
163
|
|
|
164
|
+
@property
|
|
165
|
+
def paths(self) -> type[SetupPaths]:
|
|
166
|
+
"""Convert cloud paths to lamidb local paths.
|
|
167
|
+
|
|
168
|
+
Use `settings.paths.cloud_to_local_no_update`
|
|
169
|
+
or `settings.paths.cloud_to_local`.
|
|
170
|
+
"""
|
|
171
|
+
return SetupPaths
|
|
172
|
+
|
|
164
173
|
def __repr__(self) -> str:
|
|
165
174
|
"""Rich string representation."""
|
|
166
175
|
repr = self.user.__repr__()
|
|
@@ -174,6 +183,38 @@ class SetupSettings:
|
|
|
174
183
|
return repr
|
|
175
184
|
|
|
176
185
|
|
|
186
|
+
class SetupPaths:
|
|
187
|
+
"""A static class for conversion of cloud paths to lamindb local paths."""
|
|
188
|
+
|
|
189
|
+
@staticmethod
|
|
190
|
+
def cloud_to_local_no_update(
|
|
191
|
+
filepath: UPathStr, cache_key: str | None = None
|
|
192
|
+
) -> UPath:
|
|
193
|
+
"""Local (or local cache) filepath from filepath without synchronization."""
|
|
194
|
+
# cache_key is ignored if filepath is a string or a local path
|
|
195
|
+
# ignores a mere string even if it represents a cloud path
|
|
196
|
+
if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
|
|
197
|
+
# settings is defined further in this file
|
|
198
|
+
local_filepath = settings.cache_dir / (
|
|
199
|
+
filepath.path if cache_key is None else cache_key
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
local_filepath = filepath
|
|
203
|
+
return UPath(local_filepath)
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def cloud_to_local(
|
|
207
|
+
filepath: UPathStr, cache_key: str | None = None, **kwargs
|
|
208
|
+
) -> UPath:
|
|
209
|
+
"""Local (or local cache) filepath from filepath."""
|
|
210
|
+
# cache_key is ignored in cloud_to_local_no_update if filepath is local or a string
|
|
211
|
+
local_filepath = SetupPaths.cloud_to_local_no_update(filepath, cache_key)
|
|
212
|
+
if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
|
|
213
|
+
local_filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
214
|
+
filepath.synchronize(local_filepath, **kwargs)
|
|
215
|
+
return local_filepath
|
|
216
|
+
|
|
217
|
+
|
|
177
218
|
def get_env_name():
|
|
178
219
|
if "LAMIN_ENV" in os.environ:
|
|
179
220
|
return os.environ["LAMIN_ENV"]
|
|
@@ -85,8 +85,8 @@ def init_storage(
|
|
|
85
85
|
StorageSettings,
|
|
86
86
|
Literal["hub-record-not-created", "hub-record-retireved", "hub-record-created"],
|
|
87
87
|
]:
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
assert root is not None, "`root` argument can't be `None`"
|
|
89
|
+
|
|
90
90
|
root_str = str(root) # ensure we have a string
|
|
91
91
|
if ".lamindb" in root_str:
|
|
92
92
|
raise ValueError(
|
|
@@ -322,24 +322,20 @@ class StorageSettings:
|
|
|
322
322
|
self, filepath: UPathStr, cache_key: str | None = None, **kwargs
|
|
323
323
|
) -> UPath:
|
|
324
324
|
"""Local (or local cache) filepath from filepath."""
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return local_filepath
|
|
325
|
+
from lamindb_setup import settings
|
|
326
|
+
|
|
327
|
+
return settings.paths.cloud_to_local(
|
|
328
|
+
filepath=filepath, cache_key=cache_key, **kwargs
|
|
329
|
+
)
|
|
331
330
|
|
|
332
331
|
def cloud_to_local_no_update(
|
|
333
332
|
self, filepath: UPathStr, cache_key: str | None = None
|
|
334
333
|
) -> UPath:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
else:
|
|
341
|
-
local_filepath = filepath
|
|
342
|
-
return UPath(local_filepath)
|
|
334
|
+
from lamindb_setup import settings
|
|
335
|
+
|
|
336
|
+
return settings.paths.cloud_to_local_no_update(
|
|
337
|
+
filepath=filepath, cache_key=cache_key
|
|
338
|
+
)
|
|
343
339
|
|
|
344
340
|
def key_to_filepath(self, filekey: UPathStr) -> UPath:
|
|
345
341
|
"""Cloud or local filepath from filekey."""
|
|
@@ -24,9 +24,9 @@ class UserSettings:
|
|
|
24
24
|
email: str | None = None
|
|
25
25
|
"""User email."""
|
|
26
26
|
api_key: str | None = None
|
|
27
|
-
"""
|
|
27
|
+
"""API key."""
|
|
28
28
|
password: str | None = None
|
|
29
|
-
"""API key or legacy password."""
|
|
29
|
+
"""legacy API key or legacy password."""
|
|
30
30
|
access_token: str | None = None
|
|
31
31
|
"""User access token."""
|
|
32
32
|
uid: str = "null"
|
|
@@ -55,7 +55,17 @@ def setup_django(
|
|
|
55
55
|
from .._init_instance import get_schema_module_name
|
|
56
56
|
|
|
57
57
|
schema_names = ["core"] + list(isettings.schema)
|
|
58
|
-
|
|
58
|
+
raise_import_error = True if init else False
|
|
59
|
+
installed_apps = [
|
|
60
|
+
package_name
|
|
61
|
+
for n in schema_names
|
|
62
|
+
if (
|
|
63
|
+
package_name := get_schema_module_name(
|
|
64
|
+
n, raise_import_error=raise_import_error
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
is not None
|
|
68
|
+
]
|
|
59
69
|
if view_schema:
|
|
60
70
|
installed_apps = installed_apps[::-1] # to fix how apps appear
|
|
61
71
|
installed_apps += ["schema_graph", "django.contrib.staticfiles"]
|
|
@@ -763,13 +763,9 @@ def check_storage_is_empty(
|
|
|
763
763
|
if raise_error
|
|
764
764
|
else "consider deleting them"
|
|
765
765
|
)
|
|
766
|
-
hint = "'_is_initialized'"
|
|
767
|
-
if n_offset_objects == 2:
|
|
768
|
-
hint += " & SQLite file"
|
|
769
|
-
hint += " ignored"
|
|
770
766
|
message = (
|
|
771
|
-
f"Storage {directory_string} contains {n_objects - n_offset_objects} objects
|
|
772
|
-
f"
|
|
767
|
+
f"Storage '{directory_string}' contains {n_objects - n_offset_objects} objects"
|
|
768
|
+
f" - {ask_for_deletion}"
|
|
773
769
|
)
|
|
774
770
|
if n_diff > 0:
|
|
775
771
|
if raise_error:
|
|
@@ -43,7 +43,7 @@ def test_edge_request():
|
|
|
43
43
|
assert instance["owner"] == "laminlabs"
|
|
44
44
|
assert instance["name"] == "lamindata"
|
|
45
45
|
assert instance["api_url"] == "https://us-east-1.api.lamin.ai"
|
|
46
|
-
assert instance["schema_str"]
|
|
46
|
+
assert instance["schema_str"].startswith("bionty,wetlab")
|
|
47
47
|
assert "schema_id" in instance
|
|
48
48
|
# check that schema_id is well-formed UUID
|
|
49
49
|
# if not, throws ValueError
|
|
@@ -32,6 +32,12 @@ def test_init_instance_postgres_default_name(get_hub_client):
|
|
|
32
32
|
ln_setup.delete(instance_name, force=True)
|
|
33
33
|
except InstanceNotFoundError:
|
|
34
34
|
pass
|
|
35
|
+
# test init with storage=None
|
|
36
|
+
# this happens when calling CLI lamin init or lamin init --name smth
|
|
37
|
+
with pytest.raises(SystemExit):
|
|
38
|
+
ln_setup.init(storage=None, _test=True)
|
|
39
|
+
with pytest.raises(SystemExit):
|
|
40
|
+
ln_setup.init(storage=None, name="init-to-fail", _test=True)
|
|
35
41
|
# now, run init
|
|
36
42
|
ln_setup.init(storage="./mydatapg", db=pgurl, _test=True)
|
|
37
43
|
assert ln_setup.settings.instance.slug == "testuser2/pgtest"
|
|
@@ -342,6 +342,12 @@ def test_connect_instance_hub_corrupted_or_expired_credentials(
|
|
|
342
342
|
owner="testadmin1",
|
|
343
343
|
name=create_myinstance["name"],
|
|
344
344
|
)
|
|
345
|
+
# check access_token renewal
|
|
346
|
+
access_token = ln_setup.settings.user.access_token
|
|
347
|
+
assert access_token != "corrupted_or_expired_token"
|
|
348
|
+
# check that the access_token was written to the settings
|
|
349
|
+
ln_setup.settings._user_settings = None
|
|
350
|
+
assert ln_setup.settings.user.access_token == access_token
|
|
345
351
|
|
|
346
352
|
|
|
347
353
|
def test_init_storage_with_non_existing_bucket(create_testadmin1_session):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-init-load-local-anonymously.ipynb
RENAMED
|
File without changes
|
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/docs/hub-prod/test-insufficient-user-info.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-cloud/test_init_pass_user_no_writes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.78.0 → lamindb_setup-0.80.0}/tests/hub-prod/test_switch_and_fallback_env.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|