lamindb_setup 0.77.1__tar.gz → 0.77.2__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 (97) hide show
  1. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/.github/workflows/build.yml +13 -9
  2. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/PKG-INFO +1 -1
  3. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/__init__.py +1 -1
  4. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_connect_instance.py +5 -1
  5. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_setup_user.py +10 -7
  6. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_client.py +1 -1
  7. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_core.py +68 -2
  8. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_instance.py +6 -0
  9. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_save.py +1 -1
  10. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_store.py +2 -0
  11. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/django.py +1 -0
  12. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_login.py +20 -5
  13. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-local/test_all.py +45 -0
  14. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-local/test_update_schema_in_hub.py +2 -2
  15. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/.github/workflows/doc-changes.yml +0 -0
  16. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/.gitignore +0 -0
  17. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/.pre-commit-config.yaml +0 -0
  18. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/LICENSE +0 -0
  19. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/README.md +0 -0
  20. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/changelog.md +0 -0
  21. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
  22. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
  23. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
  24. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
  25. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
  26. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
  27. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
  28. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/08-test-multi-session.ipynb +0 -0
  29. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-cloud/test_notebooks.py +0 -0
  30. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-cache-management.ipynb +0 -0
  31. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
  32. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
  33. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-empty-init.ipynb +0 -0
  34. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-import-schema.ipynb +0 -0
  35. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
  36. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
  37. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
  38. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
  39. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/hub-prod/test_notebooks2.py +0 -0
  40. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/index.md +0 -0
  41. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/notebooks.md +0 -0
  42. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/docs/reference.md +0 -0
  43. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_cache.py +0 -0
  44. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_check.py +0 -0
  45. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_check_setup.py +0 -0
  46. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_close.py +0 -0
  47. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_delete.py +0 -0
  48. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_django.py +0 -0
  49. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_entry_points.py +0 -0
  50. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_exportdb.py +0 -0
  51. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_importdb.py +0 -0
  52. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_init_instance.py +0 -0
  53. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_migrate.py +0 -0
  54. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_register_instance.py +0 -0
  55. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_schema.py +0 -0
  56. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_schema_metadata.py +0 -0
  57. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_set_managed_storage.py +0 -0
  58. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/_silence_loggers.py +0 -0
  59. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/__init__.py +0 -0
  60. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_aws_credentials.py +0 -0
  61. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_aws_storage.py +0 -0
  62. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_deprecated.py +0 -0
  63. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_docs.py +0 -0
  64. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_crud.py +0 -0
  65. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_utils.py +0 -0
  66. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_private_django_api.py +0 -0
  67. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings.py +0 -0
  68. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_load.py +0 -0
  69. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_storage.py +0 -0
  70. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_user.py +0 -0
  71. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
  72. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
  73. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/exceptions.py +0 -0
  74. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/hashing.py +0 -0
  75. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/types.py +0 -0
  76. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/lamindb_setup/core/upath.py +0 -0
  77. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/noxfile.py +0 -0
  78. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/pyproject.toml +0 -0
  79. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
  80. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_connect_instance.py +0 -0
  81. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_delete_instance.py +0 -0
  82. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
  83. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_init_instance.py +0 -0
  84. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_migrate.py +0 -0
  85. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-cloud/test_set_storage.py +0 -0
  86. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-local/conftest.py +0 -0
  87. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-prod/conftest.py +0 -0
  88. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-prod/test_django.py +0 -0
  89. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-prod/test_global_settings.py +0 -0
  90. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
  91. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/hub-prod/test_upath.py +0 -0
  92. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_entry_point.py +0 -0
  93. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_hashing.py +0 -0
  94. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_storage_access.py +0 -0
  95. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_storage_basis.py +0 -0
  96. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_storage_stats.py +0 -0
  97. {lamindb_setup-0.77.1 → lamindb_setup-0.77.2}/tests/storage/test_to_url.py +0 -0
@@ -12,7 +12,7 @@ jobs:
12
12
  # tests only on production hub
13
13
  hub-prod:
14
14
  runs-on: ubuntu-latest
15
- timeout-minutes: 6
15
+ timeout-minutes: 7
16
16
  steps:
17
17
  - uses: actions/checkout@v3
18
18
  - uses: actions/setup-python@v4
@@ -27,10 +27,11 @@ jobs:
27
27
  - run: pip install "laminci@git+https://x-access-token:${{ secrets.LAMIN_BUILD_DOCS }}@github.com/laminlabs/laminci"
28
28
  - run: nox -s "install(group='hub-prod')"
29
29
  - run: nox -s "build(lamin_env='prod', group='hub-prod')"
30
- - uses: actions/upload-artifact@v2
30
+ - uses: actions/upload-artifact@v4
31
31
  with:
32
32
  name: coverage--hub-prod
33
33
  path: .coverage
34
+ include-hidden-files: true
34
35
 
35
36
  # tests both on production and staging hub
36
37
  hub-cloud:
@@ -83,16 +84,17 @@ jobs:
83
84
  # - uses: "google-github-actions/setup-gcloud@v0"
84
85
  - run: nox -s "install(group='hub-cloud')"
85
86
  - run: nox -s "build(lamin_env='${{ matrix.lamin_env }}', group='hub-cloud')"
86
- - uses: actions/upload-artifact@v2
87
+ - uses: actions/upload-artifact@v4
87
88
  if: ${{ matrix.lamin_env == 'prod' }}
88
89
  with:
89
90
  name: coverage--hub-cloud
90
91
  path: .coverage
92
+ include-hidden-files: true
91
93
 
92
94
  # test user access to storage
93
95
  storage:
94
96
  runs-on: ubuntu-latest
95
- timeout-minutes: 6
97
+ timeout-minutes: 7
96
98
  steps:
97
99
  - uses: actions/checkout@v4
98
100
  - uses: actions/setup-python@v4
@@ -108,15 +110,16 @@ jobs:
108
110
  TEST_INSTANCE_PRIVATE_POSTGRES: ${{ secrets.TEST_INSTANCE_PRIVATE_POSTGRES }}
109
111
  TMP_AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
110
112
  TMP_AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
111
- - uses: actions/upload-artifact@v2
113
+ - uses: actions/upload-artifact@v4
112
114
  with:
113
115
  name: coverage--storage
114
116
  path: .coverage
117
+ include-hidden-files: true
115
118
 
116
119
  # test low-level hub functionality
117
120
  hub-local:
118
121
  runs-on: ubuntu-latest
119
- timeout-minutes: 6
122
+ timeout-minutes: 7
120
123
  steps:
121
124
  - uses: aws-actions/configure-aws-credentials@v4
122
125
  with:
@@ -152,10 +155,11 @@ jobs:
152
155
  - run: nox -s hub_local
153
156
  env:
154
157
  LAMIN_ENV: "local"
155
- - uses: actions/upload-artifact@v2
158
+ - uses: actions/upload-artifact@v4
156
159
  with:
157
160
  name: coverage--hub-local
158
161
  path: .coverage
162
+ include-hidden-files: true
159
163
 
160
164
  coverage:
161
165
  needs: [hub-prod, hub-cloud, storage, hub-local]
@@ -169,7 +173,7 @@ jobs:
169
173
  - run: |
170
174
  pip install coverage[toml]
171
175
  pip install --no-deps .
172
- - uses: actions/download-artifact@v2
176
+ - uses: actions/download-artifact@v4
173
177
  - name: run coverage
174
178
  run: |
175
179
  coverage combine coverage--*/.coverage*
@@ -206,7 +210,7 @@ jobs:
206
210
  cache-dependency-path: ".github/workflows/build.yml"
207
211
  - run: pip install "laminci@git+https://x-access-token:${{ secrets.LAMIN_BUILD_DOCS }}@github.com/laminlabs/laminci"
208
212
  - run: nox -s "install(group='docs')"
209
- - uses: actions/download-artifact@v2
213
+ - uses: actions/download-artifact@v4
210
214
  - run: nox -s docs
211
215
  - uses: nwtgck/actions-netlify@v1.2
212
216
  with:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamindb_setup
3
- Version: 0.77.1
3
+ Version: 0.77.2
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -34,7 +34,7 @@ Modules & settings:
34
34
 
35
35
  """
36
36
 
37
- __version__ = "0.77.1" # denote a release candidate for 0.1.0 with 0.1rc1
37
+ __version__ = "0.77.2" # denote a release candidate for 0.1.0 with 0.1rc1
38
38
 
39
39
  import os as _os
40
40
  import sys as _sys
@@ -12,6 +12,7 @@ from ._init_instance import MESSAGE_NO_MULTIPLE_INSTANCE, load_from_isettings
12
12
  from ._migrate import check_whether_migrations_in_sync
13
13
  from ._silence_loggers import silence_loggers
14
14
  from .core._hub_core import connect_instance as load_instance_from_hub
15
+ from .core._hub_core import connect_instance_new as load_instance_from_hub_edge
15
16
  from .core._hub_utils import (
16
17
  LaminDsn,
17
18
  LaminDsnModel,
@@ -126,7 +127,10 @@ def _connect_instance(
126
127
  # on the hub
127
128
  # do not call hub if the user is anonymous
128
129
  if owner != "anonymous":
129
- hub_result = load_instance_from_hub(owner=owner, name=name)
130
+ if settings.user.handle in {"Koncopd", "sunnyosun", "falexwolf"}:
131
+ hub_result = load_instance_from_hub_edge(owner=owner, name=name)
132
+ else:
133
+ hub_result = load_instance_from_hub(owner=owner, name=name)
130
134
  else:
131
135
  hub_result = "anonymous-user"
132
136
  # if hub_result is not a string, it means it made a request
@@ -28,7 +28,7 @@ def load_user(email: str | None = None, handle: str | None = None) -> UserSettin
28
28
  if settings_file.exists():
29
29
  user_settings = load_user_settings(settings_file)
30
30
  save_user_settings(user_settings) # needed to save to current_user.env
31
- assert user_settings.email is not None
31
+ assert user_settings.email is not None or user_settings.api_key is not None
32
32
  else:
33
33
  user_settings = load_or_create_user_settings()
34
34
  if email is None:
@@ -74,13 +74,15 @@ def login(
74
74
  # within UserSettings, we still call it "password" for a while
75
75
  user_settings.password = key
76
76
 
77
- if user_settings.email is None:
78
- raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
79
-
80
77
  if user_settings.password is None:
81
- raise SystemExit(
82
- "✗ No stored API key, please call: lamin login <your-email> --key <API-key>"
83
- )
78
+ api_key = user_settings.api_key
79
+ if api_key is None:
80
+ raise SystemExit(
81
+ "✗ No stored API key, please call: "
82
+ "`lamin login` or `lamin login <your-email> --key <API-key>`"
83
+ )
84
+ elif user_settings.email is None:
85
+ raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
84
86
  else:
85
87
  user_settings = load_or_create_user_settings()
86
88
 
@@ -94,6 +96,7 @@ def login(
94
96
  )
95
97
  else:
96
98
  response = sign_in_hub_api_key(api_key)
99
+ user_settings.password = None
97
100
 
98
101
  if isinstance(response, Exception):
99
102
  raise response
@@ -131,7 +131,7 @@ def call_with_fallback_auth(
131
131
  try:
132
132
  if renew_token:
133
133
  logger.warning(
134
- "renewing expired lamin token: call `lamin login` to avoid this"
134
+ "renewing expired lamin token: call `lamin login <your-handle>` to avoid this"
135
135
  )
136
136
  client = connect_hub_with_auth(
137
137
  renew_token=renew_token, fallback_env=fallback_env
@@ -277,7 +277,6 @@ def _init_instance(isettings: InstanceSettings, client: Client) -> None:
277
277
  "id": isettings._id.hex,
278
278
  "account_id": settings.user._uuid.hex, # type: ignore
279
279
  "name": isettings.name,
280
- "storage_id": isettings.storage._uuid.hex, # type: ignore
281
280
  "lnid": isettings.uid,
282
281
  "schema_str": isettings._schema_str,
283
282
  "lamindb_version": lamindb_version,
@@ -340,7 +339,7 @@ def _connect_instance(
340
339
  # get default storage
341
340
  storage = select_default_storage_by_instance_id(instance["id"], client)
342
341
  if storage is None:
343
- return "storage-does-not-exist-on-hub"
342
+ return "default-storage-does-not-exist-on-hub"
344
343
  else:
345
344
  account = instance_account_storage.pop("account")
346
345
  storage = instance_account_storage.pop("storage")
@@ -367,6 +366,73 @@ def _connect_instance(
367
366
  return instance, storage # type: ignore
368
367
 
369
368
 
369
+ def _connect_instance_new(
370
+ owner: str, # account_handle
371
+ name: str, # instance_name
372
+ client: Client,
373
+ ) -> tuple[dict, dict] | str:
374
+ response = client.functions.invoke(
375
+ "get-instance-settings", invoke_options={"body": {"owner": owner, "name": name}}
376
+ )
377
+ # no instance found, check why is that
378
+ if response == b"{}":
379
+ # try the via single requests, will take more time
380
+ account = select_account_by_handle(owner, client)
381
+ if account is None:
382
+ return "account-not-exists"
383
+ instance = select_instance_by_name(account["id"], name, client)
384
+ if instance is None:
385
+ return "instance-not-found"
386
+ # get default storage
387
+ storage = select_default_storage_by_instance_id(instance["id"], client)
388
+ if storage is None:
389
+ return "default-storage-does-not-exist-on-hub"
390
+ logger.warning(
391
+ "Could not find instance via API, but found directly querying hub."
392
+ )
393
+ else:
394
+ instance = json.loads(response)
395
+ storage = instance.pop("storage")
396
+
397
+ if instance["db_scheme"] is not None:
398
+ db_user_name, db_user_password = None, None
399
+ if "db_user_name" in instance and "db_user_password" in instance:
400
+ db_user_name, db_user_password = (
401
+ instance["db_user_name"],
402
+ instance["db_user_password"],
403
+ )
404
+ else:
405
+ db_user = select_db_user_by_instance(instance["id"], client)
406
+ if db_user is not None:
407
+ db_user_name, db_user_password = (
408
+ db_user["db_user_name"],
409
+ db_user["db_user_password"],
410
+ )
411
+ db_dsn = LaminDsn.build(
412
+ scheme=instance["db_scheme"],
413
+ user=db_user_name if db_user_name is not None else "none",
414
+ password=db_user_password if db_user_password is not None else "none",
415
+ host=instance["db_host"],
416
+ port=instance["db_port"],
417
+ database=instance["db_database"],
418
+ )
419
+ instance["db"] = db_dsn
420
+ return instance, storage # type: ignore
421
+
422
+
423
+ def connect_instance_new(
424
+ *,
425
+ owner: str, # account_handle
426
+ name: str, # instance_name
427
+ ) -> tuple[dict, dict] | str:
428
+ from ._settings import settings
429
+
430
+ if settings.user.handle != "anonymous":
431
+ return call_with_fallback_auth(_connect_instance_new, owner=owner, name=name)
432
+ else:
433
+ return call_with_fallback(_connect_instance_new, owner=owner, name=name)
434
+
435
+
370
436
  def access_aws(storage_root: str, access_token: str | None = None) -> dict[str, dict]:
371
437
  from ._settings import settings
372
438
 
@@ -333,6 +333,12 @@ class InstanceSettings:
333
333
  @property
334
334
  def db(self) -> str:
335
335
  """Database connection string (URI)."""
336
+ if "LAMINDB_DJANGO_DATABASE_URL" in os.environ:
337
+ logger.warning(
338
+ "LAMINDB_DJANGO_DATABASE_URL env variable "
339
+ f"is set to {os.environ['LAMINDB_DJANGO_DATABASE_URL']}. "
340
+ "It overwrites all db connections and is used instead of `instance.db`."
341
+ )
336
342
  if self._db is None:
337
343
  # here, we want the updated sqlite file
338
344
  # hence, we don't use self._sqlite_file_local()
@@ -55,7 +55,7 @@ def save_settings(
55
55
  settings_key = f"_{store_key.rstrip('_')}"
56
56
  else:
57
57
  settings_key = store_key
58
- value = getattr(settings, settings_key)
58
+ value = getattr(settings, settings_key, None)
59
59
  if value is None:
60
60
  value = "null"
61
61
  elif isinstance(value, UUID):
@@ -49,12 +49,14 @@ def system_storage_settings_file():
49
49
 
50
50
 
51
51
  class InstanceSettingsStore(BaseSettings):
52
+ api_url: Optional[str] = None
52
53
  owner: str
53
54
  name: str
54
55
  storage_root: str
55
56
  storage_region: Optional[str] # take old type annotations here because pydantic
56
57
  db: Optional[str] # doesn't like new types on 3.9 even with future annotations
57
58
  schema_str: Optional[str]
59
+ schema_id: Optional[str] = None
58
60
  id: str
59
61
  git_repo: Optional[str]
60
62
  keep_artifacts_local: Optional[bool]
@@ -42,6 +42,7 @@ def setup_django(
42
42
  # configuration
43
43
  if not settings.configured:
44
44
  default_db = dj_database_url.config(
45
+ env="LAMINDB_DJANGO_DATABASE_URL",
45
46
  default=isettings.db,
46
47
  # see comment next to patching BaseDatabaseWrapper below
47
48
  conn_max_age=CONN_MAX_AGE,
@@ -29,12 +29,14 @@ def test_login():
29
29
 
30
30
  def test_login_api_key():
31
31
  ln_setup.login("testuser1")
32
+ save_password = ln_setup.settings.user.password
32
33
  # obtain API key
33
- expires_at = (datetime.now(tz=timezone.utc) + timedelta(days=1)).strftime(
34
- "%Y-%m-%d"
35
- )
34
+ expires_at = datetime.now(tz=timezone.utc) + timedelta(days=1)
36
35
  api_key = create_api_key(
37
- {"expires_at": expires_at, "description": "test_login_api_key"}
36
+ {
37
+ "expires_at": expires_at.strftime("%Y-%m-%d"),
38
+ "description": "test_login_api_key",
39
+ }
38
40
  )
39
41
 
40
42
  ln_setup.logout()
@@ -50,12 +52,22 @@ def test_login_api_key():
50
52
  ln_setup.login()
51
53
  assert ln_setup.settings.user.handle == "testuser1"
52
54
  assert ln_setup.settings.user.api_key == api_key
55
+ assert ln_setup.settings.user.password is None
53
56
 
54
57
  ln_setup.logout()
55
58
 
56
59
  ln_setup.login(api_key=api_key)
57
60
  assert ln_setup.settings.user.handle == "testuser1"
58
61
  assert ln_setup.settings.user.api_key == api_key
62
+ assert ln_setup.settings.user.password is None
63
+
64
+ ln_setup.logout()
65
+
66
+ # load from handle env
67
+ ln_setup.login("testuser1")
68
+ assert ln_setup.settings.user.handle == "testuser1"
69
+ assert ln_setup.settings.user.api_key == api_key
70
+ assert ln_setup.settings.user.password is None
59
71
 
60
72
  # clean up
61
73
  # here checks also refreshing access token with api_key
@@ -64,4 +76,7 @@ def test_login_api_key():
64
76
  hub.auth.sign_out({"scope": "local"})
65
77
 
66
78
  # login back with email to populate all fields
67
- ln_setup.login("testuser1@lamin.ai")
79
+ ln_setup.login("testuser1@lamin.ai", key=save_password)
80
+ assert ln_setup.settings.user.handle == "testuser1"
81
+ assert ln_setup.settings.user.api_key is None
82
+ assert ln_setup.settings.user.password == save_password
@@ -8,10 +8,13 @@ import pytest
8
8
  from gotrue.errors import AuthApiError
9
9
  from lamindb_setup.core._hub_client import (
10
10
  Environment,
11
+ connect_hub,
11
12
  connect_hub_with_auth,
12
13
  )
13
14
  from lamindb_setup.core._hub_core import (
15
+ _connect_instance_new,
14
16
  connect_instance,
17
+ connect_instance_new,
15
18
  init_instance,
16
19
  init_storage,
17
20
  sign_in_hub,
@@ -255,6 +258,48 @@ def test_db_user(
255
258
  assert db_user["name"] == "write"
256
259
 
257
260
 
261
+ def test_connect_instance_new(create_myinstance, create_testadmin1_session):
262
+ admin_client, _ = create_testadmin1_session
263
+
264
+ owner, name = ln_setup.settings.user.handle, create_myinstance["name"]
265
+ instance, storage = connect_instance_new(owner=owner, name=name)
266
+ assert instance["name"] == name
267
+ assert instance["owner"] == owner
268
+ assert instance["api_url"] is None
269
+ assert instance["db_permissions"] == "write"
270
+ assert storage["root"] == "s3://lamindb-ci/myinstance"
271
+ assert "schema_id" in instance
272
+
273
+ # add db_server from seed_local_test
274
+ admin_client.table("instance").update(
275
+ {"db_server_id": "e36c7069-2129-4c78-b2c6-323e2354b741"}
276
+ ).eq("id", instance["id"]).execute()
277
+
278
+ instance, _ = connect_instance_new(owner=owner, name=name)
279
+ assert instance["api_url"] == "http://localhost:8000"
280
+
281
+ # test anon access to public instance
282
+ update_instance(
283
+ instance_id=create_myinstance["id"],
284
+ instance_fields={"public": True},
285
+ client=admin_client,
286
+ )
287
+
288
+ anon_client = connect_hub()
289
+ instance, _ = _connect_instance_new(owner=owner, name=name, client=anon_client)
290
+
291
+ update_instance(
292
+ instance_id=create_myinstance["id"],
293
+ instance_fields={"public": False},
294
+ client=admin_client,
295
+ )
296
+ # test non-existent
297
+ result = connect_instance_new(owner="user-not-exists", name=name)
298
+ assert result == "account-not-exists"
299
+ result = connect_instance_new(owner=owner, name="instance-not-exists")
300
+ assert result == "instance-not-found"
301
+
302
+
258
303
  def test_connect_instance(create_myinstance, create_testadmin1_session):
259
304
  # trigger return for inexistent handle
260
305
  assert "account-not-exists" == connect_instance(
@@ -82,7 +82,7 @@ def test_update_schema_in_hub(setup_instance):
82
82
  "schema_name": "core",
83
83
  "is_link_table": False,
84
84
  "relation_type": "many-to-one",
85
- "related_field_name": "artifact",
85
+ "related_field_name": "created_artifacts",
86
86
  "related_model_name": "user",
87
87
  "related_schema_name": "core",
88
88
  }
@@ -111,7 +111,7 @@ def test_update_schema_in_hub(setup_instance):
111
111
  "through": {
112
112
  "left_key": "well_id",
113
113
  "right_key": "artifact_id",
114
- "link_table_name": "wetlab_well_artifacts",
114
+ "link_table_name": "wetlab_artifactwell",
115
115
  },
116
116
  "field_name": "artifacts",
117
117
  "model_name": "well",
File without changes
File without changes