lamindb_setup 0.69.4__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.
Files changed (90) hide show
  1. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/PKG-INFO +1 -1
  2. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/changelog.md +5 -0
  3. lamindb_setup-0.70.0/docs/hub-cloud/01-init-local-instance.ipynb +114 -0
  4. lamindb_setup-0.69.4/docs/hub-cloud/02-connect-on-prem-instance.ipynb → lamindb_setup-0.70.0/docs/hub-cloud/02-connect-local-instance.ipynb +6 -13
  5. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/03-set-storage.ipynb +1 -1
  6. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +1 -1
  7. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +17 -1
  8. lamindb_setup-0.70.0/docs/hub-cloud/07-connect-hybrid-instance.ipynb +86 -0
  9. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-empty-init.ipynb +1 -1
  10. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/notebooks.md +3 -2
  11. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/__init__.py +1 -1
  12. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_connect_instance.py +19 -10
  13. lamindb_setup-0.70.0/lamindb_setup/_delete.py +144 -0
  14. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_init_instance.py +1 -1
  15. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_migrate.py +4 -1
  16. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_register_instance.py +1 -1
  17. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_setup_user.py +1 -1
  18. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_core.py +27 -16
  19. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_instance.py +67 -13
  20. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_load.py +1 -1
  21. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_save.py +1 -1
  22. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_storage.py +26 -58
  23. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_user.py +1 -1
  24. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/django.py +3 -0
  25. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/upath.py +49 -15
  26. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_connect_instance.py +13 -31
  27. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_init_instance.py +12 -36
  28. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-local/test_all.py +11 -11
  29. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-prod/conftest.py +0 -3
  30. lamindb_setup-0.69.4/docs/hub-cloud/01-init-on-prem-instance.ipynb +0 -366
  31. lamindb_setup-0.69.4/lamindb_setup/_delete.py +0 -78
  32. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/.github/workflows/build.yml +0 -0
  33. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/.github/workflows/latest-changes.jinja2 +0 -0
  34. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/.github/workflows/latest-changes.yml +0 -0
  35. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/.gitignore +0 -0
  36. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/.pre-commit-config.yaml +0 -0
  37. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/LICENSE +0 -0
  38. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/README.md +0 -0
  39. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
  40. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/test-multi-session.ipynb +0 -0
  41. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-cloud/test_notebooks.py +0 -0
  42. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
  43. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
  44. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
  45. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
  46. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
  47. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
  48. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
  49. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/hub-prod/test_notebooks2.py +0 -0
  50. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/index.md +0 -0
  51. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/docs/reference.md +0 -0
  52. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_add_remote_storage.py +0 -0
  53. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_cache.py +0 -0
  54. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_check.py +0 -0
  55. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_check_setup.py +0 -0
  56. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_close.py +0 -0
  57. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_django.py +0 -0
  58. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_exportdb.py +0 -0
  59. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_importdb.py +0 -0
  60. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_schema.py +0 -0
  61. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/_silence_loggers.py +0 -0
  62. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/__init__.py +0 -0
  63. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_aws_storage.py +0 -0
  64. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_deprecated.py +0 -0
  65. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_docs.py +0 -0
  66. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_client.py +0 -0
  67. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_crud.py +0 -0
  68. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_hub_utils.py +0 -0
  69. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings.py +0 -0
  70. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_settings_store.py +0 -0
  71. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
  72. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
  73. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/exceptions.py +0 -0
  74. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/hashing.py +0 -0
  75. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/lamindb_setup/core/types.py +0 -0
  76. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/noxfile.py +0 -0
  77. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/pyproject.toml +0 -0
  78. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_delete_instance.py +0 -0
  79. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_login.py +0 -0
  80. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_migrate.py +0 -0
  81. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-cloud/test_set_storage.py +0 -0
  82. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-local/conftest.py +0 -0
  83. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-prod/test_auto_connect.py +0 -0
  84. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-prod/test_django.py +0 -0
  85. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
  86. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/hub-prod/test_upath.py +0 -0
  87. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/storage/test_hashing.py +0 -0
  88. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/storage/test_storage_access.py +0 -0
  89. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/storage/test_storage_basis.py +0 -0
  90. {lamindb_setup-0.69.4 → lamindb_setup-0.70.0}/tests/storage/test_storage_stats.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamindb_setup
3
- Version: 0.69.4
3
+ Version: 0.70.0
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <laminlabs@gmail.com>
6
6
  Description-Content-Type: text/markdown
@@ -3,6 +3,11 @@
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 |
10
+ ✨ Upload dirs inplace | [722](https://github.com/laminlabs/lamindb-setup/pull/722) | [Koncopd](https://github.com/Koncopd) | 2024-04-20 | 0.69.5
6
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
7
12
  ♻️ Improve suffix handling | [718](https://github.com/laminlabs/lamindb-setup/pull/718) | [falexwolf](https://github.com/falexwolf) | 2024-04-19 | 0.69.3
8
13
  ✨ Enable hybrid storage mode | [717](https://github.com/laminlabs/lamindb-setup/pull/717) | [falexwolf](https://github.com/falexwolf) | 2024-04-16 | 0.69.1
@@ -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
- "# Load & delete an on-prem instance"
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
- "!yes | lamin delete mydata\n",
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.is_cloud == False\n",
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
- "## Delete an instance"
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.9.15"
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.is_cloud\n",
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.is_cloud == True\n",
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",
@@ -88,7 +88,23 @@
88
88
  "target_dir = root / \"test-dir-upload\"\n",
89
89
  "target_dir.upload_from(test_dir, recursive=True)\n",
90
90
  "\n",
91
- "assert target_dir.is_dir()"
91
+ "assert target_dir.is_dir()\n",
92
+ "assert (target_dir / \"test-dir-upload\").exists()\n",
93
+ "\n",
94
+ "target_dir.rmdir()\n",
95
+ "assert not target_dir.exists()"
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": null,
101
+ "metadata": {},
102
+ "outputs": [],
103
+ "source": [
104
+ "target_dir.upload_from(test_dir, dir_inplace=True)\n",
105
+ "\n",
106
+ "assert target_dir.is_dir()\n",
107
+ "assert not (target_dir / \"test-dir-upload\").exists()"
92
108
  ]
93
109
  },
94
110
  {
@@ -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.is_cloud\n",
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-on-prem-instance
7
- hub-cloud/connect-on-prem-instance
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
@@ -36,7 +36,7 @@ Modules & settings:
36
36
 
37
37
  """
38
38
 
39
- __version__ = "0.69.4" # denote a release candidate for 0.1.0 with 0.1rc1
39
+ __version__ = "0.70.0" # denote a release candidate for 0.1.0 with 0.1rc1
40
40
 
41
41
  import sys
42
42
  from os import name as _os_name
@@ -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
- error_message = (
156
- f"'{owner}/{name}' not loadable:"
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 SystemExit(error_message)
175
+ raise InstanceNotFoundError(message)
165
176
  return "instance-not-reachable"
166
177
 
167
178
  else:
168
179
  if _raise_not_reachable_error:
169
- raise SystemExit(error_message)
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.is_cloud:
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.uuid) # type: ignore
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.uuid,
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._uuid = init_storage_hub(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.uuid = user_uuid
102
+ user_settings._uuid = user_uuid
103
103
  user_settings.access_token = access_token
104
104
  save_user_settings(user_settings)
105
105