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.
Files changed (107) hide show
  1. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.github/workflows/build.yml +6 -6
  2. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.gitignore +3 -0
  3. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.pre-commit-config.yaml +5 -5
  4. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/PKG-INFO +3 -2
  5. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/03-add-managed-storage.ipynb +60 -59
  6. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/08-test-multi-session.ipynb +83 -6
  7. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/__init__.py +1 -1
  8. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_connect_instance.py +52 -38
  9. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_delete.py +3 -1
  10. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_init_instance.py +22 -24
  11. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_migrate.py +8 -0
  12. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_schema_metadata.py +20 -16
  13. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_aws_options.py +2 -4
  14. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_aws_storage.py +2 -3
  15. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_client.py +84 -44
  16. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_core.py +35 -12
  17. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings.py +24 -5
  18. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_instance.py +7 -7
  19. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_save.py +2 -2
  20. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_store.py +9 -9
  21. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/django.py +4 -1
  22. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/upath.py +17 -10
  23. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/pyproject.toml +3 -2
  24. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +1 -1
  25. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +3 -2
  26. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_connect_instance.py +7 -1
  27. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_init_instance.py +6 -2
  28. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/conftest.py +0 -1
  29. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/test_all.py +5 -1
  30. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/.github/workflows/doc-changes.yml +0 -0
  31. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/LICENSE +0 -0
  32. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/README.md +0 -0
  33. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/changelog.md +0 -0
  34. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
  35. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
  36. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
  37. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
  38. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
  39. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
  40. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/09-test-migrate.ipynb +0 -0
  41. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-cloud/test_notebooks.py +0 -0
  42. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
  43. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
  44. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
  45. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-empty-init.ipynb +0 -0
  46. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
  47. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
  48. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
  49. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
  50. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
  51. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/hub-prod/test_notebooks2.py +0 -0
  52. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/index.md +0 -0
  53. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/notebooks.md +0 -0
  54. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/docs/reference.md +0 -0
  55. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_cache.py +0 -0
  56. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_check.py +0 -0
  57. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_check_setup.py +0 -0
  58. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_disconnect.py +0 -0
  59. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_django.py +0 -0
  60. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_entry_points.py +0 -0
  61. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_exportdb.py +0 -0
  62. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_importdb.py +0 -0
  63. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_register_instance.py +0 -0
  64. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_schema.py +0 -0
  65. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_set_managed_storage.py +0 -0
  66. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_setup_user.py +0 -0
  67. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/_silence_loggers.py +0 -0
  68. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/__init__.py +0 -0
  69. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_deprecated.py +0 -0
  70. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_docs.py +0 -0
  71. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_crud.py +0 -0
  72. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_hub_utils.py +0 -0
  73. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_private_django_api.py +0 -0
  74. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_load.py +0 -0
  75. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_storage.py +0 -0
  76. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_settings_user.py +0 -0
  77. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
  78. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
  79. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/exceptions.py +0 -0
  80. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/hashing.py +0 -0
  81. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/core/types.py +0 -0
  82. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/errors.py +0 -0
  83. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/py.typed +0 -0
  84. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/lamindb_setup/types.py +0 -0
  85. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/noxfile.py +0 -0
  86. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_delete_instance.py +0 -0
  87. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_edge_request.py +0 -0
  88. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
  89. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
  90. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_login.py +0 -0
  91. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-cloud/test_set_storage.py +0 -0
  92. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/scripts/script-connect-fine-grained-access.py +0 -0
  93. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-local/test_update_schema_in_hub.py +0 -0
  94. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/conftest.py +0 -0
  95. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_aws_options_manager.py +0 -0
  96. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_django.py +0 -0
  97. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_global_settings.py +0 -0
  98. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_migrate.py +0 -0
  99. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
  100. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/hub-prod/test_upath.py +0 -0
  101. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_entry_point.py +0 -0
  102. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_hashing.py +0 -0
  103. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_access.py +0 -0
  104. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_basis.py +0 -0
  105. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_settings.py +0 -0
  106. {lamindb_setup-1.10.2 → lamindb_setup-1.12.0}/tests/storage/test_storage_stats.py +0 -0
  107. {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@v5
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@v4
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@v5
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@v4
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@v4
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@v5
208
+ - uses: actions/setup-python@v6
209
209
  with:
210
210
  python-version: "3.10"
211
211
  cache: "pip"
@@ -69,6 +69,9 @@ instance/
69
69
  # Scrapy stuff:
70
70
  .scrapy
71
71
 
72
+ # Ruff
73
+ .ruff_cache
74
+
72
75
  # Sphinx documentation
73
76
  docs/_build/
74
77
 
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/rbubley/mirrors-prettier
3
- rev: v3.5.1
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.8.6
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: v4.5.0
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.7.1
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.10.2
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.15.0
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(\"s3://lamindb-ci/storage3\")"
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 == \"s3://lamindb-ci/storage3\"\n",
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(\"s3://lamindb-ci/storage3\", cache_regions=False)"
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": "9a4029b0",
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 lamindb.models import User\n",
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
- "set_managed_storage(\"./storage4\", host=\"testuser2-laptop\")\n",
443
- "assert ln_setup.settings.storage.root_as_str == f\"{Path.cwd()}/storage4\""
444
- ]
445
- },
446
- {
447
- "cell_type": "markdown",
448
- "id": "60ac7cb2",
449
- "metadata": {},
450
- "source": [
451
- "Attempt to delete instance with testuser2:"
452
- ]
453
- },
454
- {
455
- "cell_type": "code",
456
- "execution_count": null,
457
- "id": "6de90900",
458
- "metadata": {},
459
- "outputs": [],
460
- "source": [
461
- "with pytest.raises(PermissionError) as error:\n",
462
- " ln_setup.delete(\"testuser1/test-add-managed-storage\", force=True)"
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": "py312",
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.12.8"
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": "markdown",
11
+ "cell_type": "code",
12
+ "execution_count": null,
12
13
  "metadata": {},
14
+ "outputs": [],
13
15
  "source": [
14
- "This notebook is complemented by the `faq/setup.ipynb` notebook in lamindb."
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
- "!lamin login testuser1\n",
24
- "!lamin init --storage \"./testsetup-prepare\""
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
- "import lamindb_setup as ln_setup\n",
34
- "import pytest"
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": {},
@@ -35,7 +35,7 @@ Modules & settings:
35
35
 
36
36
  """
37
37
 
38
- __version__ = "1.10.2" # denote a release candidate for 0.1.0 with 0.1rc1
38
+ __version__ = "1.12.0" # denote a release candidate for 0.1.0 with 0.1rc1
39
39
 
40
40
  import os
41
41
 
@@ -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.important_hint("resetting django module variables")
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(instance: str, use_root_db_user: bool = False) -> None:
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(owner, name, use_root_db_user=use_root_db_user)
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
- isettings: InstanceSettings = None # type: ignore
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
- if (
325
- settings._instance_exists
326
- and f"{owner}/{name}" == settings.instance.slug
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()