lamindb_setup 0.77.0__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.
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/.github/workflows/build.yml +13 -9
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/PKG-INFO +1 -1
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/__init__.py +5 -1
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_connect_instance.py +5 -1
- lamindb_setup-0.77.2/lamindb_setup/_entry_points.py +22 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_setup_user.py +10 -7
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_client.py +1 -1
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_core.py +68 -2
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_instance.py +6 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_save.py +1 -1
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_store.py +2 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/django.py +1 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_login.py +20 -5
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-local/test_all.py +45 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-local/test_update_schema_in_hub.py +2 -2
- lamindb_setup-0.77.2/tests/storage/test_entry_point.py +76 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/.gitignore +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/.pre-commit-config.yaml +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/LICENSE +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/README.md +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/changelog.md +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/08-test-multi-session.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/index.md +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/notebooks.md +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/reference.md +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_close.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_delete.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_init_instance.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_migrate.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_schema_metadata.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_aws_credentials.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_load.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_settings_user.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/lamindb_setup/core/upath.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/noxfile.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/pyproject.toml +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_connect_instance.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_init_instance.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_migrate.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-local/conftest.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-0.77.0 → 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:
|
|
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@
|
|
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@
|
|
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:
|
|
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@
|
|
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:
|
|
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@
|
|
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@
|
|
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@
|
|
213
|
+
- uses: actions/download-artifact@v4
|
|
210
214
|
- run: nox -s docs
|
|
211
215
|
- uses: nwtgck/actions-netlify@v1.2
|
|
212
216
|
with:
|
|
@@ -34,7 +34,7 @@ Modules & settings:
|
|
|
34
34
|
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
__version__ = "0.77.
|
|
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
|
|
@@ -45,6 +45,7 @@ from ._close import close
|
|
|
45
45
|
from ._connect_instance import connect, load
|
|
46
46
|
from ._delete import delete
|
|
47
47
|
from ._django import django
|
|
48
|
+
from ._entry_points import call_registered_entry_points as _call_registered_entry_points
|
|
48
49
|
from ._init_instance import init
|
|
49
50
|
from ._migrate import migrate
|
|
50
51
|
from ._register_instance import register
|
|
@@ -68,4 +69,7 @@ if _os.name == "nt":
|
|
|
68
69
|
|
|
69
70
|
threading.excepthook = _except_hook
|
|
70
71
|
|
|
72
|
+
# provide a way for other packages to run custom code on import
|
|
73
|
+
_call_registered_entry_points("lamindb_setup.on_import")
|
|
74
|
+
|
|
71
75
|
settings.__doc__ = """Global :class:`~lamindb.setup.core.SetupSettings`."""
|
|
@@ -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
|
-
|
|
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
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import warnings
|
|
3
|
+
from importlib.metadata import entry_points
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def call_registered_entry_points(group, **kwargs):
|
|
7
|
+
"""load and call entry points registered under group."""
|
|
8
|
+
if sys.version_info >= (3, 10):
|
|
9
|
+
eps = entry_points(group=group)
|
|
10
|
+
else:
|
|
11
|
+
eps = entry_points().get(group, [])
|
|
12
|
+
|
|
13
|
+
for ep in eps:
|
|
14
|
+
func = ep.load()
|
|
15
|
+
try:
|
|
16
|
+
func(**kwargs)
|
|
17
|
+
except BaseException as e:
|
|
18
|
+
warnings.warn(
|
|
19
|
+
f"Error loading entry point of group {group!r}: {ep} -> {e}",
|
|
20
|
+
RuntimeWarning,
|
|
21
|
+
stacklevel=2,
|
|
22
|
+
)
|
|
@@ -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
|
-
|
|
82
|
-
|
|
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
|
|
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]
|
|
@@ -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 =
|
|
34
|
-
"%Y-%m-%d"
|
|
35
|
-
)
|
|
34
|
+
expires_at = datetime.now(tz=timezone.utc) + timedelta(days=1)
|
|
36
35
|
api_key = create_api_key(
|
|
37
|
-
{
|
|
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": "
|
|
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": "
|
|
114
|
+
"link_table_name": "wetlab_artifactwell",
|
|
115
115
|
},
|
|
116
116
|
"field_name": "artifacts",
|
|
117
117
|
"model_name": "well",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import shlex
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
pyproject_toml = """\
|
|
8
|
+
[project]
|
|
9
|
+
name = "my_custom_module"
|
|
10
|
+
version = "0.0.1"
|
|
11
|
+
|
|
12
|
+
# pyproject.toml
|
|
13
|
+
[project.entry-points."lamindb_setup.on_import"]
|
|
14
|
+
my_custom_function = "my_custom_module:my_custom_function"
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
my_custom_module = """\
|
|
18
|
+
import os
|
|
19
|
+
|
|
20
|
+
def my_custom_function():
|
|
21
|
+
os.environ["MY_CUSTOM_ENV_VAR"] = "1"
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def installed_custom_module(tmp_path):
|
|
27
|
+
(tmp_path / "pyproject.toml").write_text(pyproject_toml)
|
|
28
|
+
(tmp_path / "my_custom_module.py").write_text(my_custom_module)
|
|
29
|
+
cmd_install = [sys.executable, "-m", "pip", "install", str(tmp_path)]
|
|
30
|
+
cmd_cleanup = [sys.executable, "-m", "pip", "uninstall", "my_custom_module", "-y"]
|
|
31
|
+
|
|
32
|
+
subprocess.run(shlex.join(cmd_install), shell=True, check=True)
|
|
33
|
+
try:
|
|
34
|
+
yield
|
|
35
|
+
finally:
|
|
36
|
+
subprocess.run(shlex.join(cmd_cleanup), shell=True, check=True)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.mark.parametrize(
|
|
40
|
+
"output,install_custom",
|
|
41
|
+
[
|
|
42
|
+
pytest.param(b"0", False, id="no-entry-point"),
|
|
43
|
+
pytest.param(b"1", True, id="with-entry-point"),
|
|
44
|
+
],
|
|
45
|
+
)
|
|
46
|
+
def test_on_import_entry_point(output, install_custom, request):
|
|
47
|
+
if install_custom:
|
|
48
|
+
request.getfixturevalue("installed_custom_module")
|
|
49
|
+
|
|
50
|
+
cmd = [
|
|
51
|
+
sys.executable,
|
|
52
|
+
"-c",
|
|
53
|
+
"import lamindb_setup; import os; print(os.environ.get('MY_CUSTOM_ENV_VAR', '0'), end='')",
|
|
54
|
+
]
|
|
55
|
+
out = subprocess.run(
|
|
56
|
+
shlex.join(cmd),
|
|
57
|
+
shell=True,
|
|
58
|
+
capture_output=True,
|
|
59
|
+
env={"PYTHONWARNINGS": "error"},
|
|
60
|
+
)
|
|
61
|
+
assert out.returncode == 0
|
|
62
|
+
assert out.stderr == b""
|
|
63
|
+
assert out.stdout == output
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_call_registered_entry_points(installed_custom_module):
|
|
67
|
+
from lamindb_setup._entry_points import call_registered_entry_points
|
|
68
|
+
|
|
69
|
+
call_registered_entry_points("lamindb_setup.on_import")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_broken_entry_points_does_not_crash(installed_custom_module):
|
|
73
|
+
from lamindb_setup._entry_points import call_registered_entry_points
|
|
74
|
+
|
|
75
|
+
with pytest.warns(RuntimeWarning, match="Error loading entry point"):
|
|
76
|
+
call_registered_entry_points("lamindb_setup.on_import", broken_kwarg=object())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/02-connect-local-instance.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-cloud/06-connect-hosted-instance.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-init-load-local-anonymously.ipynb
RENAMED
|
File without changes
|
{lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/docs/hub-prod/test-insufficient-user-info.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.77.0 → lamindb_setup-0.77.2}/tests/hub-prod/test_switch_and_fallback_env.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|