lamindb_setup 0.74.1__tar.gz → 0.74.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.74.1 → lamindb_setup-0.74.2}/.github/workflows/build.yml +1 -1
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/.pre-commit-config.yaml +0 -6
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/PKG-INFO +3 -3
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/__init__.py +1 -1
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_connect_instance.py +3 -2
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_init_instance.py +4 -1
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_hub_client.py +4 -2
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_hub_core.py +20 -16
- lamindb_setup-0.74.2/lamindb_setup/core/_hub_utils.py +109 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_load.py +1 -1
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_save.py +2 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_store.py +3 -9
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/noxfile.py +5 -1
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/pyproject.toml +2 -2
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-local/test_all.py +2 -1
- lamindb_setup-0.74.1/lamindb_setup/core/_hub_utils.py +0 -76
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/.github/workflows/doc-changes.yml +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/.gitignore +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/LICENSE +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/README.md +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/changelog.md +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/test-multi-session.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-cloud/test_notebooks.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-cache-management.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-connect-anonymously.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-empty-init.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-import-schema.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/hub-prod/test_notebooks2.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/index.md +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/notebooks.md +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/docs/reference.md +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_cache.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_check.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_check_setup.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_close.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_delete.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_django.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_exportdb.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_importdb.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_migrate.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_register_instance.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_schema.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_schema_metadata.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_set_managed_storage.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_setup_user.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/_silence_loggers.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/__init__.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_aws_credentials.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_aws_storage.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_deprecated.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_docs.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_hub_crud.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_private_django_api.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_instance.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_storage.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_settings_user.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/django.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/exceptions.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/hashing.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/types.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/lamindb_setup/core/upath.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_connect_instance.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_delete_instance.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_init_instance.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_login.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_migrate.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-cloud/test_set_storage.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-local/conftest.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-local/test_update_schema_in_hub.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-prod/conftest.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-prod/test_django.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-prod/test_global_settings.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/hub-prod/test_upath.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/storage/test_hashing.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/storage/test_storage_access.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/storage/test_storage_basis.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/storage/test_storage_stats.py +0 -0
- {lamindb_setup-0.74.1 → lamindb_setup-0.74.2}/tests/storage/test_to_url.py +0 -0
|
@@ -44,9 +44,3 @@ repos:
|
|
|
44
44
|
(?x)(
|
|
45
45
|
tests/hub-local/conftest.py
|
|
46
46
|
)
|
|
47
|
-
- repo: https://github.com/pycqa/pydocstyle
|
|
48
|
-
rev: 6.1.1
|
|
49
|
-
hooks:
|
|
50
|
-
- id: pydocstyle
|
|
51
|
-
args: # google style + __init__, see http://www.pydocstyle.org/en/stable/error_codes.html
|
|
52
|
-
- --ignore=D100,D101,D102,D103,D104,D106,D107,D203,D204,D213,D215,D400,D401,D403,D404,D406,D407,D408,D409,D412,D413,D417
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lamindb_setup
|
|
3
|
-
Version: 0.74.
|
|
3
|
+
Version: 0.74.2
|
|
4
4
|
Summary: Setup & configure LaminDB.
|
|
5
|
-
Author-email: Lamin Labs <
|
|
5
|
+
Author-email: Lamin Labs <open-source@lamin.ai>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
Requires-Dist: lnschema_core>=0.51.0
|
|
8
8
|
Requires-Dist: lamin_utils>=0.3.3
|
|
9
9
|
Requires-Dist: django>4.2,<5.3.0
|
|
10
10
|
Requires-Dist: dj_database_url>=1.3.0,<3.0.0
|
|
11
|
-
Requires-Dist: pydantic
|
|
11
|
+
Requires-Dist: pydantic-settings
|
|
12
12
|
Requires-Dist: appdirs<2.0.0
|
|
13
13
|
Requires-Dist: requests
|
|
14
14
|
Requires-Dist: universal_pathlib==0.2.2
|
|
@@ -74,7 +74,8 @@ def update_db_using_local(
|
|
|
74
74
|
# read from a cached settings file in case the hub result is only
|
|
75
75
|
# read level or inexistent
|
|
76
76
|
elif settings_file.exists() and (
|
|
77
|
-
|
|
77
|
+
db_dsn_hub.db.user is None
|
|
78
|
+
or (db_dsn_hub.db.user is not None and "read" in db_dsn_hub.db.user)
|
|
78
79
|
):
|
|
79
80
|
isettings = load_instance_settings(settings_file)
|
|
80
81
|
db_dsn_local = LaminDsnModel(db=isettings.db)
|
|
@@ -101,7 +102,7 @@ def update_db_using_local(
|
|
|
101
102
|
scheme=db_dsn_hub.db.scheme,
|
|
102
103
|
user=db_dsn_local.db.user,
|
|
103
104
|
password=db_dsn_local.db.password,
|
|
104
|
-
host=db_dsn_hub.db.host,
|
|
105
|
+
host=db_dsn_hub.db.host, # type: ignore
|
|
105
106
|
port=db_dsn_hub.db.port,
|
|
106
107
|
database=db_dsn_hub.db.database,
|
|
107
108
|
)
|
|
@@ -245,7 +245,10 @@ def init(
|
|
|
245
245
|
if instance_state == "connected":
|
|
246
246
|
settings.auto_connect = True # we can also debate this switch here
|
|
247
247
|
return None
|
|
248
|
-
|
|
248
|
+
# cannot past instance_id here because instance does not yet exist!
|
|
249
|
+
# the instance_id field of the storage table is populated at the end of
|
|
250
|
+
# init_instance_hub
|
|
251
|
+
ssettings = init_storage(storage)
|
|
249
252
|
isettings = InstanceSettings(
|
|
250
253
|
id=instance_id, # type: ignore
|
|
251
254
|
owner=settings.user.handle,
|
|
@@ -5,7 +5,7 @@ from urllib.request import urlretrieve
|
|
|
5
5
|
|
|
6
6
|
from gotrue.errors import AuthUnknownError
|
|
7
7
|
from lamin_utils import logger
|
|
8
|
-
from
|
|
8
|
+
from pydantic_settings import BaseSettings
|
|
9
9
|
from supabase import Client, create_client # type: ignore
|
|
10
10
|
from supabase.lib.client_options import ClientOptions
|
|
11
11
|
|
|
@@ -59,9 +59,11 @@ class Environment:
|
|
|
59
59
|
|
|
60
60
|
# runs ~0.5s
|
|
61
61
|
def connect_hub(
|
|
62
|
-
fallback_env: bool = False, client_options: ClientOptions =
|
|
62
|
+
fallback_env: bool = False, client_options: ClientOptions | None = None
|
|
63
63
|
) -> Client:
|
|
64
64
|
env = Environment(fallback=fallback_env)
|
|
65
|
+
if client_options is None:
|
|
66
|
+
client_options = ClientOptions(auto_refresh_token=False)
|
|
65
67
|
return create_client(env.supabase_api_url, env.supabase_anon_key, client_options)
|
|
66
68
|
|
|
67
69
|
|
|
@@ -93,20 +93,21 @@ def _select_storage(
|
|
|
93
93
|
return False
|
|
94
94
|
else:
|
|
95
95
|
existing_storage = response.data[0]
|
|
96
|
-
if
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
96
|
+
if existing_storage["instance_id"] is not None:
|
|
97
|
+
if ssettings._instance_id is not None:
|
|
98
|
+
# consider storage settings that are meant to be managed by an instance
|
|
99
|
+
if UUID(existing_storage["instance_id"]) != ssettings._instance_id:
|
|
100
|
+
# everything is alright if the instance_id matches
|
|
101
|
+
# we're probably just switching storage locations
|
|
102
|
+
# below can be turned into a warning and then delegate the error
|
|
103
|
+
# to a unique constraint violation below
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"Storage root {root} is already managed by instance {existing_storage['instance_id']}."
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
# if the request is agnostic of the instance, that's alright,
|
|
109
|
+
# we'll update the instance_id with what's stored in the hub
|
|
110
|
+
ssettings._instance_id = UUID(existing_storage["instance_id"])
|
|
110
111
|
ssettings._uuid_ = UUID(existing_storage["id"])
|
|
111
112
|
if update_uid:
|
|
112
113
|
ssettings._uid = existing_storage["lnid"]
|
|
@@ -145,11 +146,14 @@ def _init_storage(ssettings: StorageSettings, client: Client) -> None:
|
|
|
145
146
|
id = uuid.uuid5(uuid.NAMESPACE_URL, root)
|
|
146
147
|
else:
|
|
147
148
|
id = uuid.uuid4()
|
|
148
|
-
if ssettings._instance_id is None:
|
|
149
|
+
if ssettings._instance_id is None and settings._instance_exists:
|
|
149
150
|
logger.warning(
|
|
150
151
|
f"will manage storage location {ssettings.root_as_str} with instance {settings.instance.slug}"
|
|
151
152
|
)
|
|
152
153
|
ssettings._instance_id = settings.instance._id
|
|
154
|
+
instance_id_hex = (
|
|
155
|
+
None if ssettings._instance_id is None else ssettings._instance_id.hex
|
|
156
|
+
)
|
|
153
157
|
fields = {
|
|
154
158
|
"id": id.hex,
|
|
155
159
|
"lnid": ssettings.uid,
|
|
@@ -157,7 +161,7 @@ def _init_storage(ssettings: StorageSettings, client: Client) -> None:
|
|
|
157
161
|
"root": root,
|
|
158
162
|
"region": ssettings.region,
|
|
159
163
|
"type": ssettings.type,
|
|
160
|
-
"instance_id":
|
|
164
|
+
"instance_id": instance_id_hex,
|
|
161
165
|
# the empty string is important as we want the user flow to be through LaminHub
|
|
162
166
|
# if this errors with unique constraint error, the user has to update
|
|
163
167
|
# the description in LaminHub
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, ClassVar, Optional
|
|
4
|
+
from urllib.parse import urlparse, urlunparse
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field, GetCoreSchemaHandler
|
|
7
|
+
from pydantic_core import CoreSchema, core_schema
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def validate_schema_arg(schema: str | None = None) -> str:
|
|
11
|
+
if schema is None or schema == "":
|
|
12
|
+
return ""
|
|
13
|
+
# currently no actual validation, can add back if we see a need
|
|
14
|
+
# the following just strips white spaces
|
|
15
|
+
to_be_validated = [s.strip() for s in schema.split(",")]
|
|
16
|
+
return ",".join(to_be_validated)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def validate_db_arg(db: str | None) -> None:
|
|
20
|
+
if db is not None:
|
|
21
|
+
LaminDsnModel(db=db)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LaminDsn(str):
|
|
25
|
+
allowed_schemes: ClassVar[set[str]] = {
|
|
26
|
+
"postgresql",
|
|
27
|
+
# future enabled schemes
|
|
28
|
+
# "snowflake",
|
|
29
|
+
# "bigquery"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def __get_pydantic_core_schema__(
|
|
34
|
+
cls, source_type: Any, handler: GetCoreSchemaHandler
|
|
35
|
+
) -> CoreSchema:
|
|
36
|
+
return core_schema.no_info_after_validator_function(
|
|
37
|
+
cls.validate,
|
|
38
|
+
core_schema.str_schema(),
|
|
39
|
+
serialization=core_schema.plain_serializer_function_ser_schema(str),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def validate(cls, v: Any) -> LaminDsn:
|
|
44
|
+
if isinstance(v, str):
|
|
45
|
+
parsed = urlparse(v)
|
|
46
|
+
if parsed.scheme not in cls.allowed_schemes:
|
|
47
|
+
raise ValueError(f"Invalid scheme: {parsed.scheme}")
|
|
48
|
+
return cls(v)
|
|
49
|
+
elif isinstance(v, cls):
|
|
50
|
+
return v
|
|
51
|
+
else:
|
|
52
|
+
raise ValueError(f"Invalid value for LaminDsn: {v}")
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def user(self) -> str | None:
|
|
56
|
+
return urlparse(self).username
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def password(self) -> str | None:
|
|
60
|
+
return urlparse(self).password
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def host(self) -> str | None:
|
|
64
|
+
return urlparse(self).hostname
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def port(self) -> int | None:
|
|
68
|
+
return urlparse(self).port
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def database(self) -> str:
|
|
72
|
+
return urlparse(self).path.lstrip("/")
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def scheme(self) -> str:
|
|
76
|
+
return urlparse(self).scheme
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def build(
|
|
80
|
+
cls,
|
|
81
|
+
*,
|
|
82
|
+
scheme: str,
|
|
83
|
+
user: str | None = None,
|
|
84
|
+
password: str | None = None,
|
|
85
|
+
host: str,
|
|
86
|
+
port: int | None = None,
|
|
87
|
+
database: str | None = None,
|
|
88
|
+
query: str | None = None,
|
|
89
|
+
fragment: str | None = None,
|
|
90
|
+
) -> LaminDsn:
|
|
91
|
+
netloc = host
|
|
92
|
+
if port is not None:
|
|
93
|
+
netloc = f"{netloc}:{port}"
|
|
94
|
+
if user is not None:
|
|
95
|
+
auth = user
|
|
96
|
+
if password is not None:
|
|
97
|
+
auth = f"{auth}:{password}"
|
|
98
|
+
netloc = f"{auth}@{netloc}"
|
|
99
|
+
|
|
100
|
+
path = f"/{database}" if database else ""
|
|
101
|
+
|
|
102
|
+
url = urlunparse((scheme, netloc, path, "", query or "", fragment or ""))
|
|
103
|
+
return cls(url)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class LaminDsnModel(BaseModel):
|
|
107
|
+
db: LaminDsn = Field(..., description="The database DSN")
|
|
108
|
+
|
|
109
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Optional
|
|
|
4
4
|
from uuid import UUID, uuid4
|
|
5
5
|
|
|
6
6
|
from lamin_utils import logger
|
|
7
|
-
from pydantic
|
|
7
|
+
from pydantic import ValidationError
|
|
8
8
|
|
|
9
9
|
from ._settings_instance import InstanceSettings
|
|
10
10
|
from ._settings_storage import StorageSettings
|
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
6
6
|
|
|
7
7
|
if "LAMIN_SETTINGS_DIR" in os.environ:
|
|
8
8
|
# Needed when running with AWS Lambda, as only tmp/ directory has a write access
|
|
@@ -58,10 +58,7 @@ class InstanceSettingsStore(BaseSettings):
|
|
|
58
58
|
id: str
|
|
59
59
|
git_repo: Optional[str]
|
|
60
60
|
keep_artifacts_local: Optional[bool]
|
|
61
|
-
|
|
62
|
-
class Config:
|
|
63
|
-
env_prefix = "lamindb_instance_"
|
|
64
|
-
env_file = ".env"
|
|
61
|
+
model_config = SettingsConfigDict(env_prefix="lamindb_instance_", env_file=".env")
|
|
65
62
|
|
|
66
63
|
|
|
67
64
|
class UserSettingsStore(BaseSettings):
|
|
@@ -72,7 +69,4 @@ class UserSettingsStore(BaseSettings):
|
|
|
72
69
|
uuid: str
|
|
73
70
|
handle: str
|
|
74
71
|
name: str
|
|
75
|
-
|
|
76
|
-
class Config:
|
|
77
|
-
env_prefix = "lamin_user_"
|
|
78
|
-
env_file = ".env"
|
|
72
|
+
model_config = SettingsConfigDict(env_prefix="lamin_user_", env_file=".env")
|
|
@@ -45,10 +45,14 @@ uv pip install --system --no-deps {no_deps_packages}
|
|
|
45
45
|
cmds = ""
|
|
46
46
|
cmds += schema_deps.strip()
|
|
47
47
|
elif group == "hub-local":
|
|
48
|
-
cmds = schema_deps
|
|
48
|
+
cmds = schema_deps.strip()
|
|
49
49
|
# current package
|
|
50
50
|
cmds += """\nuv pip install --system -e '.[aws,dev]' lamin-cli"""
|
|
51
51
|
|
|
52
|
+
# above downgrades django, I don't understand why, try this
|
|
53
|
+
if group == "hub-local":
|
|
54
|
+
cmds += "\nuv pip install --system -e ./laminhub/rest-hub"
|
|
55
|
+
|
|
52
56
|
[run(session, line) for line in cmds.splitlines()]
|
|
53
57
|
|
|
54
58
|
|
|
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lamindb_setup"
|
|
7
|
-
authors = [{name = "Lamin Labs", email = "
|
|
7
|
+
authors = [{name = "Lamin Labs", email = "open-source@lamin.ai"}]
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
dynamic = ["version", "description"]
|
|
10
10
|
dependencies = [
|
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
|
13
13
|
# External dependencies
|
|
14
14
|
"django>4.2,<5.3.0",
|
|
15
15
|
"dj_database_url>=1.3.0,<3.0.0",
|
|
16
|
-
"pydantic
|
|
16
|
+
"pydantic-settings",
|
|
17
17
|
"appdirs<2.0.0",
|
|
18
18
|
"requests",
|
|
19
19
|
"universal_pathlib==0.2.2", # is still experimental, need pinning
|
|
@@ -118,8 +118,9 @@ def create_myinstance(create_testadmin1_session): # -> Dict
|
|
|
118
118
|
id=instance_id,
|
|
119
119
|
owner=usettings.handle,
|
|
120
120
|
name="myinstance",
|
|
121
|
+
# cannot yet pass instance_id here as it does not yet exist
|
|
121
122
|
storage=init_storage_base(
|
|
122
|
-
"s3://lamindb-ci/myinstance",
|
|
123
|
+
"s3://lamindb-ci/myinstance",
|
|
123
124
|
),
|
|
124
125
|
db=db_str,
|
|
125
126
|
)
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, validator
|
|
6
|
-
from pydantic.networks import MultiHostDsn
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def validate_schema_arg(schema: str | None = None) -> str:
|
|
10
|
-
if schema is None or schema == "":
|
|
11
|
-
return ""
|
|
12
|
-
# currently no actual validation, can add back if we see a need
|
|
13
|
-
# the following just strips white spaces
|
|
14
|
-
to_be_validated = [s.strip() for s in schema.split(",")]
|
|
15
|
-
return ",".join(to_be_validated)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def validate_db_arg(db: str | None) -> None:
|
|
19
|
-
if db is not None:
|
|
20
|
-
LaminDsnModel(db=db)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class LaminDsn(MultiHostDsn):
|
|
24
|
-
"""Custom DSN Type for Lamin.
|
|
25
|
-
|
|
26
|
-
This class allows us to customize the allowed schemes for databases
|
|
27
|
-
and also handles the parsing and building of DSN strings with the
|
|
28
|
-
database name instead of URL path.
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
allowed_schemes = {
|
|
32
|
-
"postgresql",
|
|
33
|
-
# future enabled schemes
|
|
34
|
-
# "snowflake",
|
|
35
|
-
# "bigquery"
|
|
36
|
-
}
|
|
37
|
-
user_required = True
|
|
38
|
-
__slots__ = ()
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
def database(self):
|
|
42
|
-
return self.path[1:]
|
|
43
|
-
|
|
44
|
-
@classmethod
|
|
45
|
-
def build(
|
|
46
|
-
cls,
|
|
47
|
-
*,
|
|
48
|
-
scheme: str,
|
|
49
|
-
user: str | None = None,
|
|
50
|
-
password: str | None = None,
|
|
51
|
-
host: str,
|
|
52
|
-
port: str | None = None,
|
|
53
|
-
database: str | None = None,
|
|
54
|
-
query: str | None = None,
|
|
55
|
-
fragment: str | None = None,
|
|
56
|
-
**_kwargs: str,
|
|
57
|
-
) -> str:
|
|
58
|
-
return super().build(
|
|
59
|
-
scheme=scheme,
|
|
60
|
-
user=user,
|
|
61
|
-
password=password,
|
|
62
|
-
host=host,
|
|
63
|
-
port=str(port),
|
|
64
|
-
path=f"/{database}",
|
|
65
|
-
query=query,
|
|
66
|
-
fragment=fragment,
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class LaminDsnModel(BaseModel):
|
|
71
|
-
db: LaminDsn
|
|
72
|
-
|
|
73
|
-
@validator("db")
|
|
74
|
-
def check_db_name(cls, v):
|
|
75
|
-
assert v.path and len(v.path) > 1, "database must be provided"
|
|
76
|
-
return v
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamindb_setup-0.74.1 → lamindb_setup-0.74.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.74.1 → lamindb_setup-0.74.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.74.1 → lamindb_setup-0.74.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
|
{lamindb_setup-0.74.1 → lamindb_setup-0.74.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
|