lamindb_setup 1.7.2__py3-none-any.whl → 1.8.0__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
@@ -35,7 +35,7 @@ Modules & settings:
35
35
 
36
36
  """
37
37
 
38
- __version__ = "1.7.2" # denote a release candidate for 0.1.0 with 0.1rc1
38
+ __version__ = "1.8.0" # denote a release candidate for 0.1.0 with 0.1rc1
39
39
 
40
40
  import os
41
41
 
@@ -7,17 +7,19 @@ from lamin_utils import logger
7
7
  from ._init_instance import register_storage_in_instance
8
8
  from .core._hub_core import delete_storage_record
9
9
  from .core._settings import settings
10
- from .core._settings_storage import init_storage
10
+ from .core._settings_storage import StorageSettings, init_storage
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from lamindb_setup.types import UPathStr
14
14
 
15
15
 
16
- def set_managed_storage(root: UPathStr, **fs_kwargs):
16
+ def set_managed_storage(root: UPathStr, host: str | None = None, **fs_kwargs):
17
17
  """Add or switch to another managed storage location.
18
18
 
19
19
  Args:
20
20
  root: `UPathStr` - The new storage root, e.g., an S3 bucket.
21
+ host: `str | None = None` For a shared local storage location, pass a globally unique host identifier, e.g. `"my-institute-cluster-1"`, `"my-server-abcd"`, ...
22
+ Discuss the naming convention with an admin.
21
23
  **fs_kwargs: Additional fsspec arguments for cloud root, e.g., profile.
22
24
 
23
25
  """
@@ -29,6 +31,16 @@ def set_managed_storage(root: UPathStr, **fs_kwargs):
29
31
  raise ValueError(
30
32
  "Can't add additional managed storage locations for instances that aren't managed through the hub."
31
33
  )
34
+
35
+ # we do not just query the instance storage table because
36
+ # we might need some information from the hub
37
+ if not StorageSettings(root).type_is_cloud and host is None:
38
+ host = "unspecified-host"
39
+ logger.warning(
40
+ "setting local storage locations with a single path is deprecated, "
41
+ "use a tuple of (local_root, host) instead"
42
+ )
43
+
32
44
  # here the storage is registered in the hub
33
45
  # hub_record_status="hub-record-created" if a new record is created
34
46
  # "hub-record-retrieved" if the storage is in the hub already
@@ -36,13 +48,14 @@ def set_managed_storage(root: UPathStr, **fs_kwargs):
36
48
  root=root,
37
49
  instance_id=settings.instance._id,
38
50
  instance_slug=settings.instance.slug,
39
- register_hub=True,
51
+ register_hub=settings.instance.is_on_hub,
52
+ prevent_register_hub=not settings.instance.is_on_hub,
53
+ region=host,
40
54
  )
41
55
  if ssettings._instance_id is None:
42
56
  raise ValueError(
43
57
  f"Cannot manage storage without write access: {ssettings.root}"
44
58
  )
45
-
46
59
  # here the storage is saved in the instance
47
60
  # if any error happens the record in the hub is deleted
48
61
  # if it was created earlier and not retrieved
@@ -56,8 +56,6 @@ class SetupSettings:
56
56
  _instance_settings_env: str | None = None
57
57
 
58
58
  _auto_connect_path: Path = settings_dir / "auto_connect"
59
- _branch_path: Path = settings_dir / "branch_uid.txt"
60
- _space_path: Path = settings_dir / "space_uid.txt"
61
59
  _private_django_api_path: Path = settings_dir / "private_django_api"
62
60
 
63
61
  _cache_dir: Path | None = None
@@ -95,14 +93,30 @@ class SetupSettings:
95
93
  else:
96
94
  self._auto_connect_path.unlink(missing_ok=True)
97
95
 
96
+ @property
97
+ def _branch_path(self) -> Path:
98
+ return (
99
+ settings_dir
100
+ / f"current-branch--{self.instance.owner}--{self.instance.name}.txt"
101
+ )
102
+
103
+ def _read_branch_idlike_name(self) -> tuple[int | str, str]:
104
+ idlike: str | int = 1
105
+ name: str = "main"
106
+ try:
107
+ branch_path = self._branch_path
108
+ except SystemExit: # in case no instance setup
109
+ return idlike, name
110
+ if branch_path.exists():
111
+ idlike, name = branch_path.read_text().split("\n")
112
+ return idlike, name
113
+
98
114
  @property
99
115
  def branch(self) -> Branch:
100
116
  """Default branch."""
101
117
  from lamindb import Branch
102
118
 
103
- idlike: str | int = 1
104
- if self._branch_path.exists():
105
- idlike = self._branch_path.read_text()
119
+ idlike, _ = self._read_branch_idlike_name()
106
120
  return Branch.get(idlike)
107
121
 
108
122
  @branch.setter
@@ -119,16 +133,34 @@ class SetupSettings:
119
133
  raise DoesNotExist(
120
134
  f"Branch '{value}', please check on the hub UI whether you have the correct `uid` or `name`."
121
135
  )
122
- self._branch_path.write_text(branch_record.uid)
136
+ # we are sure that the current instance is setup because
137
+ # it will error on lamindb import otherwise
138
+ self._branch_path.write_text(f"{branch_record.uid}\n{branch_record.name}")
139
+
140
+ @property
141
+ def _space_path(self) -> Path:
142
+ return (
143
+ settings_dir
144
+ / f"current-space--{self.instance.owner}--{self.instance.name}.txt"
145
+ )
146
+
147
+ def _read_space_idlike_name(self) -> tuple[int | str, str]:
148
+ idlike: str | int = 1
149
+ name: str = "all"
150
+ try:
151
+ space_path = self._space_path
152
+ except SystemExit: # in case no instance setup
153
+ return idlike, name
154
+ if space_path.exists():
155
+ idlike, name = space_path.read_text().split("\n")
156
+ return idlike, name
123
157
 
124
158
  @property
125
159
  def space(self) -> Space:
126
160
  """Default space."""
127
161
  from lamindb import Space
128
162
 
129
- idlike: str | int = 1
130
- if self._space_path.exists():
131
- idlike = self._space_path.read_text()
163
+ idlike, _ = self._read_space_idlike_name()
132
164
  return Space.get(idlike)
133
165
 
134
166
  @space.setter
@@ -145,7 +177,9 @@ class SetupSettings:
145
177
  raise DoesNotExist(
146
178
  f"Space '{value}', please check on the hub UI whether you have the correct `uid` or `name`."
147
179
  )
148
- self._space_path.write_text(space_record.uid)
180
+ # we are sure that the current instance is setup because
181
+ # it will error on lamindb import otherwise
182
+ self._space_path.write_text(f"{space_record.uid}\n{space_record.name}")
149
183
 
150
184
  @property
151
185
  def is_connected(self) -> bool:
@@ -264,8 +298,8 @@ class SetupSettings:
264
298
  repr = ""
265
299
  if self._instance_exists:
266
300
  repr += "Current branch & space:\n"
267
- repr += f" - branch: {self.branch.name}\n"
268
- repr += f" - space: {self.space.name}\n"
301
+ repr += f" - branch: {self._read_branch_idlike_name()[1]}\n"
302
+ repr += f" - space: {self._read_space_idlike_name()[1]}\n"
269
303
  repr += self.instance.__repr__()
270
304
  else:
271
305
  repr += "Current instance: None"
@@ -32,6 +32,8 @@ if TYPE_CHECKING:
32
32
 
33
33
  from ._settings_user import UserSettings
34
34
 
35
+ LOCAL_STORAGE_MESSAGE = "No storage location found in current environment: create one via, e.g., ln.Storage(root='/dir/our_shared_dir', host='our-server-123).save()"
36
+
35
37
 
36
38
  def sanitize_git_repo_url(repo_url: str) -> str:
37
39
  assert repo_url.startswith("https://")
@@ -82,7 +84,7 @@ class InstanceSettings:
82
84
  self._git_repo = None if git_repo is None else sanitize_git_repo_url(git_repo)
83
85
  # local storage
84
86
  self._keep_artifacts_local = keep_artifacts_local
85
- self._storage_local: StorageSettings | None = None
87
+ self._local_storage: StorageSettings | None = None
86
88
  self._is_on_hub = is_on_hub
87
89
  # private, needed for api requests
88
90
  self._api_url = api_url
@@ -151,7 +153,7 @@ class InstanceSettings:
151
153
  except ProgrammingError:
152
154
  logger.error("not able to load Storage registry: please migrate")
153
155
  return None
154
- found = False
156
+ found = []
155
157
  for record in all_local_records:
156
158
  root_path = Path(record.root)
157
159
  if root_path.exists():
@@ -175,18 +177,16 @@ class InstanceSettings:
175
177
  )
176
178
  continue
177
179
  if uid == record.uid:
178
- found = True
179
- break
180
+ found.append(record)
180
181
  if found:
182
+ if len(found) > 1:
183
+ found_display = "\n - ".join([f"{record.root}" for record in found])
184
+ logger.important(f"found locations:\n - {found_display}")
185
+ logger.important(f"defaulting to local storage: {record.root}")
181
186
  return StorageSettings(record.root)
182
187
  elif not mute_warning:
183
- logger.warning(
184
- "none of the registered local storage locations were found:\n "
185
- + "\n ".join(r.root for r in all_local_records)
186
- )
187
- logger.important(
188
- "please register a new local storage location via `ln.settings.storage_local = local_root_path` and re-load/connect the instance"
189
- )
188
+ start = LOCAL_STORAGE_MESSAGE[0].lower()
189
+ logger.warning(f"{start}{LOCAL_STORAGE_MESSAGE[1:]}")
190
190
  return None
191
191
 
192
192
  @property
@@ -209,8 +209,8 @@ class InstanceSettings:
209
209
  return self._storage
210
210
 
211
211
  @property
212
- def storage_local(self) -> StorageSettings:
213
- """An additional local default storage.
212
+ def local_storage(self) -> StorageSettings:
213
+ """An additional local storage location.
214
214
 
215
215
  Is only available if :attr:`keep_artifacts_local` is enabled.
216
216
 
@@ -218,46 +218,73 @@ class InstanceSettings:
218
218
  """
219
219
  if not self._keep_artifacts_local:
220
220
  raise ValueError("`keep_artifacts_local` is not enabled for this instance.")
221
- if self._storage_local is None:
222
- self._storage_local = self._search_local_root()
223
- if self._storage_local is None:
224
- # raise an error, there was a warning just before in search_local_root
225
- raise ValueError()
226
- return self._storage_local
227
-
228
- @storage_local.setter
229
- def storage_local(self, local_root: Path | str):
221
+ if self._local_storage is None:
222
+ self._local_storage = self._search_local_root()
223
+ if self._local_storage is None:
224
+ raise ValueError(LOCAL_STORAGE_MESSAGE)
225
+ return self._local_storage
226
+
227
+ @local_storage.setter
228
+ def local_storage(self, local_root_host: tuple[Path | str, str]):
230
229
  from lamindb_setup._init_instance import register_storage_in_instance
231
230
 
231
+ if not isinstance(local_root_host, tuple):
232
+ local_root = local_root_host
233
+ host = "unspecified-host"
234
+ else:
235
+ local_root, host = local_root_host
236
+
232
237
  local_root = Path(local_root)
233
238
  if not self._keep_artifacts_local:
234
239
  raise ValueError("`keep_artifacts_local` is not enabled for this instance.")
235
- storage_local = self._search_local_root(
240
+ local_storage = self._search_local_root(
236
241
  local_root=StorageSettings(local_root).root_as_str, mute_warning=True
237
242
  )
238
- if storage_local is not None:
243
+ if local_storage is not None:
239
244
  # great, we're merely switching storage location
240
- self._storage_local = storage_local
241
- logger.important(f"defaulting to local storage: {storage_local.root}")
245
+ self._local_storage = local_storage
242
246
  return None
243
- storage_local = self._search_local_root(mute_warning=True)
244
- if storage_local is not None:
247
+ local_storage = self._search_local_root(mute_warning=True)
248
+ if local_storage is not None:
245
249
  if os.getenv("LAMIN_TESTING") == "true":
246
250
  response = "y"
247
251
  else:
248
252
  response = input(
249
253
  "You already configured a local storage root for this instance in this"
250
- f" environment: {self.storage_local.root}\nDo you want to register another one? (y/n)"
254
+ f" environment: {self.local_storage.root}\nDo you want to register another one? (y/n)"
251
255
  )
252
256
  if response != "y":
253
257
  return None
258
+ if host == "unspecified-host":
259
+ logger.warning(
260
+ "setting local_storage with a single path is deprecated for creating storage locations"
261
+ )
262
+ logger.warning(
263
+ "use this instead: ln.Storage(root='/dir/our_shared_dir', host='our-server-123').save()"
264
+ )
254
265
  local_root = UPath(local_root)
255
266
  assert isinstance(local_root, LocalPathClasses)
256
- self._storage_local, _ = init_storage(
257
- local_root, instance_id=self._id, instance_slug=self.slug, register_hub=True
267
+ self._local_storage, _ = init_storage(
268
+ local_root,
269
+ instance_id=self._id,
270
+ instance_slug=self.slug,
271
+ register_hub=True,
272
+ region=host,
258
273
  ) # type: ignore
259
- register_storage_in_instance(self._storage_local) # type: ignore
260
- logger.important(f"defaulting to local storage: {self._storage_local.root}")
274
+ register_storage_in_instance(self._local_storage) # type: ignore
275
+ logger.important(
276
+ f"defaulting to local storage: {self._local_storage.root} on host {host}"
277
+ )
278
+
279
+ @property
280
+ @deprecated("local_storage")
281
+ def storage_local(self) -> StorageSettings:
282
+ return self.local_storage
283
+
284
+ @storage_local.setter
285
+ @deprecated("local_storage")
286
+ def storage_local(self, local_root_host: tuple[Path | str, str]):
287
+ self.local_storage = local_root_host # type: ignore
261
288
 
262
289
  @property
263
290
  def slug(self) -> str:
@@ -87,6 +87,15 @@ def get_storage_region(path: UPathStr) -> str | None:
87
87
  return region
88
88
 
89
89
 
90
+ def get_storage_type(root_as_str: str) -> StorageType:
91
+ import fsspec
92
+
93
+ convert = {"file": "local"}
94
+ # init_storage checks that the root protocol belongs to VALID_PROTOCOLS
95
+ protocol = fsspec.utils.get_protocol(root_as_str)
96
+ return convert.get(protocol, protocol) # type: ignore
97
+
98
+
90
99
  def mark_storage_root(
91
100
  root: UPathStr, uid: str, instance_id: UUID, instance_slug: str
92
101
  ) -> Literal["__marked__"] | str:
@@ -125,6 +134,7 @@ def init_storage(
125
134
  init_instance: bool = False,
126
135
  created_by: UUID | None = None,
127
136
  access_token: str | None = None,
137
+ region: str | None = None,
128
138
  ) -> tuple[
129
139
  StorageSettings,
130
140
  Literal["hub-record-not-created", "hub-record-retrieved", "hub-record-created"],
@@ -145,7 +155,6 @@ def init_storage(
145
155
  # this means we constructed a hosted location of shape s3://bucket-name/uid
146
156
  # within LaminHub
147
157
  assert root_str.endswith(uid)
148
- region = None
149
158
  lamin_env = os.getenv("LAMIN_ENV")
150
159
  if root_str.startswith("create-s3"):
151
160
  if root_str != "create-s3":
@@ -177,6 +186,10 @@ def init_storage(
177
186
  register_hub = (
178
187
  register_hub or ssettings.type_is_cloud
179
188
  ) # default to registering cloud storage
189
+ if register_hub and not ssettings.type_is_cloud and ssettings.host is None:
190
+ raise ValueError(
191
+ "`host` must be set for local storage locations that are registered on the hub"
192
+ )
180
193
  hub_record_status = init_storage_hub(
181
194
  ssettings,
182
195
  auto_populate_instance=not init_instance,
@@ -226,7 +239,10 @@ def init_storage(
226
239
 
227
240
 
228
241
  class StorageSettings:
229
- """Settings for a storage location (local or cloud)."""
242
+ """Settings for a storage location (local or cloud).
243
+
244
+ Do not instantiate this class yourself, use `ln.Storage` instead.
245
+ """
230
246
 
231
247
  def __init__(
232
248
  self,
@@ -385,6 +401,18 @@ class StorageSettings:
385
401
  """`True` if `storage_root` is in cloud, `False` otherwise."""
386
402
  return self.type != "local"
387
403
 
404
+ @property
405
+ def host(self) -> str | None:
406
+ """Host identifier for local storage locations.
407
+
408
+ Is `None` for locations with `type != "local"`.
409
+
410
+ A globally unique user-defined host identifier (cluster, server, laptop, etc.).
411
+ """
412
+ if self.type != "local":
413
+ return None
414
+ return self.region
415
+
388
416
  @property
389
417
  def region(self) -> str | None:
390
418
  """Storage region."""
@@ -398,12 +426,7 @@ class StorageSettings:
398
426
 
399
427
  Returns the protocol as a stringe, e.g., "local", "s3", "gs", "http", "https".
400
428
  """
401
- import fsspec
402
-
403
- convert = {"file": "local"}
404
- # init_storage checks that the root protocol belongs to VALID_PROTOCOLS
405
- protocol = fsspec.utils.get_protocol(self.root_as_str)
406
- return convert.get(protocol, protocol) # type: ignore
429
+ return get_storage_type(self.root_as_str)
407
430
 
408
431
  @property
409
432
  def is_on_hub(self) -> bool:
@@ -928,9 +928,13 @@ def check_storage_is_empty(
928
928
  # if the storage_uid.txt was somehow deleted, we restore a dummy version of it
929
929
  # because we need it to count files in an empty directory on S3 (otherwise permission error)
930
930
  if not (root_upath / STORAGE_UID_FILE_KEY).exists():
931
- (root_upath / STORAGE_UID_FILE_KEY).write_text(
932
- "was deleted, restored during delete"
933
- )
931
+ try:
932
+ (root_upath / STORAGE_UID_FILE_KEY).write_text(
933
+ "was deleted, restored during delete"
934
+ )
935
+ except FileNotFoundError:
936
+ # this can happen if the root is a local non-existing path
937
+ pass
934
938
  if account_for_sqlite_file:
935
939
  n_offset_objects += 1 # the SQLite file is in the ".lamindb" directory
936
940
  if root_string.startswith(HOSTED_BUCKETS):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamindb_setup
3
- Version: 1.7.2
3
+ Version: 1.8.0
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Requires-Python: >=3.10
@@ -1,4 +1,4 @@
1
- lamindb_setup/__init__.py,sha256=rXOlL53oN84rtC715KZqc82f3DmiFQu7G2giORCTMdY,2782
1
+ lamindb_setup/__init__.py,sha256=t86vewd7XZhz-qY1WJCxdsaTAqsjwQXiMF7Y6L2odJQ,2782
2
2
  lamindb_setup/_cache.py,sha256=5o749NuW6zi6uP4rmBtwxg7ifWpAHXVngzC0tEgXLgo,2776
3
3
  lamindb_setup/_check.py,sha256=28PcG8Kp6OpjSLSi1r2boL2Ryeh6xkaCL87HFbjs6GA,129
4
4
  lamindb_setup/_check_setup.py,sha256=bXuqx2HEc178RM7gbKZQ65PEVJFu6uSOKiHAs_xz6GI,5575
@@ -14,7 +14,7 @@ lamindb_setup/_migrate.py,sha256=ya-15sc91i4JmEWI4j00T2892x8hdy2fSW-qz4IdxLs,973
14
14
  lamindb_setup/_register_instance.py,sha256=zmk7UrOF6qED_zTEaTM8GbZurMSP1SwddkRy7rpYmUY,1215
15
15
  lamindb_setup/_schema.py,sha256=b3uzhhWpV5mQtDwhMINc2MabGCnGLESy51ito3yl6Wc,679
16
16
  lamindb_setup/_schema_metadata.py,sha256=yMSuLZc-7iWUV7tETNuKmcDeMW0wtUr5ypKxsKC-m7k,14898
17
- lamindb_setup/_set_managed_storage.py,sha256=9-ECe4dJNgiO5LFrDFhSkpdIK3Zzmh_Hk_WartfTaRw,2005
17
+ lamindb_setup/_set_managed_storage.py,sha256=2muJxbjhZTSgMcyLuLS0PyXlCl5tSYI3BVaSYjrFYkM,2761
18
18
  lamindb_setup/_setup_user.py,sha256=8BSGsW5jfmB4FlkhMt5osYXBbVCdOQeAVATb-oAYxa0,4495
19
19
  lamindb_setup/_silence_loggers.py,sha256=AKF_YcHvX32eGXdsYK8MJlxEaZ-Uo2f6QDRzjKFCtws,1568
20
20
  lamindb_setup/errors.py,sha256=H1UM-bii0U2vPyjprOBgZK4ijZJgzgCViyGWPd8v5yU,1493
@@ -30,11 +30,11 @@ lamindb_setup/core/_hub_core.py,sha256=x77WpaPMr1uA1kJBSvM5JRNyRG0vYIVlxQbhjAdOh
30
30
  lamindb_setup/core/_hub_crud.py,sha256=Jz0d8wFKM1Pv9B9byyUJPlCIMkIzk56Jd-c3Awpm9Xw,5730
31
31
  lamindb_setup/core/_hub_utils.py,sha256=6dyDGyzYFgVfR_lE3VN3CP1jGp98gxPtr-T91PAP05U,2687
32
32
  lamindb_setup/core/_private_django_api.py,sha256=By63l3vIEtK1pq246FhHq3tslxsaTJGKm5VakYluWp4,2656
33
- lamindb_setup/core/_settings.py,sha256=SIXxs0ZCqjNz53PwPYdLoC5sMQ2pjraEBZ3BpA8jGYU,11726
34
- lamindb_setup/core/_settings_instance.py,sha256=nXSOc6qPwamcoD-4W8sIOFD_L-W8VO8e0tT-U0INuYo,19518
33
+ lamindb_setup/core/_settings.py,sha256=0la2eYAHcdMYophheGsgQaD2nJGQrPuX4jMV5GKDiC0,12946
34
+ lamindb_setup/core/_settings_instance.py,sha256=iG4Me-9e9Z4yj3EG3YB3OtkiZ-j-u8R1WPXIeQhMNmw,20484
35
35
  lamindb_setup/core/_settings_load.py,sha256=JWd0_hBy04xjKo-tH4y8C9RkaywjrmoT0PsKzVme0n4,5176
36
36
  lamindb_setup/core/_settings_save.py,sha256=XZx-vow7BT6y3JpRBB2UOJp2vwc7jOGea4wSgOPqjPU,3262
37
- lamindb_setup/core/_settings_storage.py,sha256=AY3OpJd2uOR8nTrJUzESq_sS1P1Uo_y9oqi5_NdcSPQ,16353
37
+ lamindb_setup/core/_settings_storage.py,sha256=wVwDDD51UsJz5gS6juERbWHCdyucP0R2DLaUGhnLUpQ,17079
38
38
  lamindb_setup/core/_settings_store.py,sha256=QmeWIGdIyq7UmjfHiEB_0xRD8hY-8-ZR2WntIKfwTKI,2714
39
39
  lamindb_setup/core/_settings_user.py,sha256=K2a6nQ0fhEiSb9mCY_p6ItNrHZ3J_j7EfO7CjZap9aA,1462
40
40
  lamindb_setup/core/_setup_bionty_sources.py,sha256=ox3X-SHiHa2lNPSWjwZhINypbLacX6kGwH6hVVrSFZc,1505
@@ -43,8 +43,8 @@ lamindb_setup/core/django.py,sha256=dOt1OkUnZeYOo-LTjatQWQFh_MnjRf9IwwvRZhCwdZQ,
43
43
  lamindb_setup/core/exceptions.py,sha256=qjMzqy_uzPA7mCOdnoWnS_fdA6OWbdZGftz-YYplrY0,84
44
44
  lamindb_setup/core/hashing.py,sha256=Y8Uc5uSGTfU6L2R_gb5w8DdHhGRog7RnkK-e9FEMjPY,3680
45
45
  lamindb_setup/core/types.py,sha256=T7NwspfRHgIIpYsXDcApks8jkOlGeGRW-YbVLB7jNIo,67
46
- lamindb_setup/core/upath.py,sha256=tvu178E08VSC7YUNrcDYxri4ODuVtX3BGNhJO8UZf00,34302
47
- lamindb_setup-1.7.2.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
48
- lamindb_setup-1.7.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
49
- lamindb_setup-1.7.2.dist-info/METADATA,sha256=RO5_HhbMpABK27CGooW3cLDubeImzHtltprOJB4sLUQ,1797
50
- lamindb_setup-1.7.2.dist-info/RECORD,,
46
+ lamindb_setup/core/upath.py,sha256=UDPcZaNp3WtZSYrX8hGQ1lq214dBn079bz0FPWFjIbA,34449
47
+ lamindb_setup-1.8.0.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
48
+ lamindb_setup-1.8.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
49
+ lamindb_setup-1.8.0.dist-info/METADATA,sha256=oxlCgEfbGqZ8zUi2aKMyQdCZoVTkngUl1SKM-Dc1mdU,1797
50
+ lamindb_setup-1.8.0.dist-info/RECORD,,