lamindb_setup 0.76.3__py2.py3-none-any.whl → 0.76.5__py2.py3-none-any.whl

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/__init__.py CHANGED
@@ -34,7 +34,7 @@ Modules & settings:
34
34
 
35
35
  """
36
36
 
37
- __version__ = "0.76.3" # denote a release candidate for 0.1.0 with 0.1rc1
37
+ __version__ = "0.76.5" # denote a release candidate for 0.1.0 with 0.1rc1
38
38
 
39
39
  import sys
40
40
  from os import name as _os_name
@@ -250,7 +250,7 @@ def init(
250
250
  # see a way of making this more elegant; should become possible if we
251
251
  # remove the instance.storage_id FK on the hub
252
252
  prevent_register_hub = is_local_db_url(db) if db is not None else False
253
- ssettings = init_storage(
253
+ ssettings, _ = init_storage(
254
254
  storage,
255
255
  instance_id=instance_id,
256
256
  init_instance=True,
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
  from lamin_utils import logger
6
6
 
7
7
  from ._init_instance import register_storage_in_instance
8
+ from .core._hub_core import delete_storage_record
8
9
  from .core._settings import settings
9
10
  from .core._settings_storage import init_storage
10
11
 
@@ -28,14 +29,27 @@ def set_managed_storage(root: UPathStr, **fs_kwargs):
28
29
  raise ValueError(
29
30
  "Can't add additional managed storage locations for instances that aren't managed through the hub."
30
31
  )
31
- ssettings = init_storage(
32
+ # here the storage is registered in the hub
33
+ # hub_record_status="hub_record_created" if a new record is created
34
+ # "hub_record_retrieved" if the storage is in the hub already
35
+ ssettings, hub_record_status = init_storage(
32
36
  root=root, instance_id=settings.instance._id, register_hub=True
33
37
  )
34
38
  if ssettings._instance_id is None:
35
39
  raise ValueError(
36
40
  f"Cannot manage storage without write access: {ssettings.root}"
37
41
  )
42
+
43
+ # here the storage is saved in the instance
44
+ # if any error happens the record in the hub is deleted
45
+ # if it was created earlier and not retrieved
46
+ try:
47
+ register_storage_in_instance(ssettings)
48
+ except Exception as e:
49
+ if hub_record_status == "hub_record_created" and ssettings._uuid is not None:
50
+ delete_storage_record(ssettings._uuid) # type: ignore
51
+ raise e
52
+
38
53
  settings.instance._storage = ssettings
39
54
  settings.instance._persist() # this also updates the settings object
40
- register_storage_in_instance(ssettings)
41
55
  settings.storage._set_fs_kwargs(**fs_kwargs)
@@ -4,7 +4,7 @@ import json
4
4
  import os
5
5
  import uuid
6
6
  from importlib import metadata
7
- from typing import TYPE_CHECKING
7
+ from typing import TYPE_CHECKING, Literal
8
8
  from uuid import UUID
9
9
 
10
10
  from lamin_utils import logger
@@ -19,10 +19,10 @@ from ._hub_crud import (
19
19
  _delete_instance_record,
20
20
  select_account_by_handle,
21
21
  select_db_user_by_instance,
22
+ select_default_storage_by_instance_id,
22
23
  select_instance_by_id_with_storage,
23
24
  select_instance_by_name,
24
25
  select_instance_by_owner_name,
25
- select_storage,
26
26
  )
27
27
  from ._hub_crud import update_instance as _update_instance_record
28
28
  from ._hub_utils import (
@@ -119,7 +119,7 @@ def _select_storage(
119
119
  def init_storage(
120
120
  ssettings: StorageSettings,
121
121
  auto_populate_instance: bool = True,
122
- ) -> None:
122
+ ) -> Literal["hub_record_retrieved", "hub_record_created"]:
123
123
  if settings.user.handle != "anonymous":
124
124
  return call_with_fallback_auth(
125
125
  _init_storage,
@@ -131,21 +131,21 @@ def init_storage(
131
131
  _select_storage, ssettings=ssettings, update_uid=True
132
132
  )
133
133
  if storage_exists:
134
- return None
134
+ return "hub_record_retrieved"
135
135
  else:
136
136
  raise ValueError("Log in to create a storage location on the hub.")
137
137
 
138
138
 
139
139
  def _init_storage(
140
140
  ssettings: StorageSettings, auto_populate_instance: bool, client: Client
141
- ) -> None:
141
+ ) -> Literal["hub_record_retrieved", "hub_record_created"]:
142
142
  from lamindb_setup import settings
143
143
 
144
144
  # storage roots are always stored without the trailing slash in the SQL
145
145
  # database
146
146
  root = ssettings.root_as_str
147
147
  if _select_storage(ssettings, update_uid=True, client=client):
148
- return None
148
+ return "hub_record_retrieved"
149
149
  if ssettings.type_is_cloud:
150
150
  id = uuid.uuid5(uuid.NAMESPACE_URL, root)
151
151
  else:
@@ -181,7 +181,7 @@ def _init_storage(
181
181
  # on root & description
182
182
  client.table("storage").upsert(fields).execute()
183
183
  ssettings._uuid_ = id
184
- return None
184
+ return "hub_record_created"
185
185
 
186
186
 
187
187
  def delete_instance(identifier: UUID | str, require_empty: bool = True) -> str | None:
@@ -338,7 +338,7 @@ def _connect_instance(
338
338
  if instance is None:
339
339
  return "instance-not-found"
340
340
  # get default storage
341
- storage = select_storage(instance["storage_id"], client)
341
+ storage = select_default_storage_by_instance_id(instance["id"], client)
342
342
  if storage is None:
343
343
  return "storage-does-not-exist-on-hub"
344
344
  else:
@@ -364,7 +364,7 @@ def _connect_instance(
364
364
  database=instance["db_database"],
365
365
  )
366
366
  instance["db"] = db_dsn
367
- return instance, storage
367
+ return instance, storage # type: ignore
368
368
 
369
369
 
370
370
  def access_aws(storage_root: str, access_token: str | None = None) -> dict[str, dict]:
@@ -17,10 +17,11 @@ def select_instance_by_owner_name(
17
17
  client.table("instance")
18
18
  .select(
19
19
  "*, account!inner!instance_account_id_28936e8f_fk_account_id(*),"
20
- " storage!instance_storage_id_87963cc8_fk_storage_id(*)"
20
+ " storage!inner!storage_instance_id_359fca71_fk_instance_id(*)"
21
21
  )
22
- .eq("account.handle", owner)
23
22
  .eq("name", name)
23
+ .eq("account.handle", owner)
24
+ .eq("storage.is_default", True)
24
25
  .execute()
25
26
  .data
26
27
  )
@@ -28,7 +29,11 @@ def select_instance_by_owner_name(
28
29
  return None
29
30
  if len(data) == 0:
30
31
  return None
31
- return data[0]
32
+ result = data[0]
33
+ # this is now a list
34
+ # assume only one default storage
35
+ result["storage"] = result["storage"][0]
36
+ return result
32
37
 
33
38
 
34
39
  # --------------- ACCOUNT ----------------------
@@ -131,8 +136,20 @@ def select_collaborator(
131
136
  # --------------- STORAGE ----------------------
132
137
 
133
138
 
134
- def select_storage(id: str, client: Client):
135
- data = client.table("storage").select("*").eq("id", id).execute().data
139
+ def select_default_storage_by_instance_id(
140
+ instance_id: str, client: Client
141
+ ) -> dict | None:
142
+ try:
143
+ data = (
144
+ client.table("storage")
145
+ .select("*")
146
+ .eq("instance_id", instance_id)
147
+ .eq("is_default", True)
148
+ .execute()
149
+ .data
150
+ )
151
+ except Exception:
152
+ return None
136
153
  if len(data) == 0:
137
154
  return None
138
155
  return data[0]
@@ -230,7 +230,7 @@ class InstanceSettings:
230
230
  return None
231
231
  local_root = UPath(local_root)
232
232
  assert isinstance(local_root, LocalPathClasses)
233
- self._storage_local = init_storage(local_root, self._id, register_hub=True) # type: ignore
233
+ self._storage_local, _ = init_storage(local_root, self._id, register_hub=True) # type: ignore
234
234
  register_storage_in_instance(self._storage_local) # type: ignore
235
235
  logger.important(f"defaulting to local storage: {self._storage_local.root}")
236
236
 
@@ -36,14 +36,9 @@ def load_instance_settings(instance_settings_file: Path | None = None):
36
36
  content = f.read()
37
37
  raise SettingsEnvFileOutdated(
38
38
  f"\n\n{error}\n\nYour instance settings file with\n\n{content}\nis invalid"
39
- f" (likely outdated), please delete {instance_settings_file} &"
40
- " re-initialize (local) or re-connect to the instance (remote)"
39
+ f" (likely outdated), see validation error. Please delete {instance_settings_file} &"
40
+ " reload (remote) or re-initialize (local) the instance with the same name & storage location."
41
41
  ) from error
42
- if settings_store.id == "null":
43
- raise ValueError(
44
- "Your instance._id is undefined, please either load your instance from the"
45
- f" hub or update {instance_settings_file} with a new id: {uuid4().hex}"
46
- )
47
42
  isettings = setup_instance_from_store(settings_store)
48
43
  return isettings
49
44
 
@@ -83,7 +83,10 @@ def init_storage(
83
83
  register_hub: bool | None = None,
84
84
  prevent_register_hub: bool = False,
85
85
  init_instance: bool = False,
86
- ) -> StorageSettings:
86
+ ) -> tuple[
87
+ StorageSettings,
88
+ Literal["hub_record_not_created", "hub_record_retrieved", "hub_record_created"],
89
+ ]:
87
90
  if root is None:
88
91
  raise ValueError("`storage` argument can't be `None`")
89
92
  root_str = str(root) # ensure we have a string
@@ -117,13 +120,19 @@ def init_storage(
117
120
  region=region,
118
121
  instance_id=instance_id,
119
122
  )
123
+ # this stores the result of init_storage_hub
124
+ hub_record_status: Literal[
125
+ "hub_record_not_created", "hub_record_retrieved", "hub_record_created"
126
+ ] = "hub_record_not_created"
120
127
  # the below might update the uid with one that's already taken on the hub
121
128
  if not prevent_register_hub:
122
129
  if ssettings.type_is_cloud or register_hub:
123
130
  from ._hub_core import delete_storage_record
124
131
  from ._hub_core import init_storage as init_storage_hub
125
132
 
126
- init_storage_hub(ssettings, auto_populate_instance=not init_instance)
133
+ hub_record_status = init_storage_hub(
134
+ ssettings, auto_populate_instance=not init_instance
135
+ )
127
136
  # below comes last only if everything else was successful
128
137
  try:
129
138
  # (federated) credentials for AWS access are provisioned under-the-hood
@@ -133,10 +142,14 @@ def init_storage(
133
142
  logger.important(
134
143
  f"due to lack of write access, LaminDB won't manage storage location: {ssettings.root}"
135
144
  )
136
- if ssettings._uuid is not None:
145
+ # we have to check hub_record_status here because
146
+ # _select_storage inside init_storage_hub also populates ssettings._uuid
147
+ # and we don't want to delete an existing storage record here
148
+ # only newly created
149
+ if hub_record_status == "hub_record_created" and ssettings._uuid is not None:
137
150
  delete_storage_record(ssettings._uuid) # type: ignore
138
151
  ssettings._instance_id = None
139
- return ssettings
152
+ return ssettings, hub_record_status
140
153
 
141
154
 
142
155
  def _process_cache_path(cache_path: str | Path | UPath | None):
@@ -18,7 +18,7 @@ from upath.implementations.cloud import CloudPath, S3Path # keep CloudPath!
18
18
  from upath.implementations.local import LocalPath, PosixUPath, WindowsUPath
19
19
 
20
20
  from ._aws_credentials import HOSTED_BUCKETS, get_aws_credentials_manager
21
- from .hashing import b16_to_b64, hash_md5s_from_dir
21
+ from .hashing import HASH_LENGTH, b16_to_b64, hash_md5s_from_dir
22
22
 
23
23
  if TYPE_CHECKING:
24
24
  from .types import UPathStr
@@ -707,9 +707,9 @@ def get_stat_file_cloud(stat: dict) -> tuple[int, str, str]:
707
707
  else:
708
708
  stripped_etag, suffix = etag.split("-")
709
709
  suffix = suffix.strip('"')
710
- hash = f"{b16_to_b64(stripped_etag)}-{suffix}"
711
- hash_type = "md5-n" # this is the S3 chunk-hashing strategy
712
- return size, hash, hash_type
710
+ hash = b16_to_b64(stripped_etag)
711
+ hash_type = f"md5-{suffix}" # this is the S3 chunk-hashing strategy
712
+ return size, hash[:HASH_LENGTH], hash_type
713
713
 
714
714
 
715
715
  def get_stat_dir_cloud(path: UPath) -> tuple[int, str, str, int]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamindb_setup
3
- Version: 0.76.3
3
+ Version: 0.76.5
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -1,4 +1,4 @@
1
- lamindb_setup/__init__.py,sha256=hXWSzOTJWwpoCg2nw2RH87bEJu7oXk_jyxAbJdcrsYU,1542
1
+ lamindb_setup/__init__.py,sha256=NzRrDVvtOt5b48-AV5mbNzjP35fl6FOZy8R6GWGSOy4,1542
2
2
  lamindb_setup/_cache.py,sha256=wA7mbysANwe8hPNbjDo9bOmXJ0xIyaS5iyxIpxSWji4,846
3
3
  lamindb_setup/_check.py,sha256=28PcG8Kp6OpjSLSi1r2boL2Ryeh6xkaCL87HFbjs6GA,129
4
4
  lamindb_setup/_check_setup.py,sha256=cNEL9Q4yPpmEkGKHH8JgullWl1VUZwALJ4RHn9wZypY,2613
@@ -8,12 +8,12 @@ lamindb_setup/_delete.py,sha256=Y8KSFYgY0UHAvjd7cCL6hZ_XiLeJwx50BguVATcj_Xo,5524
8
8
  lamindb_setup/_django.py,sha256=EoyWvFzH0i9wxjy4JZhcoXCTckztP_Mrl6FbYQnMmLE,1534
9
9
  lamindb_setup/_exportdb.py,sha256=43g77-tH-vAlTn8ig1mMD9-KXLKvxUeDLaq0gVu3l-c,2114
10
10
  lamindb_setup/_importdb.py,sha256=yYYShzUajTsR-cTW4CZ-UNDWZY2uE5PAgNbp-wn8Ogc,1874
11
- lamindb_setup/_init_instance.py,sha256=pR_pK38okij7CfnQDecJLKR5lhhTeE4oZ14Lb9bMMQg,12388
11
+ lamindb_setup/_init_instance.py,sha256=VxHgD2i0hrFm2f_WCX76YmS_Lsx2iufrMtfab82r8X0,12391
12
12
  lamindb_setup/_migrate.py,sha256=P4n3x0SYzO9szjF2-JMa7z4mQadtWjHv5ow4HbCDZLI,8864
13
13
  lamindb_setup/_register_instance.py,sha256=alQuYp2f8Ct8xvRC1gt8p_HZ0tqCd3gZD3kiPBLPpsI,1269
14
14
  lamindb_setup/_schema.py,sha256=b3uzhhWpV5mQtDwhMINc2MabGCnGLESy51ito3yl6Wc,679
15
15
  lamindb_setup/_schema_metadata.py,sha256=nF29OuMNswJUCyvSyOHEUQLQ7PcfB7uwvczloBYSWuU,13187
16
- lamindb_setup/_set_managed_storage.py,sha256=mNZrANn-9rwZ0oGWxxg0wS0T0VOQCWyo4nSSyNAE15Q,1419
16
+ lamindb_setup/_set_managed_storage.py,sha256=aFVxk8sl6Jzh-LU_1sxICm_rcDPMr5Q9qmwPtUtrUbA,2043
17
17
  lamindb_setup/_setup_user.py,sha256=6Oc7Rke-yRQSZbuntdUAz8QbJ6UuPzYHI9FnYlf_q-A,3670
18
18
  lamindb_setup/_silence_loggers.py,sha256=AKF_YcHvX32eGXdsYK8MJlxEaZ-Uo2f6QDRzjKFCtws,1568
19
19
  lamindb_setup/core/__init__.py,sha256=BxIVMX5HQq8oZ1OuY_saUEJz5Tdd7gaCPngxVu5iou4,417
@@ -22,15 +22,15 @@ lamindb_setup/core/_aws_storage.py,sha256=nEjeUv4xUVpoV0Lx-zjjmyb9w804bDyaeiM-Oq
22
22
  lamindb_setup/core/_deprecated.py,sha256=3qxUI1dnDlSeR0BYrv7ucjqRBEojbqotPgpShXs4KF8,2520
23
23
  lamindb_setup/core/_docs.py,sha256=3k-YY-oVaJd_9UIY-LfBg_u8raKOCNfkZQPA73KsUhs,276
24
24
  lamindb_setup/core/_hub_client.py,sha256=Gpt3TmxWQMVenKugCu1agUb-xGN9YFsQOKmrHuFiiDs,5605
25
- lamindb_setup/core/_hub_core.py,sha256=XqXZatJOIDXukfdwL3Buq3WXZK-VVGg5OFRm2PrzO1o,16836
26
- lamindb_setup/core/_hub_crud.py,sha256=b1XF7AJpM9Q-ttm9nPG-r3OTRWHQaGzAGIyvmb83NTo,4859
25
+ lamindb_setup/core/_hub_core.py,sha256=YQ8-RiNbhTzXC_bGob3WfL47Svm0g8U8e1kxxn1nlzY,17049
26
+ lamindb_setup/core/_hub_crud.py,sha256=eZErpq9t1Cp2ULBSi457ekrcqfesw4Y6IJgaqyrINMY,5276
27
27
  lamindb_setup/core/_hub_utils.py,sha256=w5IRtrxZcvxmGSJslzuZF89ewkzXV4cCUmZUVrqmAfo,3026
28
28
  lamindb_setup/core/_private_django_api.py,sha256=KIn43HOhiRjkbTbddyJqv-WNTTa1bAizbM1tWXoXPBg,2869
29
29
  lamindb_setup/core/_settings.py,sha256=46axQ5HPvI0X9YuotgdpuSOfSo7qYU1DudIx3vxpFk0,4471
30
- lamindb_setup/core/_settings_instance.py,sha256=rPTL_Iwv-ZVMRzu_EV_E7APFkEXLoD0TgUrz5293-vg,17586
31
- lamindb_setup/core/_settings_load.py,sha256=63PTIVLk3oH1XUmznswygcOk_8VADrJLMB6O9AOppYg,3907
30
+ lamindb_setup/core/_settings_instance.py,sha256=azgqSWEnTfZM9ghgdF6atvIxoUP6fx49Y9tZTqMQTuc,17589
31
+ lamindb_setup/core/_settings_load.py,sha256=bRkGgaEnLZmnOlU5ptDoSM-YXzC2l0Cb7RBoBY6VH9k,3717
32
32
  lamindb_setup/core/_settings_save.py,sha256=n_tYfb9EBSxwm4LHyPRHJptE5uB8lmHhcRkz1JkAmhg,2781
33
- lamindb_setup/core/_settings_storage.py,sha256=bvEOm2aH4M6xBTfTARcWkx6b-jtKYl_AIUbH5yQC9GI,13435
33
+ lamindb_setup/core/_settings_storage.py,sha256=aP5cdEy9xmvNFAtU8AmpBifYWxeSFwp4Vt1UwpaKJ7o,14080
34
34
  lamindb_setup/core/_settings_store.py,sha256=VEE8Ff2A7y4j8ksOaa7g48jNaOqe1PBnBjb1PKKGUKU,2115
35
35
  lamindb_setup/core/_settings_user.py,sha256=P2lC4WDRAFfT-Xq3MlXJ-wMKIHCoGNhMTQfRGIAyUNQ,1344
36
36
  lamindb_setup/core/_setup_bionty_sources.py,sha256=ANBIiWHoYxLBQqsiKs-rCq3k-p6D34T4NM28gkY6YLA,3389
@@ -39,8 +39,8 @@ lamindb_setup/core/django.py,sha256=QUQm3zt5QIiD8uv6o9vbSm_bshqiSWzKSkgD3z2eJCg,
39
39
  lamindb_setup/core/exceptions.py,sha256=eoI7AXgATgDVzgArtN7CUvpaMUC067vsBg5LHCsWzDM,305
40
40
  lamindb_setup/core/hashing.py,sha256=Y2cvEaqtm3KwpHqj5ZG2f_sLaXhsQT4oDrmJdHbOQeo,3116
41
41
  lamindb_setup/core/types.py,sha256=bcYnZ0uM_2NXKJCl94Mmc-uYrQlRUUVKG3sK2N-F-N4,532
42
- lamindb_setup/core/upath.py,sha256=Bhxr1B1sFuIp13YTBOEYJSmSOwmU6owk8giBGLCKdg4,27194
43
- lamindb_setup-0.76.3.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
44
- lamindb_setup-0.76.3.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
45
- lamindb_setup-0.76.3.dist-info/METADATA,sha256=29omTu3ShcauGqhxT0g_ZAAuOBZveomsA-hFBH3OGzs,1638
46
- lamindb_setup-0.76.3.dist-info/RECORD,,
42
+ lamindb_setup/core/upath.py,sha256=EPLLm62q-Y3hZzd-286cynFMttXKDNXNOKL3_QGkeug,27215
43
+ lamindb_setup-0.76.5.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
44
+ lamindb_setup-0.76.5.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
45
+ lamindb_setup-0.76.5.dist-info/METADATA,sha256=RLVkEp_g_smCBEWDglvm2IcBKUbCV3SHFfNOZjOngNk,1638
46
+ lamindb_setup-0.76.5.dist-info/RECORD,,