lamindb_setup 1.10.0__tar.gz → 1.10.1__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-1.10.0 → lamindb_setup-1.10.1}/PKG-INFO +2 -2
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/02-connect-local-instance.ipynb +15 -11
- lamindb_setup-1.10.1/docs/hub-cloud/09-test-migrate.ipynb +94 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-import-schema.ipynb +3 -4
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/__init__.py +1 -1
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_connect_instance.py +34 -19
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_migrate.py +7 -7
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_deprecated.py +1 -1
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_hub_core.py +30 -7
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_hub_crud.py +40 -20
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings.py +4 -14
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_instance.py +32 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/django.py +3 -7
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/pyproject.toml +1 -1
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_connect_instance.py +4 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_init_instance.py +3 -1
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-local/scripts/script-connect-fine-grained-access.py +4 -1
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-local/test_all.py +93 -53
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/test_django.py +0 -4
- lamindb_setup-1.10.1/tests/hub-prod/test_migrate.py +13 -0
- lamindb_setup-1.10.0/tests/hub-cloud/test_migrate.py +0 -22
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/.github/workflows/build.yml +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/.gitignore +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/.pre-commit-config.yaml +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/LICENSE +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/README.md +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/changelog.md +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/08-test-multi-session.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/index.md +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/notebooks.md +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/reference.md +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_delete.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_disconnect.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_entry_points.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_init_instance.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_schema_metadata.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_setup_user.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_aws_options.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_hub_client.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_load.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_save.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_store.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_settings_user.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/core/upath.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/errors.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/py.typed +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/lamindb_setup/types.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/noxfile.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_edge_request.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-local/conftest.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-local/test_update_schema_in_hub.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/test_aws_options_manager.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_entry_point.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_storage_settings.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/tests/storage/test_to_url.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: lamindb_setup
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.1
|
|
4
4
|
Summary: Setup & configure LaminDB.
|
|
5
5
|
Author-email: Lamin Labs <open-source@lamin.ai>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -27,7 +27,7 @@ Requires-Dist: psycopg2-binary ; extra == "dev"
|
|
|
27
27
|
Requires-Dist: python-dotenv ; extra == "dev"
|
|
28
28
|
Requires-Dist: nox ; extra == "dev"
|
|
29
29
|
Requires-Dist: pytest>=6.0 ; extra == "dev"
|
|
30
|
-
Requires-Dist: pytest-cov ; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov<7.0.0 ; extra == "dev"
|
|
31
31
|
Requires-Dist: pytest-xdist ; extra == "dev"
|
|
32
32
|
Requires-Dist: nbproject-test>=0.4.3 ; extra == "dev"
|
|
33
33
|
Requires-Dist: pandas ; extra == "dev"
|
{lamindb_setup-1.10.0 → lamindb_setup-1.10.1}/docs/hub-cloud/02-connect-local-instance.ipynb
RENAMED
|
@@ -60,10 +60,7 @@
|
|
|
60
60
|
"metadata": {},
|
|
61
61
|
"outputs": [],
|
|
62
62
|
"source": [
|
|
63
|
-
"#
|
|
64
|
-
"# _check_instance_setup is called inside with from_module=None\n",
|
|
65
|
-
"# the branch where django is not setup yet\n",
|
|
66
|
-
"# as from_module=None it won't connect to an instance here\n",
|
|
63
|
+
"# no instance connected, prompts to connect\n",
|
|
67
64
|
"import bionty"
|
|
68
65
|
]
|
|
69
66
|
},
|
|
@@ -79,6 +76,17 @@
|
|
|
79
76
|
") # also test passing _reload_lamindb explicitly"
|
|
80
77
|
]
|
|
81
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"cell_type": "code",
|
|
81
|
+
"execution_count": null,
|
|
82
|
+
"id": "5a59b8d0",
|
|
83
|
+
"metadata": {},
|
|
84
|
+
"outputs": [],
|
|
85
|
+
"source": [
|
|
86
|
+
"# this is a local intstance, no spaces needed\n",
|
|
87
|
+
"assert ln_setup.settings.instance.available_spaces is None"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
82
90
|
{
|
|
83
91
|
"cell_type": "code",
|
|
84
92
|
"execution_count": null,
|
|
@@ -88,8 +96,7 @@
|
|
|
88
96
|
"source": [
|
|
89
97
|
"# wetlab is not in the (schema) modules of mydata\n",
|
|
90
98
|
"with pytest.raises(ModuleWasntConfigured):\n",
|
|
91
|
-
" # _check_instance_setup is called inside
|
|
92
|
-
" # the branch where django is setup\n",
|
|
99
|
+
" # _check_instance_setup is called inside\n",
|
|
93
100
|
" import wetlab"
|
|
94
101
|
]
|
|
95
102
|
},
|
|
@@ -100,12 +107,9 @@
|
|
|
100
107
|
"metadata": {},
|
|
101
108
|
"outputs": [],
|
|
102
109
|
"source": [
|
|
103
|
-
"#
|
|
110
|
+
"# bionty is not in the (schema) modules of mydata\n",
|
|
104
111
|
"with pytest.raises(ModuleWasntConfigured):\n",
|
|
105
|
-
"
|
|
106
|
-
" # the branch where django is setup\n",
|
|
107
|
-
" # in __getattr__ in __init__.py\n",
|
|
108
|
-
" bionty.CellType"
|
|
112
|
+
" import bionty"
|
|
109
113
|
]
|
|
110
114
|
},
|
|
111
115
|
{
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "5acb0094",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# Migrate a hosted instance"
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"cell_type": "code",
|
|
13
|
+
"execution_count": null,
|
|
14
|
+
"id": "213594a4",
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [],
|
|
17
|
+
"source": [
|
|
18
|
+
"import lamindb_setup as ln_setup"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"cell_type": "code",
|
|
23
|
+
"execution_count": null,
|
|
24
|
+
"id": "0a310f89",
|
|
25
|
+
"metadata": {},
|
|
26
|
+
"outputs": [],
|
|
27
|
+
"source": [
|
|
28
|
+
"ln_setup.login(\"testuser1\")"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"cell_type": "code",
|
|
33
|
+
"execution_count": null,
|
|
34
|
+
"id": "eecceaf0",
|
|
35
|
+
"metadata": {},
|
|
36
|
+
"outputs": [],
|
|
37
|
+
"source": [
|
|
38
|
+
"ln_setup.connect(\"laminlabs/lamindata\", use_root_db_user=True)"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"cell_type": "code",
|
|
43
|
+
"execution_count": null,
|
|
44
|
+
"id": "ffb9b496",
|
|
45
|
+
"metadata": {},
|
|
46
|
+
"outputs": [],
|
|
47
|
+
"source": [
|
|
48
|
+
"# double connect to check migration with django reset\n",
|
|
49
|
+
"ln_setup.connect(\"laminlabs/lamindata\", use_root_db_user=True)"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"cell_type": "code",
|
|
54
|
+
"execution_count": null,
|
|
55
|
+
"id": "e9887c91",
|
|
56
|
+
"metadata": {},
|
|
57
|
+
"outputs": [],
|
|
58
|
+
"source": [
|
|
59
|
+
"assert \"root\" in ln_setup.settings.instance.db"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"cell_type": "code",
|
|
64
|
+
"execution_count": null,
|
|
65
|
+
"id": "657de4c6",
|
|
66
|
+
"metadata": {},
|
|
67
|
+
"outputs": [],
|
|
68
|
+
"source": [
|
|
69
|
+
"ln_setup.migrate.deploy()"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"metadata": {
|
|
74
|
+
"kernelspec": {
|
|
75
|
+
"display_name": "Python 3 (ipykernel)",
|
|
76
|
+
"language": "python",
|
|
77
|
+
"name": "python3"
|
|
78
|
+
},
|
|
79
|
+
"language_info": {
|
|
80
|
+
"codemirror_mode": {
|
|
81
|
+
"name": "ipython",
|
|
82
|
+
"version": 3
|
|
83
|
+
},
|
|
84
|
+
"file_extension": ".py",
|
|
85
|
+
"mimetype": "text/x-python",
|
|
86
|
+
"name": "python",
|
|
87
|
+
"nbconvert_exporter": "python",
|
|
88
|
+
"pygments_lexer": "ipython3",
|
|
89
|
+
"version": "3.10.16"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"nbformat": 4,
|
|
93
|
+
"nbformat_minor": 5
|
|
94
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cells": [
|
|
3
3
|
{
|
|
4
|
-
"attachments": {},
|
|
5
4
|
"cell_type": "markdown",
|
|
6
5
|
"id": "261ca5e4-f46f-4361-9c3e-f944bbe14484",
|
|
7
6
|
"metadata": {},
|
|
@@ -16,7 +15,7 @@
|
|
|
16
15
|
"source": [
|
|
17
16
|
"Also see the corresponding FAQ notebook in lamindb: `import-modules`.\n",
|
|
18
17
|
"\n",
|
|
19
|
-
"
|
|
18
|
+
"You'll load the instance in the same way as calling `import lamindb` when you import a schema module."
|
|
20
19
|
]
|
|
21
20
|
},
|
|
22
21
|
{
|
|
@@ -60,7 +59,7 @@
|
|
|
60
59
|
"metadata": {},
|
|
61
60
|
"outputs": [],
|
|
62
61
|
"source": [
|
|
63
|
-
"assert
|
|
62
|
+
"assert lamindb_setup.core.django.IS_SETUP"
|
|
64
63
|
]
|
|
65
64
|
},
|
|
66
65
|
{
|
|
@@ -110,7 +109,7 @@
|
|
|
110
109
|
"name": "python",
|
|
111
110
|
"nbconvert_exporter": "python",
|
|
112
111
|
"pygments_lexer": "ipython3",
|
|
113
|
-
"version": "3.10.
|
|
112
|
+
"version": "3.10.16"
|
|
114
113
|
},
|
|
115
114
|
"nbproject": {
|
|
116
115
|
"id": "2lhqA4uTKSFP",
|
|
@@ -24,6 +24,7 @@ from .core._settings_load import load_instance_settings
|
|
|
24
24
|
from .core._settings_storage import StorageSettings
|
|
25
25
|
from .core._settings_store import instance_settings_file, settings_dir
|
|
26
26
|
from .core.cloud_sqlite_locker import unlock_cloud_sqlite_upon_exception
|
|
27
|
+
from .core.django import reset_django
|
|
27
28
|
from .errors import CannotSwitchDefaultInstance
|
|
28
29
|
|
|
29
30
|
if TYPE_CHECKING:
|
|
@@ -101,6 +102,7 @@ def _connect_instance(
|
|
|
101
102
|
*,
|
|
102
103
|
db: str | None = None,
|
|
103
104
|
raise_permission_error: bool = True,
|
|
105
|
+
use_root_db_user: bool = False,
|
|
104
106
|
access_token: str | None = None,
|
|
105
107
|
) -> InstanceSettings:
|
|
106
108
|
settings_file = instance_settings_file(name, owner)
|
|
@@ -120,7 +122,10 @@ def _connect_instance(
|
|
|
120
122
|
# do not call hub if the user is anonymous
|
|
121
123
|
if owner != "anonymous":
|
|
122
124
|
hub_result = connect_instance_hub(
|
|
123
|
-
owner=owner,
|
|
125
|
+
owner=owner,
|
|
126
|
+
name=name,
|
|
127
|
+
access_token=access_token,
|
|
128
|
+
use_root_db_user=use_root_db_user,
|
|
124
129
|
)
|
|
125
130
|
else:
|
|
126
131
|
hub_result = "anonymous-user"
|
|
@@ -155,7 +160,9 @@ def _connect_instance(
|
|
|
155
160
|
schema_id=None
|
|
156
161
|
if (schema_id := instance_result["schema_id"]) is None
|
|
157
162
|
else UUID(schema_id),
|
|
158
|
-
fine_grained_access=
|
|
163
|
+
fine_grained_access=bool(
|
|
164
|
+
instance_result["fine_grained_access"]
|
|
165
|
+
), # can be None
|
|
159
166
|
db_permissions=instance_result.get("db_permissions", None),
|
|
160
167
|
)
|
|
161
168
|
else:
|
|
@@ -186,6 +193,8 @@ def reset_django_module_variables():
|
|
|
186
193
|
# to the old classes
|
|
187
194
|
# There doesn't seem to be an easy way to fix this problem
|
|
188
195
|
|
|
196
|
+
logger.important_hint("resetting django module variables")
|
|
197
|
+
|
|
189
198
|
import types
|
|
190
199
|
|
|
191
200
|
from django.apps import apps
|
|
@@ -230,12 +239,11 @@ def reset_django_module_variables():
|
|
|
230
239
|
continue
|
|
231
240
|
|
|
232
241
|
|
|
233
|
-
def _connect_cli(instance: str) -> None:
|
|
242
|
+
def _connect_cli(instance: str, use_root_db_user: bool = False) -> None:
|
|
234
243
|
from lamindb_setup import settings as settings_
|
|
235
244
|
|
|
236
|
-
settings_.auto_connect = True
|
|
237
245
|
owner, name = get_owner_name_from_identifier(instance)
|
|
238
|
-
isettings = _connect_instance(owner, name)
|
|
246
|
+
isettings = _connect_instance(owner, name, use_root_db_user=use_root_db_user)
|
|
239
247
|
isettings._persist(write_to_disk=True)
|
|
240
248
|
if not isettings.is_on_hub or isettings._is_cloud_sqlite:
|
|
241
249
|
# there are two reasons to call the full-blown connect
|
|
@@ -262,6 +270,7 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
262
270
|
"""
|
|
263
271
|
# validate kwargs
|
|
264
272
|
valid_kwargs = {
|
|
273
|
+
"use_root_db_user",
|
|
265
274
|
"_db",
|
|
266
275
|
"_write_settings",
|
|
267
276
|
"_raise_not_found_error",
|
|
@@ -274,6 +283,7 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
274
283
|
raise TypeError(f"connect() got unexpected keyword argument '{kwarg}'")
|
|
275
284
|
isettings: InstanceSettings = None # type: ignore
|
|
276
285
|
# _db is still needed because it is called in init
|
|
286
|
+
use_root_db_user: bool = kwargs.get("use_root_db_user", False)
|
|
277
287
|
_db: str | None = kwargs.get("_db", None)
|
|
278
288
|
_write_settings: bool = kwargs.get("_write_settings", False)
|
|
279
289
|
_raise_not_found_error: bool = kwargs.get("_raise_not_found_error", True)
|
|
@@ -289,12 +299,18 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
289
299
|
|
|
290
300
|
try:
|
|
291
301
|
if instance is None:
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
302
|
+
if settings._instance_exists:
|
|
303
|
+
isettings = settings.instance
|
|
304
|
+
else:
|
|
305
|
+
isettings_or_none = _get_current_instance_settings()
|
|
306
|
+
if isettings_or_none is None:
|
|
307
|
+
raise ValueError(
|
|
308
|
+
"No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
|
|
309
|
+
)
|
|
310
|
+
isettings = isettings_or_none
|
|
311
|
+
if use_root_db_user:
|
|
312
|
+
reset_django()
|
|
313
|
+
owner, name = isettings.owner, isettings.name
|
|
298
314
|
if _db is not None and isettings.dialect == "postgresql":
|
|
299
315
|
isettings._db = _db
|
|
300
316
|
else:
|
|
@@ -310,14 +326,13 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
310
326
|
# could be made more specific by checking whether the django
|
|
311
327
|
# configured database is the same as the one in settings
|
|
312
328
|
and connection.settings_dict["NAME"] != ":memory:"
|
|
329
|
+
and not use_root_db_user # always re-connect for root db user
|
|
313
330
|
):
|
|
314
331
|
logger.important(
|
|
315
332
|
f"doing nothing, already connected lamindb: {settings.instance.slug}"
|
|
316
333
|
)
|
|
317
334
|
return None
|
|
318
335
|
else:
|
|
319
|
-
from lamindb_setup.core.django import reset_django
|
|
320
|
-
|
|
321
336
|
if (
|
|
322
337
|
settings._instance_exists
|
|
323
338
|
and settings.instance.slug != "none/none"
|
|
@@ -328,11 +343,6 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
328
343
|
raise CannotSwitchDefaultInstance(
|
|
329
344
|
"Cannot switch default instance while `ln.track()` is live: call `ln.finish()`"
|
|
330
345
|
)
|
|
331
|
-
else:
|
|
332
|
-
logger.important_hint(
|
|
333
|
-
"switching the default lamindb instance might produce unexpected side effects with function-scoped imports: "
|
|
334
|
-
"please import lamindb at the module level instead of inside functions"
|
|
335
|
-
)
|
|
336
346
|
reset_django()
|
|
337
347
|
elif (
|
|
338
348
|
_write_settings
|
|
@@ -341,9 +351,14 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
341
351
|
):
|
|
342
352
|
disconnect(mute=True)
|
|
343
353
|
|
|
354
|
+
if instance is not None or use_root_db_user:
|
|
344
355
|
try:
|
|
345
356
|
isettings = _connect_instance(
|
|
346
|
-
owner,
|
|
357
|
+
owner,
|
|
358
|
+
name,
|
|
359
|
+
db=_db,
|
|
360
|
+
access_token=access_token,
|
|
361
|
+
use_root_db_user=use_root_db_user,
|
|
347
362
|
)
|
|
348
363
|
except InstanceNotFoundError as e:
|
|
349
364
|
if _raise_not_found_error:
|
|
@@ -93,17 +93,13 @@ class migrate:
|
|
|
93
93
|
@disable_auto_connect
|
|
94
94
|
def create(cls) -> None:
|
|
95
95
|
"""Create a migration."""
|
|
96
|
-
if _check_instance_setup():
|
|
97
|
-
raise RuntimeError("Restart Python session to create migration or use CLI!")
|
|
98
96
|
setup_django(settings.instance, create_migrations=True)
|
|
99
97
|
|
|
100
98
|
@classmethod
|
|
101
99
|
def deploy(cls, package_name: str | None = None, number: int | None = None) -> None:
|
|
102
100
|
"""Deploy a migration."""
|
|
103
|
-
from .
|
|
104
|
-
|
|
105
|
-
if _check_instance_setup():
|
|
106
|
-
raise RuntimeError("Restart Python session to migrate or use CLI!")
|
|
101
|
+
from lamindb_setup._connect_instance import connect
|
|
102
|
+
from lamindb_setup._schema_metadata import update_schema_in_hub
|
|
107
103
|
from lamindb_setup.core._hub_client import call_with_fallback_auth
|
|
108
104
|
from lamindb_setup.core._hub_crud import (
|
|
109
105
|
select_collaborator,
|
|
@@ -117,12 +113,17 @@ class migrate:
|
|
|
117
113
|
select_collaborator,
|
|
118
114
|
instance_id=settings.instance._id,
|
|
119
115
|
account_id=settings.user._uuid,
|
|
116
|
+
fine_grained_access=settings.instance._fine_grained_access,
|
|
120
117
|
)
|
|
121
118
|
if collaborator is None or collaborator["role"] != "admin":
|
|
122
119
|
raise SystemExit(
|
|
123
120
|
"❌ Only admins can deploy migrations, please ensure that you're an"
|
|
124
121
|
f" admin: https://lamin.ai/{settings.instance.slug}/settings"
|
|
125
122
|
)
|
|
123
|
+
# ensure we connect with the root user
|
|
124
|
+
if "root" not in settings.instance.db:
|
|
125
|
+
connect(use_root_db_user=True)
|
|
126
|
+
assert "root" in (instance_db := settings.instance.db), instance_db
|
|
126
127
|
# we need lamindb to be installed, otherwise we can't populate the version
|
|
127
128
|
# information in the hub
|
|
128
129
|
import lamindb
|
|
@@ -139,7 +140,6 @@ class migrate:
|
|
|
139
140
|
# this populates the hub
|
|
140
141
|
if settings.instance.is_on_hub:
|
|
141
142
|
logger.important(f"updating lamindb version in hub: {lamindb.__version__}")
|
|
142
|
-
# TODO: integrate update of instance table within update_schema_in_hub & below
|
|
143
143
|
if settings.instance.dialect != "sqlite":
|
|
144
144
|
update_schema_in_hub()
|
|
145
145
|
call_with_fallback_auth(
|
|
@@ -51,7 +51,7 @@ def deprecated(new_name: str):
|
|
|
51
51
|
warnings.warn(
|
|
52
52
|
f"Use {new_name} instead of {func.__name__}, "
|
|
53
53
|
f"{func.__name__} will be removed in the future.",
|
|
54
|
-
category=
|
|
54
|
+
category=DeprecationWarning,
|
|
55
55
|
stacklevel=2,
|
|
56
56
|
)
|
|
57
57
|
return func(*args, **kwargs)
|
|
@@ -424,6 +424,7 @@ def _init_instance_hub(
|
|
|
424
424
|
def _connect_instance_hub(
|
|
425
425
|
owner: str, # account_handle
|
|
426
426
|
name: str, # instance_name
|
|
427
|
+
use_root_db_user: bool,
|
|
427
428
|
client: Client,
|
|
428
429
|
) -> tuple[dict, dict] | str:
|
|
429
430
|
response = client.functions.invoke(
|
|
@@ -475,17 +476,29 @@ def _connect_instance_hub(
|
|
|
475
476
|
|
|
476
477
|
if instance["db_scheme"] is not None:
|
|
477
478
|
db_user_name, db_user_password = None, None
|
|
478
|
-
if
|
|
479
|
+
if (
|
|
480
|
+
"db_user_name" in instance
|
|
481
|
+
and "db_user_password" in instance
|
|
482
|
+
and not use_root_db_user
|
|
483
|
+
):
|
|
479
484
|
db_user_name, db_user_password = (
|
|
480
485
|
instance["db_user_name"],
|
|
481
486
|
instance["db_user_password"],
|
|
482
487
|
)
|
|
483
488
|
else:
|
|
484
|
-
|
|
489
|
+
if use_root_db_user:
|
|
490
|
+
fine_grained_access = False
|
|
491
|
+
else:
|
|
492
|
+
fine_grained_access = bool(
|
|
493
|
+
instance["fine_grained_access"]
|
|
494
|
+
) # can be None
|
|
495
|
+
db_user = select_db_user_by_instance(
|
|
496
|
+
instance["id"], fine_grained_access, client
|
|
497
|
+
)
|
|
485
498
|
if db_user is not None:
|
|
486
499
|
db_user_name, db_user_password = (
|
|
487
|
-
db_user["db_user_name"],
|
|
488
|
-
db_user["db_user_password"],
|
|
500
|
+
db_user["name" if fine_grained_access else "db_user_name"],
|
|
501
|
+
db_user["password" if fine_grained_access else "db_user_password"],
|
|
489
502
|
)
|
|
490
503
|
db_dsn = LaminDsn.build(
|
|
491
504
|
scheme=instance["db_scheme"],
|
|
@@ -505,15 +518,25 @@ def connect_instance_hub(
|
|
|
505
518
|
owner: str, # account_handle
|
|
506
519
|
name: str, # instance_name
|
|
507
520
|
access_token: str | None = None,
|
|
521
|
+
use_root_db_user: bool = False,
|
|
508
522
|
) -> tuple[dict, dict] | str:
|
|
509
523
|
from ._settings import settings
|
|
510
524
|
|
|
511
525
|
if settings.user.handle != "anonymous" or access_token is not None:
|
|
512
526
|
return call_with_fallback_auth(
|
|
513
|
-
_connect_instance_hub,
|
|
527
|
+
_connect_instance_hub,
|
|
528
|
+
owner=owner,
|
|
529
|
+
name=name,
|
|
530
|
+
use_root_db_user=use_root_db_user,
|
|
531
|
+
access_token=access_token,
|
|
514
532
|
)
|
|
515
533
|
else:
|
|
516
|
-
return call_with_fallback(
|
|
534
|
+
return call_with_fallback(
|
|
535
|
+
_connect_instance_hub,
|
|
536
|
+
owner=owner,
|
|
537
|
+
name=name,
|
|
538
|
+
use_root_db_user=use_root_db_user,
|
|
539
|
+
)
|
|
517
540
|
|
|
518
541
|
|
|
519
542
|
def access_aws(storage_root: str, access_token: str | None = None) -> dict[str, dict]:
|
|
@@ -570,7 +593,7 @@ def access_db(
|
|
|
570
593
|
if isinstance(instance, InstanceSettings):
|
|
571
594
|
instance_id = instance._id
|
|
572
595
|
instance_slug = instance.slug
|
|
573
|
-
instance_api_url = instance.
|
|
596
|
+
instance_api_url = instance.api_url
|
|
574
597
|
else:
|
|
575
598
|
instance_id = UUID(instance["id"])
|
|
576
599
|
instance_slug = instance["owner"] + "/" + instance["name"]
|
|
@@ -137,10 +137,12 @@ def update_instance(instance_id: str, instance_fields: dict, client: Client):
|
|
|
137
137
|
def select_collaborator(
|
|
138
138
|
instance_id: str,
|
|
139
139
|
account_id: str,
|
|
140
|
+
fine_grained_access: bool,
|
|
140
141
|
client: Client,
|
|
141
142
|
):
|
|
143
|
+
table = "access_instance" if fine_grained_access else "account_instance"
|
|
142
144
|
data = (
|
|
143
|
-
client.table(
|
|
145
|
+
client.table(table)
|
|
144
146
|
.select("*")
|
|
145
147
|
.eq("instance_id", instance_id)
|
|
146
148
|
.eq("account_id", account_id)
|
|
@@ -180,35 +182,53 @@ def insert_db_user(
|
|
|
180
182
|
db_user_name: str,
|
|
181
183
|
db_user_password: str,
|
|
182
184
|
instance_id: UUID,
|
|
185
|
+
fine_grained_access: bool,
|
|
183
186
|
client: Client,
|
|
184
187
|
) -> None:
|
|
185
|
-
fields =
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
fields = {"instance_id": instance_id.hex}
|
|
189
|
+
if fine_grained_access:
|
|
190
|
+
table = "access_db_user"
|
|
191
|
+
fields.update(
|
|
192
|
+
{
|
|
193
|
+
"name": db_user_name,
|
|
194
|
+
"password": db_user_password,
|
|
195
|
+
"type": name,
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
else:
|
|
199
|
+
table = "db_user"
|
|
200
|
+
fields.update(
|
|
201
|
+
{
|
|
202
|
+
"id": uuid4().hex,
|
|
203
|
+
"name": name,
|
|
204
|
+
"db_user_name": db_user_name,
|
|
205
|
+
"db_user_password": db_user_password,
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
data = client.table(table).insert(fields).execute().data
|
|
195
210
|
return data[0]
|
|
196
211
|
|
|
197
212
|
|
|
198
|
-
def select_db_user_by_instance(
|
|
213
|
+
def select_db_user_by_instance(
|
|
214
|
+
instance_id: str, fine_grained_access: bool, client: Client
|
|
215
|
+
):
|
|
199
216
|
"""Get db_user for which client has permission."""
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
217
|
+
if fine_grained_access:
|
|
218
|
+
table = "access_db_user"
|
|
219
|
+
type_name = "type"
|
|
220
|
+
type_priority = "jwt"
|
|
221
|
+
else:
|
|
222
|
+
table = "db_user"
|
|
223
|
+
type_name = "name"
|
|
224
|
+
type_priority = "write"
|
|
225
|
+
|
|
226
|
+
data = client.table(table).select("*").eq("instance_id", instance_id).execute().data
|
|
207
227
|
if len(data) == 0:
|
|
208
228
|
return None
|
|
209
229
|
elif len(data) > 1:
|
|
210
230
|
for item in data:
|
|
211
|
-
if item[
|
|
231
|
+
if item[type_name] == type_priority:
|
|
212
232
|
return item
|
|
213
233
|
logger.warning("found multiple db credentials, using the first one")
|
|
214
234
|
return data[0]
|
|
@@ -79,24 +79,15 @@ class SetupSettings:
|
|
|
79
79
|
def auto_connect(self) -> bool:
|
|
80
80
|
"""Auto-connect to current instance upon `import lamindb`.
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Upon calling `lamin init` or `lamin connect` on the CLI, this setting is switched to `True`.
|
|
85
|
-
|
|
86
|
-
`ln.connect()` doesn't change the value of this setting.
|
|
87
|
-
|
|
88
|
-
You can manually change this setting
|
|
89
|
-
|
|
90
|
-
- in Python: `ln.setup.settings.auto_connect = True/False`
|
|
91
|
-
- via the CLI: `lamin settings set auto-connect true/false`
|
|
82
|
+
This setting is always `True` and will be removed in a future version.
|
|
92
83
|
"""
|
|
93
84
|
return True
|
|
94
85
|
|
|
95
86
|
@auto_connect.setter
|
|
96
87
|
def auto_connect(self, value: bool) -> None:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
logger.warning(
|
|
89
|
+
"setting auto_connect to `False` no longer has an effect and the setting will likely be removed in the future",
|
|
90
|
+
)
|
|
100
91
|
if value:
|
|
101
92
|
self._auto_connect_path.touch()
|
|
102
93
|
else:
|
|
@@ -324,7 +315,6 @@ class SetupSettings:
|
|
|
324
315
|
else:
|
|
325
316
|
repr += "Current instance: None"
|
|
326
317
|
repr += "\nConfig:\n"
|
|
327
|
-
repr += f" - auto-connect in Python: {self.auto_connect}\n"
|
|
328
318
|
repr += f" - private Django API: {self.private_django_api}\n"
|
|
329
319
|
repr += "Local directories:\n"
|
|
330
320
|
repr += f" - cache: {self.cache_dir.as_posix()}\n"
|
|
@@ -5,6 +5,7 @@ import shutil
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import TYPE_CHECKING, Literal
|
|
7
7
|
|
|
8
|
+
from django.db import connection
|
|
8
9
|
from django.db.utils import ProgrammingError
|
|
9
10
|
from lamin_utils import logger
|
|
10
11
|
|
|
@@ -343,6 +344,37 @@ class InstanceSettings:
|
|
|
343
344
|
"""
|
|
344
345
|
return self._git_repo
|
|
345
346
|
|
|
347
|
+
@property
|
|
348
|
+
def api_url(self) -> str | None:
|
|
349
|
+
"""URL for REST API.
|
|
350
|
+
|
|
351
|
+
Use this URL for API calls related to this instance.
|
|
352
|
+
"""
|
|
353
|
+
return self._api_url
|
|
354
|
+
|
|
355
|
+
@property
|
|
356
|
+
def available_spaces(self) -> dict | None:
|
|
357
|
+
"""Available spaces with roles for instances fine-grained permissions.
|
|
358
|
+
|
|
359
|
+
Returns a dictionary with roles as keys and lists of available spaces
|
|
360
|
+
as values if this instance has fine-grained permissions and the current user
|
|
361
|
+
is a collaborator, `None` otherwise.
|
|
362
|
+
"""
|
|
363
|
+
if self._db_permissions != "jwt":
|
|
364
|
+
return None
|
|
365
|
+
|
|
366
|
+
from lamindb.models import Space
|
|
367
|
+
|
|
368
|
+
spaces: dict = {"admin": [], "write": [], "read": []}
|
|
369
|
+
with connection.cursor() as cur:
|
|
370
|
+
cur.execute("SELECT * FROM check_access() WHERE type = 'space'")
|
|
371
|
+
rows = cur.fetchall()
|
|
372
|
+
for row in rows:
|
|
373
|
+
spaces[row[1]].append(row[0])
|
|
374
|
+
return {
|
|
375
|
+
k: Space.filter(id__in=v).to_list() if v else [] for k, v in spaces.items()
|
|
376
|
+
}
|
|
377
|
+
|
|
346
378
|
@property
|
|
347
379
|
def _id(self) -> UUID:
|
|
348
380
|
"""The internal instance id."""
|