lamindb_setup 0.69.5__tar.gz → 0.70.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.69.5 → lamindb_setup-0.70.0}/PKG-INFO +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/changelog.md +4 -0
- lamindb_setup-0.70.0/docs/hub-cloud/01-init-local-instance.ipynb +114 -0
- lamindb_setup-0.69.5/docs/hub-cloud/02-connect-on-prem-instance.ipynb → lamindb_setup-0.70.0/docs/hub-cloud/02-connect-local-instance.ipynb +6 -13
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/03-set-storage.ipynb +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +1 -1
- lamindb_setup-0.70.0/docs/hub-cloud/07-connect-hybrid-instance.ipynb +86 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-empty-init.ipynb +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/notebooks.md +3 -2
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/__init__.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_connect_instance.py +19 -10
- lamindb_setup-0.70.0/lamindb_setup/_delete.py +144 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_init_instance.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_migrate.py +4 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_register_instance.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_setup_user.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_core.py +27 -16
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_instance.py +67 -13
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_load.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_save.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_storage.py +26 -58
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_user.py +1 -1
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/django.py +3 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/upath.py +25 -9
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_connect_instance.py +13 -31
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_init_instance.py +12 -36
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-local/test_all.py +11 -11
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-prod/conftest.py +0 -3
- lamindb_setup-0.69.5/docs/hub-cloud/01-init-on-prem-instance.ipynb +0 -366
- lamindb_setup-0.69.5/lamindb_setup/_delete.py +0 -78
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/.github/workflows/build.yml +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/.github/workflows/latest-changes.jinja2 +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/.github/workflows/latest-changes.yml +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/.gitignore +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/.pre-commit-config.yaml +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/LICENSE +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/README.md +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/test-multi-session.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/index.md +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/docs/reference.md +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_add_remote_storage.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_close.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_client.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_store.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/noxfile.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/pyproject.toml +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_migrate.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-local/conftest.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-prod/test_auto_connect.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-0.69.5 → lamindb_setup-0.70.0}/tests/storage/test_storage_stats.py +0 -0
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
<!-- prettier-ignore -->
|
|
4
4
|
Name | PR | Developer | Date | Version
|
|
5
5
|
--- | --- | --- | --- | ---
|
|
6
|
+
✨ Introduce `local_storage` mode for cloud instances | [728](https://github.com/laminlabs/lamindb-setup/pull/728) | [falexwolf](https://github.com/falexwolf) | 2024-04-23 | 0.70.0
|
|
7
|
+
🚚 Make `.uuid` attributes private | [727](https://github.com/laminlabs/lamindb-setup/pull/727) | [falexwolf](https://github.com/falexwolf) | 2024-04-23 |
|
|
8
|
+
🚚 Rename `is_cloud` to `type_is_cloud` | [726](https://github.com/laminlabs/lamindb-setup/pull/726) | [falexwolf](https://github.com/falexwolf) | 2024-04-23 |
|
|
9
|
+
🚸 In `.delete()`, check for data deletion & delete from hub | [725](https://github.com/laminlabs/lamindb-setup/pull/725) | [falexwolf](https://github.com/falexwolf) | 2024-04-22 |
|
|
6
10
|
✨ Upload dirs inplace | [722](https://github.com/laminlabs/lamindb-setup/pull/722) | [Koncopd](https://github.com/Koncopd) | 2024-04-20 | 0.69.5
|
|
7
11
|
♻️ Do not always read from local cache | [720](https://github.com/laminlabs/lamindb-setup/pull/720) | [falexwolf](https://github.com/falexwolf) | 2024-04-19 | 0.69.4
|
|
8
12
|
♻️ Improve suffix handling | [718](https://github.com/laminlabs/lamindb-setup/pull/718) | [falexwolf](https://github.com/falexwolf) | 2024-04-19 | 0.69.3
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"attachments": {},
|
|
5
|
+
"cell_type": "markdown",
|
|
6
|
+
"metadata": {
|
|
7
|
+
"tags": []
|
|
8
|
+
},
|
|
9
|
+
"source": [
|
|
10
|
+
"# Init a local instance"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"cell_type": "code",
|
|
15
|
+
"execution_count": null,
|
|
16
|
+
"metadata": {},
|
|
17
|
+
"outputs": [],
|
|
18
|
+
"source": [
|
|
19
|
+
"!lamin login testuser1"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"cell_type": "code",
|
|
24
|
+
"execution_count": null,
|
|
25
|
+
"metadata": {},
|
|
26
|
+
"outputs": [],
|
|
27
|
+
"source": [
|
|
28
|
+
"import lamindb_setup as ln_setup"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"cell_type": "code",
|
|
33
|
+
"execution_count": null,
|
|
34
|
+
"metadata": {},
|
|
35
|
+
"outputs": [],
|
|
36
|
+
"source": [
|
|
37
|
+
"ln_setup.init(storage=\"./mydata\")"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"cell_type": "code",
|
|
42
|
+
"execution_count": null,
|
|
43
|
+
"metadata": {
|
|
44
|
+
"tags": [
|
|
45
|
+
"hide-cell"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"outputs": [],
|
|
49
|
+
"source": [
|
|
50
|
+
"from pathlib import Path\n",
|
|
51
|
+
"\n",
|
|
52
|
+
"assert ln_setup.settings.instance.storage.type_is_cloud == False\n",
|
|
53
|
+
"assert ln_setup.settings.instance.owner == ln_setup.settings.user.handle\n",
|
|
54
|
+
"assert ln_setup.settings.instance.name == \"mydata\"\n",
|
|
55
|
+
"assert ln_setup.settings.storage.root.as_posix() == Path(\"mydata\").resolve().as_posix()\n",
|
|
56
|
+
"storage_root = ln_setup.settings.storage.root\n",
|
|
57
|
+
"assert storage_root.exists()\n",
|
|
58
|
+
"assert ln_setup.settings.storage.id is not None\n",
|
|
59
|
+
"assert (\n",
|
|
60
|
+
" ln_setup.settings.instance.db\n",
|
|
61
|
+
" == f\"sqlite:///{Path('./mydata').resolve().as_posix()}/{ln_setup.settings.instance.id.hex}.lndb\"\n",
|
|
62
|
+
")"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"cell_type": "code",
|
|
67
|
+
"execution_count": null,
|
|
68
|
+
"metadata": {},
|
|
69
|
+
"outputs": [],
|
|
70
|
+
"source": [
|
|
71
|
+
"ln_setup.delete(\"mydata\", force=True)"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"cell_type": "code",
|
|
76
|
+
"execution_count": null,
|
|
77
|
+
"metadata": {},
|
|
78
|
+
"outputs": [],
|
|
79
|
+
"source": [
|
|
80
|
+
"from lamindb_setup.core._settings_store import instance_settings_file\n",
|
|
81
|
+
"\n",
|
|
82
|
+
"settings_file = instance_settings_file(\"mydata\", \"testuser1\")\n",
|
|
83
|
+
"assert not storage_root.exists()\n",
|
|
84
|
+
"assert settings_file.exists() == False"
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"metadata": {
|
|
89
|
+
"kernelspec": {
|
|
90
|
+
"display_name": "Python 3 (ipykernel)",
|
|
91
|
+
"language": "python",
|
|
92
|
+
"name": "python3"
|
|
93
|
+
},
|
|
94
|
+
"language_info": {
|
|
95
|
+
"codemirror_mode": {
|
|
96
|
+
"name": "ipython",
|
|
97
|
+
"version": 3
|
|
98
|
+
},
|
|
99
|
+
"file_extension": ".py",
|
|
100
|
+
"mimetype": "text/x-python",
|
|
101
|
+
"name": "python",
|
|
102
|
+
"nbconvert_exporter": "python",
|
|
103
|
+
"pygments_lexer": "ipython3",
|
|
104
|
+
"version": "3.10.13"
|
|
105
|
+
},
|
|
106
|
+
"vscode": {
|
|
107
|
+
"interpreter": {
|
|
108
|
+
"hash": "40d3a090f54c6569ab1632332b64b2c03c39dcf918b08424e98f38b5ae0af88f"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"nbformat": 4,
|
|
113
|
+
"nbformat_minor": 4
|
|
114
|
+
}
|
|
@@ -8,15 +8,7 @@
|
|
|
8
8
|
"tags": []
|
|
9
9
|
},
|
|
10
10
|
"source": [
|
|
11
|
-
"#
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"cell_type": "markdown",
|
|
16
|
-
"id": "f165d50c",
|
|
17
|
-
"metadata": {},
|
|
18
|
-
"source": [
|
|
19
|
-
"Here, we construct a case in which the storage location of the previous instance was moved:"
|
|
11
|
+
"# Connect to local instance"
|
|
20
12
|
]
|
|
21
13
|
},
|
|
22
14
|
{
|
|
@@ -28,8 +20,9 @@
|
|
|
28
20
|
},
|
|
29
21
|
"outputs": [],
|
|
30
22
|
"source": [
|
|
23
|
+
"# here, we construct a case in which the storage location of the previous instance was moved\n",
|
|
31
24
|
"!lamin close\n",
|
|
32
|
-
"!
|
|
25
|
+
"!lamin delete --force mydata\n",
|
|
33
26
|
"!lamin init --storage mydata\n",
|
|
34
27
|
"!rm -r ./mydata_new_loc\n",
|
|
35
28
|
"!mv mydata ./mydata_new_loc\n",
|
|
@@ -99,7 +92,7 @@
|
|
|
99
92
|
"source": [
|
|
100
93
|
"from pathlib import Path\n",
|
|
101
94
|
"\n",
|
|
102
|
-
"assert ln_setup.settings.instance.storage.
|
|
95
|
+
"assert ln_setup.settings.instance.storage.type_is_cloud == False\n",
|
|
103
96
|
"assert ln_setup.settings.instance.name == \"mydata\"\n",
|
|
104
97
|
"assert (\n",
|
|
105
98
|
" ln_setup.settings.instance.storage.root.as_posix()\n",
|
|
@@ -141,7 +134,7 @@
|
|
|
141
134
|
"id": "e3701120",
|
|
142
135
|
"metadata": {},
|
|
143
136
|
"source": [
|
|
144
|
-
"
|
|
137
|
+
"Delete:"
|
|
145
138
|
]
|
|
146
139
|
},
|
|
147
140
|
{
|
|
@@ -173,7 +166,7 @@
|
|
|
173
166
|
"name": "python",
|
|
174
167
|
"nbconvert_exporter": "python",
|
|
175
168
|
"pygments_lexer": "ipython3",
|
|
176
|
-
"version": "3.
|
|
169
|
+
"version": "3.10.13"
|
|
177
170
|
},
|
|
178
171
|
"vscode": {
|
|
179
172
|
"interpreter": {
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
},
|
|
183
183
|
"outputs": [],
|
|
184
184
|
"source": [
|
|
185
|
-
"assert ln_setup.settings.storage.
|
|
185
|
+
"assert ln_setup.settings.storage.type_is_cloud\n",
|
|
186
186
|
"assert ln_setup.settings.storage.root_as_str == \"s3://lamindb-ci\"\n",
|
|
187
187
|
"assert ln_setup.settings.storage.region == \"us-west-1\"\n",
|
|
188
188
|
"# root.fs contains the underlying fsspec filesystem\n",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"metadata": {},
|
|
91
91
|
"outputs": [],
|
|
92
92
|
"source": [
|
|
93
|
-
"assert ln_setup.settings.instance.storage.
|
|
93
|
+
"assert ln_setup.settings.instance.storage.type_is_cloud == True\n",
|
|
94
94
|
"assert ln_setup.settings.instance.owner == ln_setup.settings.user.handle\n",
|
|
95
95
|
"assert ln_setup.settings.instance.name == \"my-hosted\"\n",
|
|
96
96
|
"assert ln_setup.settings.storage.root.as_posix().startswith(hosted_buckets)\n",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Connect hybrid instance"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"cell_type": "code",
|
|
12
|
+
"execution_count": null,
|
|
13
|
+
"metadata": {},
|
|
14
|
+
"outputs": [],
|
|
15
|
+
"source": [
|
|
16
|
+
"# this shouldn't run in a notebook, but in the unit tests...\n",
|
|
17
|
+
"\n",
|
|
18
|
+
"import pytest\n",
|
|
19
|
+
"import lamindb_setup as ln_setup\n",
|
|
20
|
+
"from pathlib import Path\n",
|
|
21
|
+
"\n",
|
|
22
|
+
"ln_setup.login(\"testuser1\")\n",
|
|
23
|
+
"ln_setup.init(storage=\"s3://lamindb-ci/load_remote_instance\")\n",
|
|
24
|
+
"\n",
|
|
25
|
+
"assert ln_setup.settings.instance.name == \"load_remote_instance\"\n",
|
|
26
|
+
"assert ln_setup.settings.instance.storage.type_is_cloud\n",
|
|
27
|
+
"assert (\n",
|
|
28
|
+
" ln_setup.settings.instance.storage.root_as_str\n",
|
|
29
|
+
" == \"s3://lamindb-ci/load_remote_instance\"\n",
|
|
30
|
+
")\n",
|
|
31
|
+
"assert (\n",
|
|
32
|
+
" ln_setup.settings.instance._sqlite_file.as_posix()\n",
|
|
33
|
+
" == f\"s3://lamindb-ci/load_remote_instance/{ln_setup.settings.instance.id.hex}.lndb\" # noqa\n",
|
|
34
|
+
")\n",
|
|
35
|
+
"with pytest.raises(ValueError) as error:\n",
|
|
36
|
+
" ln_setup.settings.instance.local_storage\n",
|
|
37
|
+
"assert error.exconly() == \"ValueError: Local storage is not enabled for this instance.\"\n",
|
|
38
|
+
"ln_setup.settings.instance._local_storage_on = True\n",
|
|
39
|
+
"with pytest.raises(ValueError) as error:\n",
|
|
40
|
+
" ln_setup.settings.instance.local_storage\n",
|
|
41
|
+
"assert (\n",
|
|
42
|
+
" error.exconly()\n",
|
|
43
|
+
" == \"ValueError: No local storage root found, set via\"\n",
|
|
44
|
+
" \" `ln.setup.settings.instance.local_storage = local_root`\"\n",
|
|
45
|
+
")\n",
|
|
46
|
+
"\n",
|
|
47
|
+
"# now set local storage location\n",
|
|
48
|
+
"ln_setup.settings.instance.local_storage = \"./my_local_storage\"\n",
|
|
49
|
+
"\n",
|
|
50
|
+
"assert (\n",
|
|
51
|
+
" ln_setup.settings.instance.local_storage.root.as_posix()\n",
|
|
52
|
+
" == Path(\"./my_local_storage\").resolve().as_posix()\n",
|
|
53
|
+
")\n",
|
|
54
|
+
"assert ln_setup.settings.instance.local_storage is not None\n",
|
|
55
|
+
"with pytest.raises(ValueError) as error:\n",
|
|
56
|
+
" ln_setup.settings.instance.local_storage = \"./my_local_storage2\"\n",
|
|
57
|
+
"assert error.exconly().startswith(\n",
|
|
58
|
+
" \"ValueError: You already configured a local storage root for this instance in this\"\n",
|
|
59
|
+
" \" environment:\"\n",
|
|
60
|
+
")\n",
|
|
61
|
+
"ln_setup.delete(\"load_remote_instance\", force=True)"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"metadata": {
|
|
66
|
+
"kernelspec": {
|
|
67
|
+
"display_name": "py310",
|
|
68
|
+
"language": "python",
|
|
69
|
+
"name": "python3"
|
|
70
|
+
},
|
|
71
|
+
"language_info": {
|
|
72
|
+
"codemirror_mode": {
|
|
73
|
+
"name": "ipython",
|
|
74
|
+
"version": 3
|
|
75
|
+
},
|
|
76
|
+
"file_extension": ".py",
|
|
77
|
+
"mimetype": "text/x-python",
|
|
78
|
+
"name": "python",
|
|
79
|
+
"nbconvert_exporter": "python",
|
|
80
|
+
"pygments_lexer": "ipython3",
|
|
81
|
+
"version": "3.10.13"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"nbformat": 4,
|
|
85
|
+
"nbformat_minor": 2
|
|
86
|
+
}
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"metadata": {},
|
|
72
72
|
"outputs": [],
|
|
73
73
|
"source": [
|
|
74
|
-
"assert ln_setup.settings.storage.
|
|
74
|
+
"assert ln_setup.settings.storage.type_is_cloud\n",
|
|
75
75
|
"assert ln_setup.settings.storage.root_as_str == root_str\n",
|
|
76
76
|
"assert ln_setup.settings.storage.region == \"us-east-1\"\n",
|
|
77
77
|
"assert (\n",
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
```{toctree}
|
|
4
4
|
:maxdepth: 1
|
|
5
5
|
|
|
6
|
-
hub-cloud/init-
|
|
7
|
-
hub-cloud/connect-
|
|
6
|
+
hub-cloud/init-local-instance
|
|
7
|
+
hub-cloud/connect-local-instance
|
|
8
8
|
hub-cloud/set-storage
|
|
9
9
|
hub-cloud/test-bionty
|
|
10
10
|
hub-cloud/init-hosted-instance
|
|
11
11
|
hub-cloud/connect-hosted-instance
|
|
12
12
|
hub-cloud/test-multi-session
|
|
13
|
+
hub-cloud/connect-hybrid-instance
|
|
13
14
|
|
|
14
15
|
hub-prod/test-cache-management
|
|
15
16
|
hub-prod/test-empty-init
|
|
@@ -27,6 +27,17 @@ from ._migrate import check_whether_migrations_in_sync
|
|
|
27
27
|
_TEST_FAILED_LOAD = False
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
INSTANCE_NOT_FOUND_MESSAGE = (
|
|
31
|
+
"'{owner}/{name}' not found:"
|
|
32
|
+
" '{hub_result}'\nCheck your permissions:"
|
|
33
|
+
" https://lamin.ai/{owner}/{name}"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class InstanceNotFoundError(SystemExit):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
30
41
|
def check_db_dsn_equal_up_to_credentials(db_dsn_hub, db_dsn_local):
|
|
31
42
|
return (
|
|
32
43
|
db_dsn_hub.scheme == db_dsn_local.scheme
|
|
@@ -121,6 +132,8 @@ def connect(
|
|
|
121
132
|
make_hub_request = True
|
|
122
133
|
if settings_file.exists():
|
|
123
134
|
isettings = load_instance_settings(settings_file)
|
|
135
|
+
# mimic instance_result from hub
|
|
136
|
+
instance_result = {"id": isettings.id.hex}
|
|
124
137
|
# skip hub request for a purely local instance
|
|
125
138
|
make_hub_request = isettings.is_remote
|
|
126
139
|
|
|
@@ -139,7 +152,6 @@ def connect(
|
|
|
139
152
|
root=storage_result["root"],
|
|
140
153
|
region=storage_result["region"],
|
|
141
154
|
uid=storage_result["lnid"],
|
|
142
|
-
is_hybrid=instance_result["storage_mode"] == "hybrid",
|
|
143
155
|
)
|
|
144
156
|
isettings = InstanceSettings(
|
|
145
157
|
id=UUID(instance_result["id"]),
|
|
@@ -149,27 +161,24 @@ def connect(
|
|
|
149
161
|
db=db_updated,
|
|
150
162
|
schema=instance_result["schema_str"],
|
|
151
163
|
git_repo=instance_result["git_repo"],
|
|
164
|
+
local_storage=instance_result["storage_mode"] == "hybrid",
|
|
152
165
|
)
|
|
153
166
|
check_whether_migrations_in_sync(instance_result["lamindb_version"])
|
|
154
167
|
else:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
f" '{hub_result}'\nCheck your permissions:"
|
|
158
|
-
f" https://lamin.ai/{owner}/{name}?tab=collaborators"
|
|
168
|
+
message = INSTANCE_NOT_FOUND_MESSAGE.format(
|
|
169
|
+
owner=owner, name=name, hub_result=hub_result
|
|
159
170
|
)
|
|
160
171
|
if settings_file.exists():
|
|
161
172
|
isettings = load_instance_settings(settings_file)
|
|
162
173
|
if isettings.is_remote:
|
|
163
174
|
if _raise_not_reachable_error:
|
|
164
|
-
raise
|
|
175
|
+
raise InstanceNotFoundError(message)
|
|
165
176
|
return "instance-not-reachable"
|
|
166
177
|
|
|
167
178
|
else:
|
|
168
179
|
if _raise_not_reachable_error:
|
|
169
|
-
raise
|
|
180
|
+
raise InstanceNotFoundError(message)
|
|
170
181
|
return "instance-not-reachable"
|
|
171
|
-
# mimic instance_result from hub
|
|
172
|
-
instance_result = {"id": isettings.id.hex}
|
|
173
182
|
|
|
174
183
|
if storage is not None:
|
|
175
184
|
update_isettings_with_storage(isettings, storage)
|
|
@@ -255,7 +264,7 @@ def update_isettings_with_storage(
|
|
|
255
264
|
isettings: InstanceSettings, storage: UPathStr
|
|
256
265
|
) -> None:
|
|
257
266
|
ssettings = StorageSettings(storage)
|
|
258
|
-
if ssettings.
|
|
267
|
+
if ssettings.type_is_cloud:
|
|
259
268
|
try: # triggering ssettings.id makes a lookup in the storage table
|
|
260
269
|
logger.success(f"loaded storage: {ssettings.id} / {ssettings.root_as_str}")
|
|
261
270
|
except RuntimeError as e:
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from lamin_utils import logger
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from .core._settings_instance import InstanceSettings
|
|
7
|
+
from .core._settings_storage import StorageSettings
|
|
8
|
+
from .core._settings import settings
|
|
9
|
+
from .core._settings_load import load_instance_settings
|
|
10
|
+
from .core._settings_store import instance_settings_file
|
|
11
|
+
from .core.upath import check_storage_is_empty, hosted_buckets
|
|
12
|
+
from .core._hub_core import delete_instance as delete_instance_on_hub
|
|
13
|
+
from .core._hub_core import connect_instance as load_instance_from_hub
|
|
14
|
+
from ._connect_instance import INSTANCE_NOT_FOUND_MESSAGE
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def delete_cache(cache_dir: Path):
|
|
18
|
+
if cache_dir is not None and cache_dir.exists():
|
|
19
|
+
shutil.rmtree(cache_dir)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def delete_exclusion_dir(isettings: InstanceSettings) -> None:
|
|
23
|
+
exclusion_dir = isettings.storage.root / f".lamindb/_exclusion/{isettings.id.hex}"
|
|
24
|
+
if exclusion_dir.exists():
|
|
25
|
+
exclusion_dir.rmdir()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def delete_by_isettings(isettings: InstanceSettings) -> None:
|
|
29
|
+
settings_file = isettings._get_settings_file()
|
|
30
|
+
if settings_file.exists():
|
|
31
|
+
settings_file.unlink()
|
|
32
|
+
delete_cache(isettings.storage.cache_dir)
|
|
33
|
+
if isettings.dialect == "sqlite":
|
|
34
|
+
try:
|
|
35
|
+
if isettings._sqlite_file.exists():
|
|
36
|
+
isettings._sqlite_file.unlink()
|
|
37
|
+
except PermissionError:
|
|
38
|
+
logger.warning(
|
|
39
|
+
"Did not have permission to delete SQLite file:"
|
|
40
|
+
f" {isettings._sqlite_file}"
|
|
41
|
+
)
|
|
42
|
+
pass
|
|
43
|
+
# unset the global instance settings
|
|
44
|
+
if settings._instance_exists and isettings.slug == settings.instance.slug:
|
|
45
|
+
if settings._instance_settings_path.exists():
|
|
46
|
+
settings._instance_settings_path.unlink()
|
|
47
|
+
settings._instance_settings = None
|
|
48
|
+
if isettings.storage._mark_storage_root.exists():
|
|
49
|
+
isettings.storage._mark_storage_root.unlink()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def delete(
|
|
53
|
+
instance_name: str, force: bool = False, require_empty: bool = True
|
|
54
|
+
) -> Optional[int]:
|
|
55
|
+
"""Delete a LaminDB instance.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
instance_name (str): The name of the instance to delete.
|
|
59
|
+
force (bool): Whether to skip the confirmation prompt.
|
|
60
|
+
require_empty (bool): Whether to check if the instance is empty before deleting.
|
|
61
|
+
"""
|
|
62
|
+
if "/" in instance_name:
|
|
63
|
+
logger.warning(
|
|
64
|
+
"Deleting the instance of another user is currently not supported with the"
|
|
65
|
+
" CLI. Please provide only the instance name when deleting an instance ('/'"
|
|
66
|
+
" delimiter not allowed)."
|
|
67
|
+
)
|
|
68
|
+
raise ValueError("Invalid instance name: '/' delimiter not allowed.")
|
|
69
|
+
instance_slug = f"{settings.user.handle}/{instance_name}"
|
|
70
|
+
if settings._instance_exists and settings.instance.name == instance_name:
|
|
71
|
+
isettings = settings.instance
|
|
72
|
+
else:
|
|
73
|
+
settings_file = instance_settings_file(instance_name, settings.user.handle)
|
|
74
|
+
if not settings_file.exists():
|
|
75
|
+
hub_result = load_instance_from_hub(
|
|
76
|
+
owner=settings.user.handle, name=instance_name
|
|
77
|
+
)
|
|
78
|
+
if isinstance(hub_result, str):
|
|
79
|
+
message = INSTANCE_NOT_FOUND_MESSAGE.format(
|
|
80
|
+
owner=settings.user.handle,
|
|
81
|
+
name=instance_name,
|
|
82
|
+
hub_result=hub_result,
|
|
83
|
+
)
|
|
84
|
+
logger.warning(message)
|
|
85
|
+
return None
|
|
86
|
+
instance_result, storage_result = hub_result
|
|
87
|
+
ssettings = StorageSettings(
|
|
88
|
+
root=storage_result["root"],
|
|
89
|
+
region=storage_result["region"],
|
|
90
|
+
uid=storage_result["lnid"],
|
|
91
|
+
)
|
|
92
|
+
isettings = InstanceSettings(
|
|
93
|
+
id=UUID(instance_result["id"]),
|
|
94
|
+
owner=settings.user.handle,
|
|
95
|
+
name=instance_name,
|
|
96
|
+
storage=ssettings,
|
|
97
|
+
local_storage=instance_result["storage_mode"] == "hybrid",
|
|
98
|
+
db=instance_result["db"] if "db" in instance_result else None,
|
|
99
|
+
schema=instance_result["schema_str"],
|
|
100
|
+
git_repo=instance_result["git_repo"],
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
isettings = load_instance_settings(settings_file)
|
|
104
|
+
if isettings.dialect != "sqlite":
|
|
105
|
+
logger.warning(
|
|
106
|
+
f"delete() does not yet affect your Postgres database at {isettings.db}"
|
|
107
|
+
)
|
|
108
|
+
if not force:
|
|
109
|
+
valid_responses = ["y", "yes"]
|
|
110
|
+
user_input = (
|
|
111
|
+
input(f"Are you sure you want to delete instance {instance_slug}? (y/n) ")
|
|
112
|
+
.strip()
|
|
113
|
+
.lower()
|
|
114
|
+
)
|
|
115
|
+
if user_input not in valid_responses:
|
|
116
|
+
return -1
|
|
117
|
+
|
|
118
|
+
# the actual deletion process begins here
|
|
119
|
+
if isettings.dialect == "sqlite" and isettings.is_remote:
|
|
120
|
+
# delete the exlusion dir first because it's hard to count its objects
|
|
121
|
+
delete_exclusion_dir(isettings)
|
|
122
|
+
if isettings.storage.type_is_cloud and isettings.storage.root_as_str.startswith(
|
|
123
|
+
hosted_buckets
|
|
124
|
+
):
|
|
125
|
+
if not require_empty:
|
|
126
|
+
logger.warning(
|
|
127
|
+
"hosted storage always has to be empty, ignoring `require_empty`"
|
|
128
|
+
)
|
|
129
|
+
require_empty = True
|
|
130
|
+
n_objects = check_storage_is_empty(
|
|
131
|
+
isettings.storage.root,
|
|
132
|
+
raise_error=require_empty,
|
|
133
|
+
account_for_sqlite_file=isettings.dialect == "sqlite",
|
|
134
|
+
)
|
|
135
|
+
logger.info(f"deleting instance {instance_slug}")
|
|
136
|
+
# below we can skip check_storage_is_empty() because we already called
|
|
137
|
+
# it above
|
|
138
|
+
delete_instance_on_hub(isettings.id, require_empty=False)
|
|
139
|
+
delete_by_isettings(isettings)
|
|
140
|
+
if n_objects == 0 and isettings.storage.type == "local":
|
|
141
|
+
# dir is only empty after sqlite file was delete via delete_by_isettings
|
|
142
|
+
(isettings.storage.root / ".lamindb").rmdir()
|
|
143
|
+
isettings.storage.root.rmdir()
|
|
144
|
+
return None
|
|
@@ -269,7 +269,7 @@ def init(
|
|
|
269
269
|
delete_instance_record(isettings.id)
|
|
270
270
|
isettings._get_settings_file().unlink(missing_ok=True) # type: ignore
|
|
271
271
|
if ssettings is not None:
|
|
272
|
-
delete_storage_record(ssettings.
|
|
272
|
+
delete_storage_record(ssettings._uuid) # type: ignore
|
|
273
273
|
raise e
|
|
274
274
|
return None
|
|
275
275
|
|
|
@@ -16,6 +16,9 @@ def check_whether_migrations_in_sync(db_version_str: str):
|
|
|
16
16
|
installed_version_str = metadata.version("lamindb")
|
|
17
17
|
except metadata.PackageNotFoundError:
|
|
18
18
|
return None
|
|
19
|
+
if db_version_str is None:
|
|
20
|
+
logger.warning("no lamindb version stored to compare with installed version")
|
|
21
|
+
return None
|
|
19
22
|
installed_version = version.parse(installed_version_str)
|
|
20
23
|
db_version = version.parse(db_version_str)
|
|
21
24
|
if (
|
|
@@ -83,7 +86,7 @@ class migrate:
|
|
|
83
86
|
collaborator = call_with_fallback_auth(
|
|
84
87
|
select_collaborator,
|
|
85
88
|
instance_id=instance_id_str,
|
|
86
|
-
account_id=settings.user.
|
|
89
|
+
account_id=settings.user._uuid,
|
|
87
90
|
)
|
|
88
91
|
if collaborator is None or collaborator["role"] != "admin":
|
|
89
92
|
raise SystemExit(
|
|
@@ -17,6 +17,6 @@ def register(_test: bool = False):
|
|
|
17
17
|
if ssettings._uid is None and _test:
|
|
18
18
|
# because django isn't up, we can't get it from the database
|
|
19
19
|
ssettings._uid = base62(8)
|
|
20
|
-
ssettings.
|
|
20
|
+
ssettings._uuid_ = init_storage_hub(ssettings)
|
|
21
21
|
init_instance_hub(isettings)
|
|
22
22
|
isettings._persist()
|
|
@@ -99,7 +99,7 @@ def login(
|
|
|
99
99
|
user_settings.uid = user_id
|
|
100
100
|
user_settings.handle = user_handle
|
|
101
101
|
user_settings.name = user_name
|
|
102
|
-
user_settings.
|
|
102
|
+
user_settings._uuid = user_uuid
|
|
103
103
|
user_settings.access_token = access_token
|
|
104
104
|
save_user_settings(user_settings)
|
|
105
105
|
|