lamindb_setup 1.11.0__tar.gz → 1.12.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.
Files changed (107) hide show
  1. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/.github/workflows/build.yml +6 -6
  2. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/.gitignore +3 -0
  3. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/.pre-commit-config.yaml +5 -5
  4. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/PKG-INFO +3 -2
  5. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/08-test-multi-session.ipynb +83 -6
  6. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/__init__.py +7 -1
  7. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_connect_instance.py +55 -41
  8. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_delete.py +3 -1
  9. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_init_instance.py +22 -25
  10. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_migrate.py +2 -2
  11. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_schema_metadata.py +3 -3
  12. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_aws_options.py +2 -4
  13. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_aws_storage.py +2 -3
  14. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_hub_client.py +84 -44
  15. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_hub_core.py +27 -10
  16. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings.py +2 -3
  17. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_instance.py +20 -7
  18. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_save.py +2 -2
  19. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_store.py +9 -9
  20. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/upath.py +7 -10
  21. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/pyproject.toml +3 -2
  22. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +4 -5
  23. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_connect_instance.py +13 -4
  24. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_init_instance.py +6 -2
  25. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-local/conftest.py +0 -1
  26. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-local/test_all.py +5 -1
  27. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/.github/workflows/doc-changes.yml +0 -0
  28. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/LICENSE +0 -0
  29. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/README.md +0 -0
  30. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/changelog.md +0 -0
  31. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
  32. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
  33. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
  34. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
  35. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
  36. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
  37. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
  38. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/09-test-migrate.ipynb +0 -0
  39. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-cloud/test_notebooks.py +0 -0
  40. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-cache-management.ipynb +0 -0
  41. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
  42. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
  43. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-empty-init.ipynb +0 -0
  44. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-import-schema.ipynb +0 -0
  45. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
  46. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
  47. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
  48. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
  49. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/hub-prod/test_notebooks2.py +0 -0
  50. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/index.md +0 -0
  51. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/notebooks.md +0 -0
  52. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/docs/reference.md +0 -0
  53. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_cache.py +0 -0
  54. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_check.py +0 -0
  55. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_check_setup.py +0 -0
  56. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_disconnect.py +0 -0
  57. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_django.py +0 -0
  58. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_entry_points.py +0 -0
  59. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_exportdb.py +0 -0
  60. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_importdb.py +0 -0
  61. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_register_instance.py +0 -0
  62. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_schema.py +0 -0
  63. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_set_managed_storage.py +0 -0
  64. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_setup_user.py +0 -0
  65. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/_silence_loggers.py +0 -0
  66. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/__init__.py +0 -0
  67. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_deprecated.py +0 -0
  68. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_docs.py +0 -0
  69. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_hub_crud.py +0 -0
  70. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_hub_utils.py +0 -0
  71. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_private_django_api.py +0 -0
  72. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_load.py +0 -0
  73. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_storage.py +0 -0
  74. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_settings_user.py +0 -0
  75. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
  76. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
  77. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/django.py +0 -0
  78. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/exceptions.py +0 -0
  79. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/hashing.py +0 -0
  80. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/core/types.py +0 -0
  81. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/errors.py +0 -0
  82. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/py.typed +0 -0
  83. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/lamindb_setup/types.py +0 -0
  84. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/noxfile.py +0 -0
  85. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +0 -0
  86. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_delete_instance.py +0 -0
  87. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_edge_request.py +0 -0
  88. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
  89. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
  90. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_login.py +0 -0
  91. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-cloud/test_set_storage.py +0 -0
  92. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-local/scripts/script-connect-fine-grained-access.py +0 -0
  93. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-local/test_update_schema_in_hub.py +0 -0
  94. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/conftest.py +0 -0
  95. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_aws_options_manager.py +0 -0
  96. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_django.py +0 -0
  97. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_global_settings.py +0 -0
  98. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_migrate.py +0 -0
  99. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
  100. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/hub-prod/test_upath.py +0 -0
  101. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_entry_point.py +0 -0
  102. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_hashing.py +0 -0
  103. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_storage_access.py +0 -0
  104. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_storage_basis.py +0 -0
  105. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_storage_settings.py +0 -0
  106. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/tests/storage/test_storage_stats.py +0 -0
  107. {lamindb_setup-1.11.0 → lamindb_setup-1.12.1}/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.11.0
3
+ Version: 1.12.1
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
@@ -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,9 +35,15 @@ Modules & settings:
35
35
 
36
36
  """
37
37
 
38
- __version__ = "1.11.0" # denote a release candidate for 0.1.0 with 0.1rc1
38
+ __version__ = "1.12.1" # denote a release candidate for 0.1.0 with 0.1rc1
39
39
 
40
40
  import os
41
+ import warnings
42
+
43
+ # ignore for now, remove this after supabase upgrade in the deps
44
+ warnings.filterwarnings("ignore", category=DeprecationWarning, module="supabase")
45
+ warnings.filterwarnings("ignore", category=DeprecationWarning, module="supafunc")
46
+ warnings.filterwarnings("ignore", category=DeprecationWarning, module="postgrest")
41
47
 
42
48
  from packaging import version as packaging_version
43
49
 
@@ -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"
@@ -161,10 +162,10 @@ def _connect_instance(
161
162
  schema_id=None
162
163
  if (schema_id := instance_result["schema_id"]) is None
163
164
  else UUID(schema_id),
164
- fine_grained_access=bool(
165
- instance_result["fine_grained_access"]
166
- ), # can be None
167
- db_permissions=instance_result.get("db_permissions", None),
165
+ fine_grained_access=bool(instance_result["fine_grained_access"]),
166
+ db_permissions=instance_result.get("db_permissions", None)
167
+ if not use_root_db_user
168
+ else "write",
168
169
  )
169
170
  else:
170
171
  if hub_result != "anonymous-user":
@@ -192,8 +193,7 @@ 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
199
  logger.debug("resetting django module variables")
@@ -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()
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import importlib
4
4
  import os
5
5
  import uuid
6
- from pathlib import Path
7
6
  from typing import TYPE_CHECKING, Literal
8
7
  from uuid import UUID
9
8
 
@@ -17,12 +16,13 @@ from ._silence_loggers import silence_loggers
17
16
  from .core import InstanceSettings
18
17
  from .core._docs import doc_args
19
18
  from .core._settings import settings
20
- from .core._settings_instance import check_is_instance_remote, is_local_db_url
19
+ from .core._settings_instance import check_is_instance_remote
21
20
  from .core._settings_storage import StorageSettings, init_storage
22
21
  from .core.upath import UPath
23
22
  from .errors import CannotSwitchDefaultInstance
24
23
 
25
24
  if TYPE_CHECKING:
25
+ from lamindb.models import Storage
26
26
  from pydantic import PostgresDsn
27
27
 
28
28
  from .core._settings_user import UserSettings
@@ -50,7 +50,7 @@ def get_schema_module_name(module_name, raise_import_error: bool = True) -> str
50
50
  return None
51
51
 
52
52
 
53
- def register_storage_in_instance(ssettings: StorageSettings):
53
+ def register_storage_in_instance(ssettings: StorageSettings) -> Storage:
54
54
  from lamindb.models import Storage
55
55
 
56
56
  # how do we ensure that this function is only called passing
@@ -70,7 +70,7 @@ def register_storage_in_instance(ssettings: StorageSettings):
70
70
  return storage
71
71
 
72
72
 
73
- def register_user(usettings: UserSettings, update_user: bool = True):
73
+ def register_user(usettings: UserSettings, update_user: bool = True) -> None:
74
74
  from lamindb.models import User
75
75
 
76
76
  if not update_user and User.objects.filter(uid=usettings.uid).exists():
@@ -92,7 +92,9 @@ def register_user(usettings: UserSettings, update_user: bool = True):
92
92
  pass
93
93
 
94
94
 
95
- def register_initial_records(isettings: InstanceSettings, usettings: UserSettings):
95
+ def register_initial_records(
96
+ isettings: InstanceSettings, usettings: UserSettings
97
+ ) -> None:
96
98
  """Register space, user & storage in DB."""
97
99
  from django.db.utils import OperationalError
98
100
  from lamindb.models import Branch, Space
@@ -246,6 +248,15 @@ def init(
246
248
  See Also:
247
249
  Init an instance for via the CLI, see `here <https://docs.lamin.ai/cli#init>`__.
248
250
  """
251
+ from ._check_setup import _check_instance_setup
252
+ from ._connect_instance import (
253
+ reset_django_module_variables,
254
+ validate_connection_state,
255
+ )
256
+ from .core._hub_core import init_instance_hub
257
+
258
+ silence_loggers()
259
+
249
260
  isettings = None
250
261
  ssettings = None
251
262
 
@@ -262,22 +273,6 @@ def init(
262
273
  access_token: str | None = None if _user is None else _user.access_token
263
274
 
264
275
  try:
265
- silence_loggers()
266
- from ._check_setup import _check_instance_setup
267
-
268
- if _check_instance_setup() and not _test:
269
- from lamindb_setup.core.django import reset_django
270
-
271
- if settings._instance_exists:
272
- raise CannotSwitchDefaultInstance(
273
- "Cannot init new instance after connecting to an existing instance."
274
- )
275
- reset_django()
276
- elif _write_settings:
277
- disconnect(mute=True)
278
- from ._connect_instance import reset_django_module_variables
279
- from .core._hub_core import init_instance_hub
280
-
281
276
  name_str, instance_id, instance_state, _ = validate_init_args(
282
277
  storage=storage,
283
278
  name=name,
@@ -289,6 +284,10 @@ def init(
289
284
  )
290
285
  if instance_state == "connected":
291
286
  return None
287
+ if _check_instance_setup() and not _test:
288
+ validate_connection_state(user_handle, name_str)
289
+ elif _write_settings:
290
+ disconnect(mute=True)
292
291
  isettings = InstanceSettings(
293
292
  id=instance_id, # type: ignore
294
293
  owner=user_handle,
@@ -379,10 +378,8 @@ def load_from_isettings(
379
378
  else:
380
379
  # when loading, django is already set up
381
380
  #
382
- # only register user if the instance is connected
383
- # for the first time in an environment
384
- # this is our best proxy for that the user might not
385
- # yet be registered
381
+ # only register user if the instance is connected for the first time in an environment
382
+ # this is our best proxy for that the user might not yet be registered
386
383
  if not isettings._get_settings_file().exists():
387
384
  # do not try to update the user on fine grained access instances
388
385
  # this is blocked anyways, only select and insert are allowed
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- import requests # type: ignore
3
+ import httpx
4
4
  from django.db import connection
5
5
  from django.db.migrations.loader import MigrationLoader
6
6
  from lamin_utils import logger
@@ -146,7 +146,7 @@ class migrate:
146
146
  logger.warning(
147
147
  "clearing instance cache in hub; if this fails, re-run with latest lamindb version"
148
148
  )
149
- requests.delete(
149
+ httpx.delete(
150
150
  f"{settings.instance.api_url}/cache/instances/{settings.instance._id.hex}",
151
151
  headers={"Authorization": f"Bearer {settings.user.access_token}"},
152
152
  )
@@ -71,9 +71,9 @@ def _synchronize_schema(client: Client) -> tuple[bool, UUID, dict]:
71
71
  .eq("id", settings.instance._id.hex)
72
72
  .execute()
73
73
  )
74
- assert (
75
- len(instance_response.data) == 1
76
- ), f"schema of instance {settings.instance._id.hex} could not be updated with schema {schema_uuid.hex}"
74
+ assert len(instance_response.data) == 1, (
75
+ f"schema of instance {settings.instance._id.hex} could not be updated with schema {schema_uuid.hex}"
76
+ )
77
77
 
78
78
  return is_new, schema_uuid, schema
79
79
 
@@ -29,8 +29,7 @@ def _keep_trailing_slash(path_str: str) -> str:
29
29
  AWS_CREDENTIALS_EXPIRATION: int = 11 * 60 * 60 # refresh credentials after 11 hours
30
30
 
31
31
 
32
- # set anon=True for these buckets if credentials fail for a public bucket
33
- # to be expanded
32
+ # set anon=True for these buckets if credentials fail for a public bucket to be expanded
34
33
  PUBLIC_BUCKETS: tuple[str, ...] = ("cellxgene-data-public", "bionty-assets")
35
34
 
36
35
 
@@ -155,8 +154,7 @@ class AWSOptionsManager:
155
154
  # this option is needed for correct uploads to R2
156
155
  path = UPath(path, fixed_upload_size=True)
157
156
  return path
158
- # trailing slash is needed to avoid returning incorrect results
159
- # with .startswith
157
+ # trailing slash is needed to avoid returning incorrect results with .startswith
160
158
  # for example s3://lamindata-eu should not receive cache for s3://lamindata
161
159
  path_str = _keep_trailing_slash(path.as_posix())
162
160
  root = self._find_root(path_str)
@@ -1,12 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import httpx
3
4
  from lamin_utils import logger
4
5
 
5
6
 
6
7
  def get_location(ip="ipinfo.io"):
7
- import requests # type: ignore
8
-
9
- response = requests.get(f"http://{ip}/json").json()
8
+ response = httpx.get(f"http://{ip}/json").json()
10
9
  loc = response["loc"].split(",")
11
10
  return {"latitude": float(loc[0]), "longitude": float(loc[1])}
12
11