lamindb_setup 1.10.2__tar.gz → 1.12.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-1.10.2 → lamindb_setup-1.12.0}/.github/workflows/build.yml +6 -6
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.gitignore +3 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.pre-commit-config.yaml +5 -5
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/PKG-INFO +3 -2
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/03-add-managed-storage.ipynb +60 -59
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/08-test-multi-session.ipynb +83 -6
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/__init__.py +1 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_connect_instance.py +52 -38
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_delete.py +3 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_init_instance.py +22 -24
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_migrate.py +8 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_schema_metadata.py +20 -16
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_aws_options.py +2 -4
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_aws_storage.py +2 -3
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_client.py +84 -44
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_core.py +35 -12
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings.py +24 -5
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_instance.py +7 -7
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_save.py +2 -2
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_store.py +9 -9
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/django.py +4 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/upath.py +17 -10
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/pyproject.toml +3 -2
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +1 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +3 -2
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_connect_instance.py +7 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_init_instance.py +6 -2
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/conftest.py +0 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/test_all.py +5 -1
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/LICENSE +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/README.md +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/changelog.md +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/09-test-migrate.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/index.md +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/notebooks.md +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/reference.md +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_disconnect.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_entry_points.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_setup_user.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_load.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_storage.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_user.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/errors.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/py.typed +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/types.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/noxfile.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_edge_request.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/scripts/script-connect-fine-grained-access.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/test_update_schema_in_hub.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_aws_options_manager.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_migrate.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_entry_point.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_settings.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_to_url.py +0 -0
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
timeout-minutes: 12
|
|
16
16
|
steps:
|
|
17
17
|
- uses: actions/checkout@v4
|
|
18
|
-
- uses: actions/setup-python@
|
|
18
|
+
- uses: actions/setup-python@v6
|
|
19
19
|
with:
|
|
20
20
|
python-version: "3.10"
|
|
21
21
|
cache: "pip"
|
|
@@ -52,7 +52,7 @@ jobs:
|
|
|
52
52
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
53
53
|
aws-region: eu-central-1
|
|
54
54
|
- uses: actions/checkout@v4
|
|
55
|
-
- uses: actions/setup-python@
|
|
55
|
+
- uses: actions/setup-python@v6
|
|
56
56
|
with:
|
|
57
57
|
python-version: ${{ matrix.python-version }}
|
|
58
58
|
cache: "pip"
|
|
@@ -97,7 +97,7 @@ jobs:
|
|
|
97
97
|
timeout-minutes: 12
|
|
98
98
|
steps:
|
|
99
99
|
- uses: actions/checkout@v4
|
|
100
|
-
- uses: actions/setup-python@
|
|
100
|
+
- uses: actions/setup-python@v6
|
|
101
101
|
with:
|
|
102
102
|
python-version: "3.10"
|
|
103
103
|
cache: "pip"
|
|
@@ -139,7 +139,7 @@ jobs:
|
|
|
139
139
|
echo "AWS_ACCESS_KEY_ID_HOSTED_S3=${{ secrets.AWS_ACCESS_KEY_ID }}" >> .env.local
|
|
140
140
|
echo "AWS_SECRET_ACCESS_KEY_HOSTED_S3=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> .env.local
|
|
141
141
|
working-directory: laminhub/rest-hub/supabase
|
|
142
|
-
- uses: actions/setup-python@
|
|
142
|
+
- uses: actions/setup-python@v6
|
|
143
143
|
with:
|
|
144
144
|
python-version: "3.11" # we need to run everything for coverage on 3.11
|
|
145
145
|
cache: "pip"
|
|
@@ -168,7 +168,7 @@ jobs:
|
|
|
168
168
|
runs-on: ubuntu-latest
|
|
169
169
|
steps:
|
|
170
170
|
- uses: actions/checkout@v4
|
|
171
|
-
- uses: actions/setup-python@
|
|
171
|
+
- uses: actions/setup-python@v6
|
|
172
172
|
with:
|
|
173
173
|
python-version: "3.11"
|
|
174
174
|
cache: "pip"
|
|
@@ -205,7 +205,7 @@ jobs:
|
|
|
205
205
|
ssh-key: ${{ secrets.READ_LNDOCS }}
|
|
206
206
|
path: lndocs
|
|
207
207
|
ref: main
|
|
208
|
-
- uses: actions/setup-python@
|
|
208
|
+
- uses: actions/setup-python@v6
|
|
209
209
|
with:
|
|
210
210
|
python-version: "3.10"
|
|
211
211
|
cache: "pip"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/rbubley/mirrors-prettier
|
|
3
|
-
rev: v3.
|
|
3
|
+
rev: v3.6.2
|
|
4
4
|
hooks:
|
|
5
5
|
- id: prettier
|
|
6
6
|
exclude: |
|
|
@@ -17,13 +17,13 @@ repos:
|
|
|
17
17
|
docs/notes/
|
|
18
18
|
)
|
|
19
19
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
20
|
-
rev: v0.
|
|
20
|
+
rev: v0.14.0
|
|
21
21
|
hooks:
|
|
22
|
-
- id: ruff
|
|
22
|
+
- id: ruff-check
|
|
23
23
|
args: [--fix, --exit-non-zero-on-fix, --unsafe-fixes]
|
|
24
24
|
- id: ruff-format
|
|
25
25
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
26
|
-
rev:
|
|
26
|
+
rev: v6.0.0
|
|
27
27
|
hooks:
|
|
28
28
|
- id: detect-private-key
|
|
29
29
|
- id: check-ast
|
|
@@ -37,7 +37,7 @@ repos:
|
|
|
37
37
|
- id: trailing-whitespace
|
|
38
38
|
- id: check-case-conflict
|
|
39
39
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
40
|
-
rev: v1.
|
|
40
|
+
rev: v1.18.1
|
|
41
41
|
hooks:
|
|
42
42
|
- id: mypy
|
|
43
43
|
exclude: |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: lamindb_setup
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.0
|
|
4
4
|
Summary: Setup & configure LaminDB.
|
|
5
5
|
Author-email: Lamin Labs <open-source@lamin.ai>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -10,10 +10,11 @@ Requires-Dist: django>=5.1,<5.2
|
|
|
10
10
|
Requires-Dist: dj_database_url>=1.3.0,<3.0.0
|
|
11
11
|
Requires-Dist: pydantic-settings
|
|
12
12
|
Requires-Dist: platformdirs<5.0.0
|
|
13
|
+
Requires-Dist: httpx_retries<1.0.0
|
|
13
14
|
Requires-Dist: requests
|
|
14
15
|
Requires-Dist: universal_pathlib==0.2.6
|
|
15
16
|
Requires-Dist: botocore<2.0.0
|
|
16
|
-
Requires-Dist: supabase>=2.8.1,<=2.
|
|
17
|
+
Requires-Dist: supabase>=2.8.1,<=2.16.0
|
|
17
18
|
Requires-Dist: gotrue<=2.12.0
|
|
18
19
|
Requires-Dist: storage3!=0.11.2; python_version < '3.11'
|
|
19
20
|
Requires-Dist: pyjwt<3.0.0
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"metadata": {},
|
|
53
53
|
"outputs": [],
|
|
54
54
|
"source": [
|
|
55
|
+
"import os\n",
|
|
55
56
|
"import laminci\n",
|
|
56
57
|
"import pytest\n",
|
|
57
58
|
"from pathlib import Path\n",
|
|
@@ -305,6 +306,16 @@
|
|
|
305
306
|
"Cloud storage:"
|
|
306
307
|
]
|
|
307
308
|
},
|
|
309
|
+
{
|
|
310
|
+
"cell_type": "code",
|
|
311
|
+
"execution_count": null,
|
|
312
|
+
"id": "47affaad",
|
|
313
|
+
"metadata": {},
|
|
314
|
+
"outputs": [],
|
|
315
|
+
"source": [
|
|
316
|
+
"cloud_storage = f\"s3://lamindb-ci/storage3_{os.getenv('LAMIN_ENV', 'prod')}\""
|
|
317
|
+
]
|
|
318
|
+
},
|
|
308
319
|
{
|
|
309
320
|
"cell_type": "code",
|
|
310
321
|
"execution_count": null,
|
|
@@ -312,7 +323,7 @@
|
|
|
312
323
|
"metadata": {},
|
|
313
324
|
"outputs": [],
|
|
314
325
|
"source": [
|
|
315
|
-
"set_managed_storage(
|
|
326
|
+
"set_managed_storage(cloud_storage)"
|
|
316
327
|
]
|
|
317
328
|
},
|
|
318
329
|
{
|
|
@@ -327,7 +338,7 @@
|
|
|
327
338
|
"outputs": [],
|
|
328
339
|
"source": [
|
|
329
340
|
"assert ln_setup.settings.storage.type_is_cloud\n",
|
|
330
|
-
"assert ln_setup.settings.storage.root_as_str == \
|
|
341
|
+
"assert ln_setup.settings.storage.root_as_str == cloud_storage\n",
|
|
331
342
|
"assert ln_setup.settings.storage.region == \"us-west-1\"\n",
|
|
332
343
|
"assert (\n",
|
|
333
344
|
" ln_setup.settings.storage.root / \".lamindb/storage_uid.txt\"\n",
|
|
@@ -354,7 +365,7 @@
|
|
|
354
365
|
"metadata": {},
|
|
355
366
|
"outputs": [],
|
|
356
367
|
"source": [
|
|
357
|
-
"set_managed_storage(
|
|
368
|
+
"set_managed_storage(cloud_storage, cache_regions=False)"
|
|
358
369
|
]
|
|
359
370
|
},
|
|
360
371
|
{
|
|
@@ -395,71 +406,61 @@
|
|
|
395
406
|
"id": "83a2ee6b",
|
|
396
407
|
"metadata": {},
|
|
397
408
|
"source": [
|
|
398
|
-
"Add testuser2 as a collaborator to the instance:"
|
|
409
|
+
"Add testuser2 as a collaborator to the instance, sign them in and let them add another storage location:"
|
|
399
410
|
]
|
|
400
411
|
},
|
|
401
412
|
{
|
|
402
413
|
"cell_type": "code",
|
|
403
414
|
"execution_count": null,
|
|
404
|
-
"id": "
|
|
415
|
+
"id": "67e455af",
|
|
405
416
|
"metadata": {},
|
|
406
417
|
"outputs": [],
|
|
407
418
|
"source": [
|
|
408
|
-
"from laminhub_rest.core.legacy._instance_collaborator import InstanceCollaboratorHandler\n",
|
|
409
|
-
"from laminhub_rest.core.account import AccountHandler\n",
|
|
410
419
|
"from lamindb_setup.core._hub_client import connect_hub_with_auth\n",
|
|
411
|
-
"from
|
|
420
|
+
"from laminhub_rest.core._central_client import SupabaseClientWrapper\n",
|
|
421
|
+
"from laminhub_rest.core.instance_collaborator import InstanceCollaboratorHandler\n",
|
|
422
|
+
"from laminhub_rest.core.organization import OrganizationMemberHandler\n",
|
|
423
|
+
"\n",
|
|
424
|
+
"admin_hub = SupabaseClientWrapper(connect_hub_with_auth())\n",
|
|
425
|
+
"organization_member_handler = OrganizationMemberHandler(admin_hub)\n",
|
|
426
|
+
"\n",
|
|
427
|
+
"assert ln_setup.settings.user.handle == \"testuser1\"\n",
|
|
428
|
+
"organization_id = ln_setup.settings.user._uuid # testuser1\n",
|
|
412
429
|
"\n",
|
|
413
|
-
"admin_hub = connect_hub_with_auth()\n",
|
|
414
|
-
"testuser2 = AccountHandler(admin_hub).get_by_handle(\"testuser2\")\n",
|
|
415
|
-
"InstanceCollaboratorHandler(admin_hub).add(\n",
|
|
416
|
-
" instance_id=instance_id,\n",
|
|
417
|
-
" account_id=testuser2.id,\n",
|
|
418
|
-
" role=\"write\",\n",
|
|
419
|
-
" schema_id=None,\n",
|
|
420
|
-
" skip_insert_user_table=True,\n",
|
|
421
|
-
")\n",
|
|
422
|
-
"User.objects.create(uid=testuser2.lnid, handle=testuser2.handle, name=testuser2.name)\n",
|
|
423
|
-
"admin_hub.auth.close()"
|
|
424
|
-
]
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
"cell_type": "markdown",
|
|
428
|
-
"id": "e9d64cad",
|
|
429
|
-
"metadata": {},
|
|
430
|
-
"source": [
|
|
431
|
-
"Sign them in and let them add another storage location:"
|
|
432
|
-
]
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
"cell_type": "code",
|
|
436
|
-
"execution_count": null,
|
|
437
|
-
"id": "d6915638-db49-4d3d-bd91-819bb4719ef7",
|
|
438
|
-
"metadata": {},
|
|
439
|
-
"outputs": [],
|
|
440
|
-
"source": [
|
|
441
430
|
"ln_setup.login(\"testuser2\")\n",
|
|
442
|
-
"
|
|
443
|
-
"
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
"
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
"
|
|
462
|
-
"
|
|
431
|
+
"assert ln_setup.settings.user.handle == \"testuser2\"\n",
|
|
432
|
+
"account_id = ln_setup.settings.user._uuid\n",
|
|
433
|
+
"\n",
|
|
434
|
+
"try:\n",
|
|
435
|
+
" organization_member_handler.add(\n",
|
|
436
|
+
" organization_id=organization_id,\n",
|
|
437
|
+
" account_id=account_id,\n",
|
|
438
|
+
" role=\"member\",\n",
|
|
439
|
+
" )\n",
|
|
440
|
+
" try:\n",
|
|
441
|
+
" InstanceCollaboratorHandler(admin_hub).add(\n",
|
|
442
|
+
" account_id=account_id,\n",
|
|
443
|
+
" instance_id=instance_id,\n",
|
|
444
|
+
" role=\"write\",\n",
|
|
445
|
+
" )\n",
|
|
446
|
+
" except TypeError:\n",
|
|
447
|
+
" # the above failes in the mid due to no resource_db_server associated with the instance\n",
|
|
448
|
+
" # but still adds the collaborator\n",
|
|
449
|
+
" pass\n",
|
|
450
|
+
"\n",
|
|
451
|
+
" # although technically a user doesn't have to be a collaborator to insert into storage table\n",
|
|
452
|
+
" set_managed_storage(\"./storage4\", host=\"testuser2-laptop\")\n",
|
|
453
|
+
" assert ln_setup.settings.storage.root_as_str == f\"{Path.cwd()}/storage4\"\n",
|
|
454
|
+
" # attempt to delete the instance with testuser2\n",
|
|
455
|
+
" with pytest.raises(PermissionError) as error:\n",
|
|
456
|
+
" ln_setup.delete(\"testuser1/test-add-managed-storage\", force=True)\n",
|
|
457
|
+
"\n",
|
|
458
|
+
"finally:\n",
|
|
459
|
+
" organization_member_handler.remove(\n",
|
|
460
|
+
" organization_id=organization_id,\n",
|
|
461
|
+
" account_id=account_id,\n",
|
|
462
|
+
" )\n",
|
|
463
|
+
" admin_hub.auth.sign_out(options={\"scope\": \"local\"})"
|
|
463
464
|
]
|
|
464
465
|
},
|
|
465
466
|
{
|
|
@@ -510,7 +511,7 @@
|
|
|
510
511
|
],
|
|
511
512
|
"metadata": {
|
|
512
513
|
"kernelspec": {
|
|
513
|
-
"display_name": "
|
|
514
|
+
"display_name": "Python 3 (ipykernel)",
|
|
514
515
|
"language": "python",
|
|
515
516
|
"name": "python3"
|
|
516
517
|
},
|
|
@@ -524,7 +525,7 @@
|
|
|
524
525
|
"name": "python",
|
|
525
526
|
"nbconvert_exporter": "python",
|
|
526
527
|
"pygments_lexer": "ipython3",
|
|
527
|
-
"version": "3.
|
|
528
|
+
"version": "3.10.16"
|
|
528
529
|
}
|
|
529
530
|
},
|
|
530
531
|
"nbformat": 4,
|
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
]
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
|
-
"cell_type": "
|
|
11
|
+
"cell_type": "code",
|
|
12
|
+
"execution_count": null,
|
|
12
13
|
"metadata": {},
|
|
14
|
+
"outputs": [],
|
|
13
15
|
"source": [
|
|
14
|
-
"
|
|
16
|
+
"!lamin login testuser1\n",
|
|
17
|
+
"!lamin init --storage \"./testsetup-prepare\"\n",
|
|
18
|
+
"!lamin disconnect"
|
|
15
19
|
]
|
|
16
20
|
},
|
|
17
21
|
{
|
|
@@ -20,8 +24,16 @@
|
|
|
20
24
|
"metadata": {},
|
|
21
25
|
"outputs": [],
|
|
22
26
|
"source": [
|
|
23
|
-
"
|
|
24
|
-
"
|
|
27
|
+
"import lamindb_setup as ln_setup\n",
|
|
28
|
+
"import lamindb as ln\n",
|
|
29
|
+
"import pytest"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"cell_type": "markdown",
|
|
34
|
+
"metadata": {},
|
|
35
|
+
"source": [
|
|
36
|
+
"If you try to use lamindb, it will raise an `CurrentInstanceNotConfigured` and ask you to `init` or `connect` an instance via the python API."
|
|
25
37
|
]
|
|
26
38
|
},
|
|
27
39
|
{
|
|
@@ -30,8 +42,8 @@
|
|
|
30
42
|
"metadata": {},
|
|
31
43
|
"outputs": [],
|
|
32
44
|
"source": [
|
|
33
|
-
"
|
|
34
|
-
"
|
|
45
|
+
"with pytest.raises(ln.setup.errors.CurrentInstanceNotConfigured):\n",
|
|
46
|
+
" ln.track()"
|
|
35
47
|
]
|
|
36
48
|
},
|
|
37
49
|
{
|
|
@@ -98,6 +110,71 @@
|
|
|
98
110
|
" User.objects.get(handle=\"testuser2\")"
|
|
99
111
|
]
|
|
100
112
|
},
|
|
113
|
+
{
|
|
114
|
+
"cell_type": "code",
|
|
115
|
+
"execution_count": null,
|
|
116
|
+
"metadata": {},
|
|
117
|
+
"outputs": [],
|
|
118
|
+
"source": [
|
|
119
|
+
"ln.track()"
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"cell_type": "markdown",
|
|
124
|
+
"metadata": {},
|
|
125
|
+
"source": [
|
|
126
|
+
"Let us try connecting to another instance:"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"cell_type": "code",
|
|
131
|
+
"execution_count": null,
|
|
132
|
+
"metadata": {},
|
|
133
|
+
"outputs": [],
|
|
134
|
+
"source": [
|
|
135
|
+
"with pytest.raises(ln.setup.errors.CannotSwitchDefaultInstance) as error:\n",
|
|
136
|
+
" ln.connect(\"testsetup3\")\n",
|
|
137
|
+
"assert error.exconly().endswith(\n",
|
|
138
|
+
" \"Cannot switch default instance while `ln.track()` is live: call `ln.finish()`\"\n",
|
|
139
|
+
")"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"cell_type": "markdown",
|
|
144
|
+
"metadata": {},
|
|
145
|
+
"source": [
|
|
146
|
+
"Let us try to init another instance in the same Python session."
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"cell_type": "code",
|
|
151
|
+
"execution_count": null,
|
|
152
|
+
"metadata": {},
|
|
153
|
+
"outputs": [],
|
|
154
|
+
"source": [
|
|
155
|
+
"with pytest.raises(ln.setup.errors.CannotSwitchDefaultInstance) as error:\n",
|
|
156
|
+
" ln.setup.init(storage=\"./testsetup2\")\n",
|
|
157
|
+
"assert error.exconly().endswith(\n",
|
|
158
|
+
" \"Cannot switch default instance while `ln.track()` is live: call `ln.finish()`\"\n",
|
|
159
|
+
")"
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"cell_type": "markdown",
|
|
164
|
+
"metadata": {},
|
|
165
|
+
"source": [
|
|
166
|
+
"Switch off `ln.track()`."
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"cell_type": "code",
|
|
171
|
+
"execution_count": null,
|
|
172
|
+
"metadata": {},
|
|
173
|
+
"outputs": [],
|
|
174
|
+
"source": [
|
|
175
|
+
"ln.context._transform = None"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
101
178
|
{
|
|
102
179
|
"cell_type": "markdown",
|
|
103
180
|
"metadata": {},
|
|
@@ -104,6 +104,7 @@ def _connect_instance(
|
|
|
104
104
|
db: str | None = None,
|
|
105
105
|
raise_permission_error: bool = True,
|
|
106
106
|
use_root_db_user: bool = False,
|
|
107
|
+
use_proxy_db: bool = False,
|
|
107
108
|
access_token: str | None = None,
|
|
108
109
|
) -> InstanceSettings:
|
|
109
110
|
settings_file = instance_settings_file(name, owner)
|
|
@@ -118,8 +119,7 @@ def _connect_instance(
|
|
|
118
119
|
if db is not None and isettings.dialect == "postgresql":
|
|
119
120
|
isettings._db = db
|
|
120
121
|
if make_hub_request:
|
|
121
|
-
# the following will return a string if the instance does not exist
|
|
122
|
-
# on the hub
|
|
122
|
+
# the following will return a string if the instance does not exist on the hub
|
|
123
123
|
# do not call hub if the user is anonymous
|
|
124
124
|
if owner != "anonymous":
|
|
125
125
|
hub_result = connect_instance_hub(
|
|
@@ -127,6 +127,7 @@ def _connect_instance(
|
|
|
127
127
|
name=name,
|
|
128
128
|
access_token=access_token,
|
|
129
129
|
use_root_db_user=use_root_db_user,
|
|
130
|
+
use_proxy_db=use_proxy_db,
|
|
130
131
|
)
|
|
131
132
|
else:
|
|
132
133
|
hub_result = "anonymous-user"
|
|
@@ -192,11 +193,10 @@ def reset_django_module_variables():
|
|
|
192
193
|
# import lamindb as ln
|
|
193
194
|
# ln.connect(...)
|
|
194
195
|
#
|
|
195
|
-
# Then it will **not** work and the `ln` variable becomes stale and hold a reference
|
|
196
|
-
# to the old classes
|
|
196
|
+
# Then it will **not** work and the `ln` variable becomes stale and hold a reference to the old classes
|
|
197
197
|
# Other functions that dynamically import are no problem because the variables
|
|
198
198
|
# are automatically refreshed when the function runs the next time after ln.connect() was called
|
|
199
|
-
logger.
|
|
199
|
+
logger.debug("resetting django module variables")
|
|
200
200
|
|
|
201
201
|
# django.apps needs to be a local import to refresh variables
|
|
202
202
|
from django.apps import apps
|
|
@@ -242,11 +242,15 @@ def reset_django_module_variables():
|
|
|
242
242
|
continue
|
|
243
243
|
|
|
244
244
|
|
|
245
|
-
def _connect_cli(
|
|
245
|
+
def _connect_cli(
|
|
246
|
+
instance: str, use_root_db_user: bool = False, use_proxy_db: bool = False
|
|
247
|
+
) -> None:
|
|
246
248
|
from lamindb_setup import settings as settings_
|
|
247
249
|
|
|
248
250
|
owner, name = get_owner_name_from_identifier(instance)
|
|
249
|
-
isettings = _connect_instance(
|
|
251
|
+
isettings = _connect_instance(
|
|
252
|
+
owner, name, use_root_db_user=use_root_db_user, use_proxy_db=use_proxy_db
|
|
253
|
+
)
|
|
250
254
|
isettings._persist(write_to_disk=True)
|
|
251
255
|
if not isettings.is_on_hub or isettings._is_cloud_sqlite:
|
|
252
256
|
# there are two reasons to call the full-blown connect
|
|
@@ -259,6 +263,36 @@ def _connect_cli(instance: str, use_root_db_user: bool = False) -> None:
|
|
|
259
263
|
return None
|
|
260
264
|
|
|
261
265
|
|
|
266
|
+
def validate_connection_state(
|
|
267
|
+
owner: str, name: str, use_root_db_user: bool = False
|
|
268
|
+
) -> None:
|
|
269
|
+
from django.db import connection
|
|
270
|
+
|
|
271
|
+
if (
|
|
272
|
+
settings._instance_exists
|
|
273
|
+
and f"{owner}/{name}" == settings.instance.slug
|
|
274
|
+
# below is to ensure that if another process interferes
|
|
275
|
+
# we don't use the in-memory mock database
|
|
276
|
+
# could be made more specific by checking whether the django
|
|
277
|
+
# configured database is the same as the one in settings
|
|
278
|
+
and connection.settings_dict["NAME"] != ":memory:"
|
|
279
|
+
and not use_root_db_user # always re-connect for root db user
|
|
280
|
+
):
|
|
281
|
+
logger.important(
|
|
282
|
+
f"doing nothing, already connected lamindb: {settings.instance.slug}"
|
|
283
|
+
)
|
|
284
|
+
return None
|
|
285
|
+
else:
|
|
286
|
+
if settings._instance_exists and settings.instance.slug != "none/none":
|
|
287
|
+
import lamindb as ln
|
|
288
|
+
|
|
289
|
+
if ln.context.transform is not None:
|
|
290
|
+
raise CannotSwitchDefaultInstance(
|
|
291
|
+
"Cannot switch default instance while `ln.track()` is live: call `ln.finish()`"
|
|
292
|
+
)
|
|
293
|
+
reset_django()
|
|
294
|
+
|
|
295
|
+
|
|
262
296
|
@unlock_cloud_sqlite_upon_exception(ignore_prev_locker=True)
|
|
263
297
|
def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
264
298
|
"""Connect to an instance.
|
|
@@ -274,6 +308,7 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
274
308
|
# validate kwargs
|
|
275
309
|
valid_kwargs = {
|
|
276
310
|
"use_root_db_user",
|
|
311
|
+
"use_proxy_db",
|
|
277
312
|
"_db",
|
|
278
313
|
"_write_settings",
|
|
279
314
|
"_raise_not_found_error",
|
|
@@ -284,15 +319,18 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
284
319
|
for kwarg in kwargs:
|
|
285
320
|
if kwarg not in valid_kwargs:
|
|
286
321
|
raise TypeError(f"connect() got unexpected keyword argument '{kwarg}'")
|
|
287
|
-
|
|
288
|
-
# _db is still needed because it is called in init
|
|
322
|
+
|
|
289
323
|
use_root_db_user: bool = kwargs.get("use_root_db_user", False)
|
|
324
|
+
use_proxy_db = kwargs.get("use_proxy_db", False)
|
|
325
|
+
# _db is still needed because it is called in init
|
|
290
326
|
_db: str | None = kwargs.get("_db", None)
|
|
291
327
|
_write_settings: bool = kwargs.get("_write_settings", False)
|
|
292
328
|
_raise_not_found_error: bool = kwargs.get("_raise_not_found_error", True)
|
|
293
329
|
_reload_lamindb: bool = kwargs.get("_reload_lamindb", True)
|
|
294
330
|
_test: bool = kwargs.get("_test", False)
|
|
295
331
|
|
|
332
|
+
isettings: InstanceSettings = None # type: ignore
|
|
333
|
+
|
|
296
334
|
access_token: str | None = None
|
|
297
335
|
_user: UserSettings | None = kwargs.get("_user", None)
|
|
298
336
|
if _user is not None:
|
|
@@ -317,36 +355,11 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
317
355
|
if _db is not None and isettings.dialect == "postgresql":
|
|
318
356
|
isettings._db = _db
|
|
319
357
|
else:
|
|
320
|
-
from django.db import connection
|
|
321
|
-
|
|
322
358
|
owner, name = get_owner_name_from_identifier(instance)
|
|
323
359
|
if _check_instance_setup() and not _test:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
# below is to ensure that if another process interferes
|
|
328
|
-
# we don't use the in-memory mock database
|
|
329
|
-
# could be made more specific by checking whether the django
|
|
330
|
-
# configured database is the same as the one in settings
|
|
331
|
-
and connection.settings_dict["NAME"] != ":memory:"
|
|
332
|
-
and not use_root_db_user # always re-connect for root db user
|
|
333
|
-
):
|
|
334
|
-
logger.important(
|
|
335
|
-
f"doing nothing, already connected lamindb: {settings.instance.slug}"
|
|
336
|
-
)
|
|
337
|
-
return None
|
|
338
|
-
else:
|
|
339
|
-
if (
|
|
340
|
-
settings._instance_exists
|
|
341
|
-
and settings.instance.slug != "none/none"
|
|
342
|
-
):
|
|
343
|
-
import lamindb as ln
|
|
344
|
-
|
|
345
|
-
if ln.context.transform is not None:
|
|
346
|
-
raise CannotSwitchDefaultInstance(
|
|
347
|
-
"Cannot switch default instance while `ln.track()` is live: call `ln.finish()`"
|
|
348
|
-
)
|
|
349
|
-
reset_django()
|
|
360
|
+
validate_connection_state(
|
|
361
|
+
owner, name, use_root_db_user=use_root_db_user
|
|
362
|
+
)
|
|
350
363
|
elif (
|
|
351
364
|
_write_settings
|
|
352
365
|
and settings._instance_exists
|
|
@@ -362,6 +375,7 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
362
375
|
db=_db,
|
|
363
376
|
access_token=access_token,
|
|
364
377
|
use_root_db_user=use_root_db_user,
|
|
378
|
+
use_proxy_db=use_proxy_db,
|
|
365
379
|
)
|
|
366
380
|
except InstanceNotFoundError as e:
|
|
367
381
|
if _raise_not_found_error:
|
|
@@ -416,7 +430,7 @@ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
|
|
|
416
430
|
return None
|
|
417
431
|
|
|
418
432
|
|
|
419
|
-
def get_owner_name_from_identifier(identifier: str):
|
|
433
|
+
def get_owner_name_from_identifier(identifier: str) -> tuple[str, str]:
|
|
420
434
|
if "/" in identifier:
|
|
421
435
|
if identifier.startswith("https://lamin.ai/"):
|
|
422
436
|
identifier = identifier.replace("https://lamin.ai/", "")
|
|
@@ -21,6 +21,8 @@ if TYPE_CHECKING:
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def delete_cache(isettings: InstanceSettings):
|
|
24
|
+
if isettings.storage is None:
|
|
25
|
+
return
|
|
24
26
|
# avoid init of root
|
|
25
27
|
root = isettings.storage._root_init
|
|
26
28
|
if not isinstance(root, LocalPathClasses):
|
|
@@ -40,7 +42,7 @@ def delete_by_isettings(isettings: InstanceSettings) -> None:
|
|
|
40
42
|
if settings_file.exists():
|
|
41
43
|
settings_file.unlink()
|
|
42
44
|
delete_cache(isettings)
|
|
43
|
-
if isettings.dialect == "sqlite":
|
|
45
|
+
if isettings.dialect == "sqlite" and isettings.storage is not None:
|
|
44
46
|
try:
|
|
45
47
|
if isettings._sqlite_file.exists():
|
|
46
48
|
isettings._sqlite_file.unlink()
|