lamindb_setup 1.4.1__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/PKG-INFO +3 -3
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-connect-anonymously-set-token.ipynb +11 -5
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/__init__.py +6 -3
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_cache.py +4 -4
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_check_setup.py +10 -1
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_connect_instance.py +7 -16
- lamindb_setup-1.4.1/lamindb_setup/_close.py → lamindb_setup-1.5.0/lamindb_setup/_disconnect.py +3 -3
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_init_instance.py +2 -2
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_setup_user.py +14 -18
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_aws_options.py +16 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_hub_core.py +22 -10
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings.py +5 -2
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_instance.py +1 -1
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_load.py +15 -4
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/django.py +93 -20
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/noxfile.py +7 -4
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/pyproject.toml +2 -2
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_connect_instance.py +2 -2
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-local/conftest.py +1 -0
- lamindb_setup-1.5.0/tests/hub-local/scripts/script-connect-fine-grained-access.py +41 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-local/test_all.py +13 -4
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_storage_access.py +1 -1
- lamindb_setup-1.4.1/tests/hub-local/scripts/script-connect-fine-grained-access.py +0 -19
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/.github/workflows/build.yml +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/.gitignore +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/.pre-commit-config.yaml +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/LICENSE +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/README.md +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/changelog.md +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/08-test-multi-session.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/index.md +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/notebooks.md +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/reference.md +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_delete.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_entry_points.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_migrate.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_schema_metadata.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_hub_client.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_hub_utils.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_save.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_store.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_settings_user.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/lamindb_setup/core/upath.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_edge_request.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_init_instance.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_migrate.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-local/test_update_schema_in_hub.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/test_aws_options_manager.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_entry_point.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_storage_settings.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/storage/test_to_url.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: lamindb_setup
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Setup & configure LaminDB.
|
|
5
5
|
Author-email: Lamin Labs <open-source@lamin.ai>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -21,7 +21,7 @@ Requires-Dist: psutil
|
|
|
21
21
|
Requires-Dist: packaging
|
|
22
22
|
Requires-Dist: urllib3<2 ; extra == "aws"
|
|
23
23
|
Requires-Dist: aiobotocore[boto3]>=2.5.4,<3.0.0 ; extra == "aws"
|
|
24
|
-
Requires-Dist: s3fs>=2023.12.2,<=2025.2
|
|
24
|
+
Requires-Dist: s3fs>=2023.12.2,<=2025.3.2,!=2024.10.0 ; extra == "aws"
|
|
25
25
|
Requires-Dist: line_profiler ; extra == "dev"
|
|
26
26
|
Requires-Dist: psycopg2-binary ; extra == "dev"
|
|
27
27
|
Requires-Dist: python-dotenv ; extra == "dev"
|
|
@@ -32,7 +32,7 @@ Requires-Dist: pytest-xdist ; extra == "dev"
|
|
|
32
32
|
Requires-Dist: nbproject-test>=0.4.3 ; extra == "dev"
|
|
33
33
|
Requires-Dist: pandas ; extra == "dev"
|
|
34
34
|
Requires-Dist: django-schema-graph ; extra == "erdiagram"
|
|
35
|
-
Requires-Dist: gcsfs>=2023.12.2,<=2025.2
|
|
35
|
+
Requires-Dist: gcsfs>=2023.12.2,<=2025.3.2 ; extra == "gcp"
|
|
36
36
|
Project-URL: Home, https://github.com/laminlabs/lamindb-setup
|
|
37
37
|
Provides-Extra: aws
|
|
38
38
|
Provides-Extra: dev
|
{lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-connect-anonymously-set-token.ipynb
RENAMED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"source": [
|
|
16
16
|
"import pytest\n",
|
|
17
17
|
"import lamindb_setup as ln_setup\n",
|
|
18
|
-
"from lamindb_setup.core.django import
|
|
19
|
-
"from
|
|
18
|
+
"from lamindb_setup.core.django import db_token_manager\n",
|
|
19
|
+
"from django.db.utils import ProgrammingError"
|
|
20
20
|
]
|
|
21
21
|
},
|
|
22
22
|
{
|
|
@@ -55,10 +55,16 @@
|
|
|
55
55
|
"source": [
|
|
56
56
|
"# this just tests that the function is setup properly\n",
|
|
57
57
|
"# the actual functionality is tested in lamindb\n",
|
|
58
|
-
"set_db_token(None)\n",
|
|
59
58
|
"# set_token sql function is not defined\n",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
59
|
+
"db_token_manager.debug = True\n",
|
|
60
|
+
"db_token_manager.set(\"test\")\n",
|
|
61
|
+
"\n",
|
|
62
|
+
"with pytest.raises(ProgrammingError):\n",
|
|
63
|
+
" ln_setup.settings.storage.record # makes a db query through django\n",
|
|
64
|
+
"\n",
|
|
65
|
+
"db_token_manager.reset() # turn off token\n",
|
|
66
|
+
"\n",
|
|
67
|
+
"ln_setup.settings.storage.record"
|
|
62
68
|
]
|
|
63
69
|
},
|
|
64
70
|
{
|
|
@@ -12,7 +12,7 @@ Basic operations:
|
|
|
12
12
|
login
|
|
13
13
|
logout
|
|
14
14
|
init
|
|
15
|
-
|
|
15
|
+
disconnect
|
|
16
16
|
delete
|
|
17
17
|
|
|
18
18
|
Instance operations:
|
|
@@ -33,7 +33,7 @@ Modules & settings:
|
|
|
33
33
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
__version__ = "1.
|
|
36
|
+
__version__ = "1.5.0" # denote a release candidate for 0.1.0 with 0.1rc1
|
|
37
37
|
|
|
38
38
|
import os
|
|
39
39
|
|
|
@@ -41,9 +41,9 @@ from packaging import version as packaging_version
|
|
|
41
41
|
|
|
42
42
|
from . import core
|
|
43
43
|
from ._check_setup import _check_instance_setup
|
|
44
|
-
from ._close import close
|
|
45
44
|
from ._connect_instance import connect, load
|
|
46
45
|
from ._delete import delete
|
|
46
|
+
from ._disconnect import disconnect
|
|
47
47
|
from ._django import django
|
|
48
48
|
from ._entry_points import call_registered_entry_points as _call_registered_entry_points
|
|
49
49
|
from ._init_instance import init
|
|
@@ -100,3 +100,6 @@ _TESTING = _is_CI_environment()
|
|
|
100
100
|
_call_registered_entry_points("lamindb_setup.on_import")
|
|
101
101
|
|
|
102
102
|
settings.__doc__ = """Global :class:`~lamindb.setup.core.SetupSettings`."""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
close = disconnect # backward compatibility
|
|
@@ -8,16 +8,16 @@ from .core._settings_save import save_system_storage_settings
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def clear_cache_dir():
|
|
11
|
-
from lamindb_setup import
|
|
11
|
+
from lamindb_setup import disconnect, settings
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
14
|
if settings.instance._is_cloud_sqlite:
|
|
15
15
|
logger.warning(
|
|
16
|
-
"
|
|
16
|
+
"Disconnecting the current instance to update the cloud sqlite database."
|
|
17
17
|
)
|
|
18
|
-
|
|
18
|
+
disconnect()
|
|
19
19
|
except SystemExit as e:
|
|
20
|
-
if str(e) != "No instance
|
|
20
|
+
if str(e) != "No instance connected! Call `lamin connect` or `lamin init`":
|
|
21
21
|
raise e
|
|
22
22
|
|
|
23
23
|
cache_dir = settings.cache_dir
|
|
@@ -163,5 +163,14 @@ def _check_instance_setup(from_module: str | None = None) -> bool:
|
|
|
163
163
|
return django_lamin.IS_SETUP
|
|
164
164
|
else:
|
|
165
165
|
if from_module is not None and settings.auto_connect:
|
|
166
|
-
|
|
166
|
+
# the below enables users to auto-connect to an instance
|
|
167
|
+
# simply by setting an environment variable, bypassing the
|
|
168
|
+
# need of calling connect() manually
|
|
169
|
+
if os.environ.get("LAMIN_CURRENT_INSTANCE") is not None:
|
|
170
|
+
from ._connect_instance import connect
|
|
171
|
+
|
|
172
|
+
connect(_write_settings=False, _reload_lamindb=False)
|
|
173
|
+
return django_lamin.IS_SETUP
|
|
174
|
+
else:
|
|
175
|
+
logger.warning(InstanceNotSetupError.default_message)
|
|
167
176
|
return False
|
|
@@ -8,7 +8,7 @@ from uuid import UUID
|
|
|
8
8
|
from lamin_utils import logger
|
|
9
9
|
|
|
10
10
|
from ._check_setup import _check_instance_setup, _get_current_instance_settings
|
|
11
|
-
from .
|
|
11
|
+
from ._disconnect import disconnect
|
|
12
12
|
from ._init_instance import (
|
|
13
13
|
MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
|
|
14
14
|
CannotSwitchDefaultInstance,
|
|
@@ -192,8 +192,8 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
|
|
|
192
192
|
"""Connect to an instance.
|
|
193
193
|
|
|
194
194
|
Args:
|
|
195
|
-
instance:
|
|
196
|
-
If `None`, it
|
|
195
|
+
instance: Pass a slug (`account/name`) or URL (`https://lamin.ai/account/name`).
|
|
196
|
+
If `None`, looks for an environment variable `LAMIN_CURRENT_INSTANCE` to get the instance identifier. If it doesn't find this variable, it connects to the instance that was connected with `lamin connect` through the CLI.
|
|
197
197
|
"""
|
|
198
198
|
# validate kwargs
|
|
199
199
|
valid_kwargs = {
|
|
@@ -219,12 +219,14 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
|
|
|
219
219
|
_user: UserSettings | None = kwargs.get("_user", None)
|
|
220
220
|
if _user is not None:
|
|
221
221
|
access_token = _user.access_token
|
|
222
|
+
if instance is None:
|
|
223
|
+
instance = os.environ.get("LAMIN_CURRENT_INSTANCE")
|
|
222
224
|
|
|
223
225
|
try:
|
|
224
226
|
if instance is None:
|
|
225
227
|
isettings_or_none = _get_current_instance_settings()
|
|
226
228
|
if isettings_or_none is None:
|
|
227
|
-
raise
|
|
229
|
+
raise ValueError(
|
|
228
230
|
"No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
|
|
229
231
|
)
|
|
230
232
|
isettings = isettings_or_none
|
|
@@ -246,7 +248,7 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
|
|
|
246
248
|
and settings._instance_exists
|
|
247
249
|
and f"{owner}/{name}" != settings.instance.slug
|
|
248
250
|
):
|
|
249
|
-
|
|
251
|
+
disconnect(mute=True)
|
|
250
252
|
|
|
251
253
|
try:
|
|
252
254
|
isettings = _connect_instance(
|
|
@@ -299,17 +301,6 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
|
|
|
299
301
|
if _TEST_FAILED_LOAD:
|
|
300
302
|
raise RuntimeError("Technical testing error.")
|
|
301
303
|
|
|
302
|
-
# below is for backfilling the instance_uid value
|
|
303
|
-
# we'll enable it once more people migrated to 0.71.0
|
|
304
|
-
# ssettings_record = isettings.storage.record
|
|
305
|
-
# if ssettings_record.instance_uid is None:
|
|
306
|
-
# ssettings_record.instance_uid = isettings.uid
|
|
307
|
-
# # try saving if not read-only access
|
|
308
|
-
# try:
|
|
309
|
-
# ssettings_record.save()
|
|
310
|
-
# # raised by django when the access is denied
|
|
311
|
-
# except ProgrammingError:
|
|
312
|
-
# pass
|
|
313
304
|
load_from_isettings(isettings, user=_user, write_settings=_write_settings)
|
|
314
305
|
if _reload_lamindb:
|
|
315
306
|
importlib.reload(importlib.import_module("lamindb"))
|
lamindb_setup-1.4.1/lamindb_setup/_close.py → lamindb_setup-1.5.0/lamindb_setup/_disconnect.py
RENAMED
|
@@ -7,8 +7,8 @@ from .core._settings_store import current_instance_settings_file
|
|
|
7
7
|
from .core.cloud_sqlite_locker import clear_locker
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
"""
|
|
10
|
+
def disconnect(mute: bool = False) -> None:
|
|
11
|
+
"""Disconnect an instance.
|
|
12
12
|
|
|
13
13
|
Returns `None` if succeeds, otherwise an exception is raised.
|
|
14
14
|
"""
|
|
@@ -26,7 +26,7 @@ def close(mute: bool = False) -> None:
|
|
|
26
26
|
current_instance_settings_file().unlink()
|
|
27
27
|
clear_locker()
|
|
28
28
|
if not mute:
|
|
29
|
-
logger.success(f"
|
|
29
|
+
logger.success(f"disconnected instance: {instance}")
|
|
30
30
|
else:
|
|
31
31
|
if not mute:
|
|
32
32
|
logger.info("no instance loaded")
|
|
@@ -11,7 +11,7 @@ from django.core.exceptions import FieldError
|
|
|
11
11
|
from django.db.utils import OperationalError, ProgrammingError
|
|
12
12
|
from lamin_utils import logger
|
|
13
13
|
|
|
14
|
-
from .
|
|
14
|
+
from ._disconnect import disconnect
|
|
15
15
|
from ._silence_loggers import silence_loggers
|
|
16
16
|
from .core import InstanceSettings
|
|
17
17
|
from .core._docs import doc_args
|
|
@@ -262,7 +262,7 @@ def init(
|
|
|
262
262
|
if _check_instance_setup() and not _test:
|
|
263
263
|
raise CannotSwitchDefaultInstance(MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE)
|
|
264
264
|
elif _write_settings:
|
|
265
|
-
|
|
265
|
+
disconnect(mute=True)
|
|
266
266
|
from .core._hub_core import init_instance_hub
|
|
267
267
|
|
|
268
268
|
name_str, instance_id, instance_state, _ = validate_init_args(
|
|
@@ -8,16 +8,14 @@ from lamin_utils import logger
|
|
|
8
8
|
from ._check_setup import _check_instance_setup
|
|
9
9
|
from ._init_instance import register_user
|
|
10
10
|
from .core._settings import settings
|
|
11
|
-
from .core._settings_load import
|
|
11
|
+
from .core._settings_load import load_user_settings
|
|
12
12
|
from .core._settings_save import save_user_settings
|
|
13
13
|
from .core._settings_store import (
|
|
14
14
|
current_user_settings_file,
|
|
15
15
|
user_settings_file_email,
|
|
16
16
|
user_settings_file_handle,
|
|
17
17
|
)
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from lamindb_setup.core._settings_save import UserSettings
|
|
18
|
+
from .core._settings_user import UserSettings
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
def load_user(email: str | None = None, handle: str | None = None) -> UserSettings:
|
|
@@ -30,15 +28,12 @@ def load_user(email: str | None = None, handle: str | None = None) -> UserSettin
|
|
|
30
28
|
save_user_settings(user_settings) # needed to save to current_user.env
|
|
31
29
|
assert user_settings.email is not None or user_settings.api_key is not None
|
|
32
30
|
else:
|
|
33
|
-
user_settings = load_or_create_user_settings()
|
|
34
31
|
if email is None:
|
|
35
32
|
raise SystemExit(
|
|
36
33
|
"✗ Use your email for your first login in a compute environment. "
|
|
37
34
|
"After that, you can use your handle."
|
|
38
35
|
)
|
|
39
|
-
user_settings
|
|
40
|
-
user_settings.handle = handle
|
|
41
|
-
save_user_settings(user_settings)
|
|
36
|
+
user_settings = UserSettings(handle=handle, email=email, uid="null") # type: ignore
|
|
42
37
|
|
|
43
38
|
from .core._settings import settings
|
|
44
39
|
|
|
@@ -49,7 +44,7 @@ def load_user(email: str | None = None, handle: str | None = None) -> UserSettin
|
|
|
49
44
|
|
|
50
45
|
def login(
|
|
51
46
|
user: str | None = None, *, api_key: str | None = None, key: str | None = None
|
|
52
|
-
) ->
|
|
47
|
+
) -> UserSettings:
|
|
53
48
|
"""Log in user.
|
|
54
49
|
|
|
55
50
|
Args:
|
|
@@ -84,7 +79,7 @@ def login(
|
|
|
84
79
|
elif user_settings.email is None:
|
|
85
80
|
raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
|
|
86
81
|
else:
|
|
87
|
-
user_settings =
|
|
82
|
+
user_settings = UserSettings(handle="temporary", uid="null")
|
|
88
83
|
|
|
89
84
|
from .core._hub_core import sign_in_hub, sign_in_hub_api_key
|
|
90
85
|
|
|
@@ -104,14 +99,12 @@ def login(
|
|
|
104
99
|
raise SystemExit(f"✗ Unsuccessful login: {response}.")
|
|
105
100
|
else:
|
|
106
101
|
user_uuid, user_id, user_handle, user_name, access_token = response
|
|
102
|
+
|
|
107
103
|
if api_key is not None:
|
|
108
|
-
logger.success(
|
|
109
|
-
|
|
110
|
-
)
|
|
111
|
-
elif handle is None:
|
|
112
|
-
logger.success(f"logged in with handle {user_handle} (uid: {user_id})")
|
|
113
|
-
else:
|
|
104
|
+
logger.success(f"logged in {user_handle} (uid: {user_id})")
|
|
105
|
+
else: # legacy flow
|
|
114
106
|
logger.success(f"logged in with email {user_settings.email} (uid: {user_id})")
|
|
107
|
+
|
|
115
108
|
user_settings.uid = user_id
|
|
116
109
|
user_settings.handle = user_handle
|
|
117
110
|
user_settings.name = user_name
|
|
@@ -124,14 +117,17 @@ def login(
|
|
|
124
117
|
register_user(user_settings)
|
|
125
118
|
|
|
126
119
|
settings._user_settings = None
|
|
127
|
-
return
|
|
120
|
+
return user_settings
|
|
128
121
|
|
|
129
122
|
|
|
130
123
|
def logout():
|
|
131
124
|
if current_user_settings_file().exists():
|
|
132
125
|
current_user_settings_file().unlink()
|
|
133
|
-
# update user info
|
|
134
126
|
settings._user_settings = None
|
|
135
127
|
logger.success("logged out")
|
|
136
128
|
else:
|
|
137
129
|
logger.important("already logged out")
|
|
130
|
+
if os.environ.get("LAMIN_API_KEY") is not None:
|
|
131
|
+
logger.warning(
|
|
132
|
+
"LAMIN_API_KEY is still set in your environment and will automatically log you in"
|
|
133
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
import time
|
|
5
6
|
|
|
@@ -38,7 +39,19 @@ PUBLIC_BUCKETS: tuple[str] = ("cellxgene-data-public",)
|
|
|
38
39
|
LAMIN_ENDPOINTS: tuple[str | None] = (None,)
|
|
39
40
|
|
|
40
41
|
|
|
42
|
+
class NoTracebackFilter(logging.Filter):
|
|
43
|
+
def filter(self, record):
|
|
44
|
+
record.exc_info = None # Remove traceback info from the log record.
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
41
48
|
class AWSOptionsManager:
|
|
49
|
+
# suppress giant traceback logs from aiobotocore when failing to refresh sso etc
|
|
50
|
+
@staticmethod
|
|
51
|
+
def _suppress_aiobotocore_traceback_logging():
|
|
52
|
+
logger = logging.getLogger("aiobotocore.credentials")
|
|
53
|
+
logger.addFilter(NoTracebackFilter())
|
|
54
|
+
|
|
42
55
|
def __init__(self):
|
|
43
56
|
self._credentials_cache = {}
|
|
44
57
|
|
|
@@ -48,6 +61,9 @@ class AWSOptionsManager:
|
|
|
48
61
|
fs = S3FileSystem(
|
|
49
62
|
cache_regions=True, use_listings_cache=True, version_aware=False
|
|
50
63
|
)
|
|
64
|
+
|
|
65
|
+
self._suppress_aiobotocore_traceback_logging()
|
|
66
|
+
|
|
51
67
|
try:
|
|
52
68
|
fs.connect()
|
|
53
69
|
self.anon: bool = fs.session._credentials is None
|
|
@@ -34,13 +34,12 @@ from ._hub_utils import (
|
|
|
34
34
|
LaminDsnModel,
|
|
35
35
|
)
|
|
36
36
|
from ._settings import settings
|
|
37
|
+
from ._settings_instance import InstanceSettings
|
|
37
38
|
from ._settings_storage import StorageSettings, base62
|
|
38
39
|
|
|
39
40
|
if TYPE_CHECKING:
|
|
40
41
|
from supabase import Client # type: ignore
|
|
41
42
|
|
|
42
|
-
from ._settings_instance import InstanceSettings
|
|
43
|
-
|
|
44
43
|
|
|
45
44
|
def delete_storage_record(storage_uuid: UUID, access_token: str | None = None) -> None:
|
|
46
45
|
return call_with_fallback_auth(
|
|
@@ -439,11 +438,25 @@ def _access_aws(*, storage_root: str, client: Client) -> dict[str, dict]:
|
|
|
439
438
|
return storage_root_info
|
|
440
439
|
|
|
441
440
|
|
|
442
|
-
def access_db(
|
|
441
|
+
def access_db(
|
|
442
|
+
instance: InstanceSettings | dict, access_token: str | None = None
|
|
443
|
+
) -> str:
|
|
444
|
+
instance_id: UUID
|
|
445
|
+
instance_slug: str
|
|
446
|
+
instance_api_url: str | None
|
|
447
|
+
if isinstance(instance, InstanceSettings):
|
|
448
|
+
instance_id = instance._id
|
|
449
|
+
instance_slug = instance.slug
|
|
450
|
+
instance_api_url = instance._api_url
|
|
451
|
+
else:
|
|
452
|
+
instance_id = UUID(instance["id"])
|
|
453
|
+
instance_slug = instance["owner"] + "/" + instance["name"]
|
|
454
|
+
instance_api_url = instance["api_url"]
|
|
455
|
+
|
|
443
456
|
if access_token is None:
|
|
444
457
|
if settings.user.handle == "anonymous":
|
|
445
458
|
raise RuntimeError(
|
|
446
|
-
f"Can only get fine-grained access to {
|
|
459
|
+
f"Can only get fine-grained access to {instance_slug} if authenticated."
|
|
447
460
|
)
|
|
448
461
|
else:
|
|
449
462
|
access_token = settings.user.access_token
|
|
@@ -451,20 +464,19 @@ def access_db(isettings: InstanceSettings, access_token: str | None = None) -> s
|
|
|
451
464
|
else:
|
|
452
465
|
renew_token = False
|
|
453
466
|
# local is used in tests
|
|
454
|
-
url = f"/access_v2/instances/{
|
|
467
|
+
url = f"/access_v2/instances/{instance_id}/db_token"
|
|
455
468
|
if os.environ.get("LAMIN_ENV", "prod") != "local":
|
|
456
|
-
|
|
457
|
-
if api_url is None:
|
|
469
|
+
if instance_api_url is None:
|
|
458
470
|
raise RuntimeError(
|
|
459
|
-
f"Can only get fine-grained access to {
|
|
471
|
+
f"Can only get fine-grained access to {instance_slug} if api_url is present."
|
|
460
472
|
)
|
|
461
|
-
url =
|
|
473
|
+
url = instance_api_url + url
|
|
462
474
|
|
|
463
475
|
response = request_get_auth(url, access_token, renew_token) # type: ignore
|
|
464
476
|
response_json = response.json()
|
|
465
477
|
if response.status_code != 200:
|
|
466
478
|
raise PermissionError(
|
|
467
|
-
f"Fine-grained access to {
|
|
479
|
+
f"Fine-grained access to {instance_slug} failed: {response_json}"
|
|
468
480
|
)
|
|
469
481
|
if "token" not in response_json:
|
|
470
482
|
raise RuntimeError("The response of access_db does not contain a db token.")
|
|
@@ -114,10 +114,13 @@ class SetupSettings:
|
|
|
114
114
|
and self._user_settings_env != get_env_name()
|
|
115
115
|
)
|
|
116
116
|
if self._user_settings is None or env_changed:
|
|
117
|
-
|
|
117
|
+
# only uses LAMIN_API_KEY if there is no current_user.env
|
|
118
|
+
self._user_settings = load_or_create_user_settings(
|
|
119
|
+
api_key=os.environ.get("LAMIN_API_KEY")
|
|
120
|
+
)
|
|
118
121
|
self._user_settings_env = get_env_name()
|
|
119
122
|
if self._user_settings and self._user_settings.uid is None:
|
|
120
|
-
raise RuntimeError("Need to login, first: lamin login
|
|
123
|
+
raise RuntimeError("Need to login, first: lamin login")
|
|
121
124
|
return self._user_settings # type: ignore
|
|
122
125
|
|
|
123
126
|
@property
|
|
@@ -286,7 +286,7 @@ class InstanceSettings:
|
|
|
286
286
|
The core schema contained in lamindb is not included in this set.
|
|
287
287
|
"""
|
|
288
288
|
if self._schema_str is None:
|
|
289
|
-
return
|
|
289
|
+
return set()
|
|
290
290
|
else:
|
|
291
291
|
return {module for module in self._schema_str.split(",") if module != ""}
|
|
292
292
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
from uuid import UUID, uuid4
|
|
5
6
|
|
|
@@ -40,7 +41,7 @@ def load_instance_settings(instance_settings_file: Path | None = None):
|
|
|
40
41
|
if instance_settings_file is None:
|
|
41
42
|
instance_settings_file = current_instance_settings_file()
|
|
42
43
|
if not instance_settings_file.exists():
|
|
43
|
-
raise SystemExit("No instance
|
|
44
|
+
raise SystemExit("No instance connected! Call `lamin connect` or `lamin init`")
|
|
44
45
|
try:
|
|
45
46
|
settings_store = InstanceSettingsStore(_env_file=instance_settings_file)
|
|
46
47
|
except (ValidationError, TypeError) as error:
|
|
@@ -55,11 +56,21 @@ def load_instance_settings(instance_settings_file: Path | None = None):
|
|
|
55
56
|
return isettings
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
def load_or_create_user_settings() -> UserSettings:
|
|
59
|
-
"""Return current user settings.
|
|
59
|
+
def load_or_create_user_settings(api_key: str | None = None) -> UserSettings:
|
|
60
|
+
"""Return current user settings.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
api_key: if provided and there is no current user,
|
|
64
|
+
perform login and return the user settings.
|
|
65
|
+
"""
|
|
60
66
|
current_user_settings = current_user_settings_file()
|
|
61
67
|
if not current_user_settings.exists():
|
|
62
|
-
|
|
68
|
+
if api_key is not None:
|
|
69
|
+
from lamindb_setup._setup_user import login
|
|
70
|
+
|
|
71
|
+
return login(api_key=api_key)
|
|
72
|
+
else:
|
|
73
|
+
logger.warning("using anonymous user (to identify, call: lamin login)")
|
|
63
74
|
usettings = UserSettings(handle="anonymous", uid="00000000")
|
|
64
75
|
from ._settings_save import save_user_settings
|
|
65
76
|
|
|
@@ -14,29 +14,101 @@ IS_MIGRATING = False
|
|
|
14
14
|
CONN_MAX_AGE = 299
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
# a class to manage jwt in dbs
|
|
18
|
+
class DBTokenManager:
|
|
19
|
+
def __init__(self, debug: bool = False):
|
|
20
|
+
from django.db.transaction import Atomic
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
self.debug = debug
|
|
23
|
+
self.original_atomic_enter = Atomic.__enter__
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
self.tokens: dict[str, str] = {}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# now the connection should be set
|
|
30
|
-
# Use a psycopg cursor directly, bypassing Django's utilities.
|
|
31
|
-
with self.connection.cursor() as cursor:
|
|
32
|
-
cursor.execute("SELECT set_token(%s, false);", (token,))
|
|
33
|
-
else:
|
|
34
|
-
connect = BaseDatabaseWrapper.connect
|
|
27
|
+
def get_connection(self, connection_name: str):
|
|
28
|
+
from django.db import connections
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
connection = connections[connection_name]
|
|
31
|
+
assert connection.vendor == "postgresql"
|
|
32
|
+
|
|
33
|
+
return connection
|
|
34
|
+
|
|
35
|
+
def set(self, token: str, connection_name: str = "default"):
|
|
36
|
+
from django.db.transaction import Atomic
|
|
37
|
+
|
|
38
|
+
# no adapt in psycopg3
|
|
39
|
+
from psycopg2.extensions import adapt
|
|
40
|
+
|
|
41
|
+
connection = self.get_connection(connection_name)
|
|
42
|
+
|
|
43
|
+
# escape correctly to avoid wrangling with params
|
|
44
|
+
set_token_query = (
|
|
45
|
+
f"SELECT set_token({adapt(token).getquoted().decode()}, true); "
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def set_token_wrapper(execute, sql, params, many, context):
|
|
49
|
+
not_in_atomic_block = (
|
|
50
|
+
context is None
|
|
51
|
+
or "connection" not in context
|
|
52
|
+
or not context["connection"].in_atomic_block
|
|
53
|
+
)
|
|
54
|
+
# ignore atomic blocks
|
|
55
|
+
if not_in_atomic_block:
|
|
56
|
+
sql = set_token_query + sql
|
|
57
|
+
elif self.debug:
|
|
58
|
+
print("--in atomic block--")
|
|
59
|
+
|
|
60
|
+
if self.debug:
|
|
61
|
+
print(sql)
|
|
62
|
+
result = execute(sql, params, many, context)
|
|
63
|
+
# this ensures that psycopg3 in the current env doesn't break this wrapper
|
|
64
|
+
# psycopg3 returns a cursor
|
|
65
|
+
# psycopg3 fetching differs from psycopg2, it returns the output of all sql statements
|
|
66
|
+
# not only the last one as psycopg2 does. So we shift the cursor from set_token
|
|
67
|
+
if (
|
|
68
|
+
not_in_atomic_block
|
|
69
|
+
and result is not None
|
|
70
|
+
and hasattr(result, "nextset")
|
|
71
|
+
):
|
|
72
|
+
if self.debug:
|
|
73
|
+
print("(shift cursor)")
|
|
74
|
+
result.nextset()
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
connection.execute_wrappers.append(set_token_wrapper)
|
|
78
|
+
|
|
79
|
+
# ensure we set the token only once for an outer atomic block
|
|
80
|
+
def __enter__(atomic):
|
|
81
|
+
self.original_atomic_enter(atomic)
|
|
82
|
+
is_same_connection = (
|
|
83
|
+
"default" if atomic.using is None else atomic.using
|
|
84
|
+
) == connection_name
|
|
85
|
+
if is_same_connection and len(connection.atomic_blocks) == 1:
|
|
86
|
+
# use raw psycopg2 connection here
|
|
87
|
+
# atomic block ensures connection
|
|
88
|
+
if self.debug:
|
|
89
|
+
print("(set transaction token)")
|
|
90
|
+
connection.connection.cursor().execute(set_token_query)
|
|
91
|
+
|
|
92
|
+
Atomic.__enter__ = __enter__
|
|
93
|
+
|
|
94
|
+
self.tokens[connection_name] = token
|
|
95
|
+
|
|
96
|
+
def reset(self, connection_name: str = "default"):
|
|
97
|
+
from django.db.transaction import Atomic
|
|
98
|
+
|
|
99
|
+
connection = self.get_connection(connection_name)
|
|
100
|
+
|
|
101
|
+
connection.execute_wrappers = [
|
|
102
|
+
w
|
|
103
|
+
for w in connection.execute_wrappers
|
|
104
|
+
if getattr(w, "__name__", None) != "set_token_wrapper"
|
|
105
|
+
]
|
|
106
|
+
Atomic.__enter__ = self.original_atomic_enter
|
|
107
|
+
|
|
108
|
+
self.tokens.pop(connection_name, None)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
db_token_manager = DBTokenManager()
|
|
40
112
|
|
|
41
113
|
|
|
42
114
|
def close_if_health_check_failed(self) -> None:
|
|
@@ -128,7 +200,8 @@ def setup_django(
|
|
|
128
200
|
if isettings._fine_grained_access and isettings._db_permissions == "jwt":
|
|
129
201
|
from ._hub_core import access_db
|
|
130
202
|
|
|
131
|
-
|
|
203
|
+
db_token = access_db(isettings)
|
|
204
|
+
db_token_manager.set(db_token) # sets for the default connection
|
|
132
205
|
|
|
133
206
|
if configure_only:
|
|
134
207
|
return None
|
|
@@ -33,7 +33,9 @@ uv pip install --system git+https://github.com/laminlabs/bionty
|
|
|
33
33
|
"""
|
|
34
34
|
if group == "hub-cloud":
|
|
35
35
|
cmds = (
|
|
36
|
-
modules_deps
|
|
36
|
+
modules_deps
|
|
37
|
+
+ "uv pip install --system sentry_sdk line_profiler wheel==0.45.1 flit"
|
|
38
|
+
+ "\nuv pip install --system ./laminhub/rest-hub --no-build-isolation"
|
|
37
39
|
)
|
|
38
40
|
elif group == "docs":
|
|
39
41
|
cmds = """uv pip install --system git+https://github.com/laminlabs/lamindb"""
|
|
@@ -52,9 +54,10 @@ uv pip install --system git+https://github.com/laminlabs/bionty
|
|
|
52
54
|
|
|
53
55
|
# above downgrades django, I don't understand why, try this
|
|
54
56
|
if group == "hub-local":
|
|
55
|
-
cmds +=
|
|
56
|
-
|
|
57
|
-
)
|
|
57
|
+
cmds += "\nuv pip install --system sentry_sdk line_profiler wheel==0.45.1 flit"
|
|
58
|
+
cmds += "\nuv pip install --system -e ./laminhub/rest-hub --no-build-isolation"
|
|
59
|
+
# check that just installing psycopg (psycopg3) doesn't break fine-grained access
|
|
60
|
+
cmds += "\nuv pip install --system psycopg[binary]"
|
|
58
61
|
|
|
59
62
|
run(session, "uv pip install --system pandera") # needed to import lamindb
|
|
60
63
|
[run(session, line) for line in cmds.splitlines()]
|
|
@@ -34,10 +34,10 @@ aws = [
|
|
|
34
34
|
"urllib3<2", # for botocore, TODO: check that really required
|
|
35
35
|
"aiobotocore[boto3]>=2.5.4,<3.0.0",
|
|
36
36
|
# exclude 2024.10.0 due to https://github.com/fsspec/s3fs/pull/910
|
|
37
|
-
"s3fs>=2023.12.2,<=2025.2
|
|
37
|
+
"s3fs>=2023.12.2,<=2025.3.2,!=2024.10.0"
|
|
38
38
|
]
|
|
39
39
|
gcp = [
|
|
40
|
-
"gcsfs>=2023.12.2,<=2025.2
|
|
40
|
+
"gcsfs>=2023.12.2,<=2025.3.2"
|
|
41
41
|
]
|
|
42
42
|
erdiagram = [
|
|
43
43
|
"django-schema-graph",
|
|
@@ -12,11 +12,11 @@ from postgrest.exceptions import APIError
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def test_connect_pass_none():
|
|
15
|
-
with pytest.raises(
|
|
15
|
+
with pytest.raises(ValueError) as err:
|
|
16
16
|
ln_setup.connect(_test=True)
|
|
17
17
|
assert (
|
|
18
18
|
err.exconly()
|
|
19
|
-
== "
|
|
19
|
+
== "ValueError: No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import lamindb_setup as ln_setup
|
|
4
|
+
import pytest
|
|
5
|
+
from django.db import transaction
|
|
6
|
+
from lamindb_setup.core._hub_core import access_db
|
|
7
|
+
from lamindb_setup.core.django import db_token_manager
|
|
8
|
+
|
|
9
|
+
assert os.environ["LAMIN_ENV"] == "local"
|
|
10
|
+
|
|
11
|
+
ln_setup.connect("instance_access_v2")
|
|
12
|
+
|
|
13
|
+
isettings = ln_setup.settings.instance
|
|
14
|
+
|
|
15
|
+
assert isettings._fine_grained_access
|
|
16
|
+
assert isettings._db_permissions == "jwt"
|
|
17
|
+
assert isettings._api_url is not None
|
|
18
|
+
|
|
19
|
+
# test querying
|
|
20
|
+
db_token_manager.debug = True
|
|
21
|
+
|
|
22
|
+
storage_record = isettings.storage.record
|
|
23
|
+
|
|
24
|
+
isettings.storage._record = None
|
|
25
|
+
with transaction.atomic():
|
|
26
|
+
assert isettings.storage.record.id == storage_record.id
|
|
27
|
+
|
|
28
|
+
# check calling access_db with a dict
|
|
29
|
+
instance_dict = {
|
|
30
|
+
"owner": isettings.owner,
|
|
31
|
+
"name": isettings.name,
|
|
32
|
+
"id": isettings._id.hex,
|
|
33
|
+
"api_url": isettings._api_url,
|
|
34
|
+
}
|
|
35
|
+
access_db(instance_dict)
|
|
36
|
+
# check calling access_db with anonymous user
|
|
37
|
+
ln_setup.settings.user.handle = "anonymous"
|
|
38
|
+
with pytest.raises(RuntimeError):
|
|
39
|
+
access_db(isettings)
|
|
40
|
+
# check with providing access_token explicitly
|
|
41
|
+
access_db(isettings, ln_setup.settings.user.access_token)
|
|
@@ -14,7 +14,6 @@ from lamindb_setup.core._hub_client import (
|
|
|
14
14
|
)
|
|
15
15
|
from lamindb_setup.core._hub_core import (
|
|
16
16
|
_connect_instance_hub,
|
|
17
|
-
access_db,
|
|
18
17
|
connect_instance_hub,
|
|
19
18
|
init_instance_hub,
|
|
20
19
|
init_storage_hub,
|
|
@@ -309,9 +308,9 @@ def test_connect_instance_hub(create_myinstance, create_testadmin1_session):
|
|
|
309
308
|
assert instance["name"] == create_myinstance["name"]
|
|
310
309
|
assert instance["db"] == expected_dsn
|
|
311
310
|
|
|
312
|
-
# add
|
|
311
|
+
# add resource_db_server from seed_local_test
|
|
313
312
|
admin_client.table("instance").update(
|
|
314
|
-
{"
|
|
313
|
+
{"resource_db_server_id": "e36c7069-2129-4c78-b2c6-323e2354b741"}
|
|
315
314
|
).eq("id", instance["id"]).execute()
|
|
316
315
|
|
|
317
316
|
instance, _ = connect_instance_hub(owner=owner, name=name)
|
|
@@ -391,8 +390,18 @@ def test_init_storage_incorrect_protocol():
|
|
|
391
390
|
assert "Protocol incorrect-protocol is not supported" in error.exconly()
|
|
392
391
|
|
|
393
392
|
|
|
394
|
-
def test_fine_grained_access(
|
|
393
|
+
def test_fine_grained_access(
|
|
394
|
+
create_testadmin1_session, create_instance_fine_grained_access
|
|
395
|
+
):
|
|
396
|
+
admin_client, testadmin1 = create_testadmin1_session
|
|
395
397
|
instance = create_instance_fine_grained_access
|
|
398
|
+
# check api_url is set up correctly through the new tables
|
|
399
|
+
instance_record = select_instance_by_name(
|
|
400
|
+
account_id=testadmin1._uuid,
|
|
401
|
+
name=instance.name,
|
|
402
|
+
client=admin_client,
|
|
403
|
+
)
|
|
404
|
+
assert instance_record["resource_db_server_id"] is not None
|
|
396
405
|
|
|
397
406
|
isettings_file = instance_settings_file(
|
|
398
407
|
instance.name, ln_setup.settings.user.handle
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
import lamindb_setup as ln_setup
|
|
4
|
-
import pytest
|
|
5
|
-
from lamindb_setup.core._hub_core import access_db
|
|
6
|
-
|
|
7
|
-
assert os.environ["LAMIN_ENV"] == "local"
|
|
8
|
-
|
|
9
|
-
ln_setup.connect("instance_access_v2")
|
|
10
|
-
|
|
11
|
-
assert ln_setup.settings.instance._fine_grained_access
|
|
12
|
-
assert ln_setup.settings.instance._db_permissions == "jwt"
|
|
13
|
-
|
|
14
|
-
# check calling access_db with anonymous user
|
|
15
|
-
ln_setup.settings.user.handle = "anonymous"
|
|
16
|
-
with pytest.raises(RuntimeError):
|
|
17
|
-
access_db(ln_setup.settings.instance)
|
|
18
|
-
# check with providing access_token explicitly
|
|
19
|
-
access_db(ln_setup.settings.instance, ln_setup.settings.user.access_token)
|
|
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-1.4.1 → lamindb_setup-1.5.0}/docs/hub-prod/test-init-load-local-anonymously.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
|
{lamindb_setup-1.4.1 → lamindb_setup-1.5.0}/tests/hub-cloud/test_init_pass_user_no_writes.py
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
|