lamindb_setup 0.79.0__py3-none-any.whl → 0.80.1__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
@@ -33,7 +33,7 @@ Modules & settings:
33
33
 
34
34
  """
35
35
 
36
- __version__ = "0.79.0" # denote a release candidate for 0.1.0 with 0.1rc1
36
+ __version__ = "0.80.1" # denote a release candidate for 0.1.0 with 0.1rc1
37
37
 
38
38
  import os as _os
39
39
  import sys as _sys
@@ -415,9 +415,10 @@ def infer_instance_name(
415
415
  if storage == "create-s3":
416
416
  raise ValueError("pass name to init if storage = 'create-s3'")
417
417
  storage_path = UPath(storage)
418
+ # not sure if name is ever ""
418
419
  if storage_path.name != "":
419
420
  name = storage_path.name
420
421
  else:
421
422
  # dedicated treatment of bucket names
422
- name = storage_path._url.netloc
423
+ name = storage_path.drive
423
424
  return name.lower()
@@ -48,14 +48,14 @@ def load_user(email: str | None = None, handle: str | None = None) -> UserSettin
48
48
 
49
49
 
50
50
  def login(
51
- user: str | None = None, *, key: str | None = None, api_key: str | None = None
51
+ user: str | None = None, *, api_key: str | None = None, key: str | None = None
52
52
  ) -> None:
53
53
  """Log in user.
54
54
 
55
55
  Args:
56
56
  user: handle or email
57
- key: API key
58
- api_key: Beta API key
57
+ api_key: API key
58
+ key: legacy API key
59
59
  """
60
60
  if user is None and api_key is None:
61
61
  if "LAMIN_API_KEY" in os.environ:
@@ -15,9 +15,7 @@ HOSTED_REGIONS = [
15
15
  ]
16
16
  lamin_env = os.getenv("LAMIN_ENV")
17
17
  if lamin_env is None or lamin_env == "prod":
18
- hosted_buckets_list = [f"s3://lamin-{region}" for region in HOSTED_REGIONS]
19
- hosted_buckets_list.append("s3://scverse-spatial-eu-central-1")
20
- HOSTED_BUCKETS = tuple(hosted_buckets_list)
18
+ HOSTED_BUCKETS = tuple([f"s3://lamin-{region}" for region in HOSTED_REGIONS])
21
19
  else:
22
20
  HOSTED_BUCKETS = ("s3://lamin-hosted-test",) # type: ignore
23
21
 
@@ -29,6 +27,11 @@ def _keep_trailing_slash(path_str: str):
29
27
  AWS_CREDENTIALS_EXPIRATION = 11 * 60 * 60 # refresh credentials after 11 hours
30
28
 
31
29
 
30
+ # set anon=True for these buckets if credentials fail for a public bucket
31
+ # to be expanded
32
+ PUBLIC_BUCKETS = ("cellxgene-data-public",)
33
+
34
+
32
35
  class AWSCredentialsManager:
33
36
  def __init__(self):
34
37
  self._credentials_cache = {}
@@ -38,7 +41,15 @@ class AWSCredentialsManager:
38
41
  # this is cached so will be resued with the connection initialized
39
42
  fs = S3FileSystem(cache_regions=True)
40
43
  fs.connect()
41
- self.anon = fs.session._credentials is None
44
+ self.anon: bool = fs.session._credentials is None
45
+ self.anon_public: bool | None = None
46
+ if not self.anon:
47
+ try:
48
+ # use lamindata public bucket for this test
49
+ fs.call_s3("head_bucket", Bucket="lamindata")
50
+ self.anon_public = False
51
+ except Exception as e:
52
+ self.anon_public = isinstance(e, PermissionError)
42
53
 
43
54
  def _find_root(self, path_str: str) -> str | None:
44
55
  roots = self._credentials_cache.keys()
@@ -73,6 +84,8 @@ class AWSCredentialsManager:
73
84
  anon = False
74
85
  else:
75
86
  anon = self.anon
87
+ if not anon and self.anon_public and path.drive in PUBLIC_BUCKETS:
88
+ anon = True
76
89
  connection_options = {"anon": anon}
77
90
  else:
78
91
  connection_options = credentials
@@ -132,7 +145,7 @@ class AWSCredentialsManager:
132
145
  root = "/".join(path.path.rstrip("/").split("/")[:2])
133
146
  else:
134
147
  # write the bucket for everything else
135
- root = path._url.netloc
148
+ root = path.drive
136
149
  root = "s3://" + root
137
150
  self._set_cached_credentials(_keep_trailing_slash(root), credentials)
138
151
 
@@ -10,6 +10,8 @@ from pydantic_settings import BaseSettings
10
10
  from supabase import Client, create_client # type: ignore
11
11
  from supabase.lib.client_options import ClientOptions
12
12
 
13
+ from ._settings_save import save_user_settings
14
+
13
15
 
14
16
  class Connector(BaseSettings):
15
17
  url: str
@@ -129,14 +131,17 @@ def call_with_fallback_auth(
129
131
 
130
132
  for renew_token, fallback_env in [(False, False), (True, False), (False, True)]:
131
133
  try:
132
- if renew_token:
133
- logger.warning(
134
- "renewing expired lamin token: call `lamin login <your-handle>` to avoid this"
135
- )
136
134
  client = connect_hub_with_auth(
137
135
  renew_token=renew_token, fallback_env=fallback_env
138
136
  )
139
137
  result = callable(**kwargs, client=client)
138
+ # we update access_token here
139
+ # because at this point the call has been successfully resolved
140
+ if renew_token:
141
+ from lamindb_setup import settings
142
+
143
+ # here settings.user contains an updated access_token
144
+ save_user_settings(settings.user)
140
145
  break
141
146
  # we use Exception here as the ways in which the client fails upon 401
142
147
  # are not consistent and keep changing
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ import sys
4
5
  from typing import TYPE_CHECKING
5
6
 
6
7
  from appdirs import AppDirs
@@ -161,8 +162,20 @@ class SetupSettings:
161
162
  cache_dir.mkdir(parents=True, exist_ok=True)
162
163
  return cache_dir
163
164
 
165
+ @property
166
+ def paths(self) -> type[SetupPaths]:
167
+ """Convert cloud paths to lamidb local paths.
168
+
169
+ Use `settings.paths.cloud_to_local_no_update`
170
+ or `settings.paths.cloud_to_local`.
171
+ """
172
+ return SetupPaths
173
+
164
174
  def __repr__(self) -> str:
165
175
  """Rich string representation."""
176
+ # do not show current setting representation when building docs
177
+ if "sphinx" in sys.modules:
178
+ return object.__repr__(self)
166
179
  repr = self.user.__repr__()
167
180
  repr += f"\nAuto-connect in Python: {self.auto_connect}\n"
168
181
  repr += f"Private Django API: {self.private_django_api}\n"
@@ -174,6 +187,38 @@ class SetupSettings:
174
187
  return repr
175
188
 
176
189
 
190
+ class SetupPaths:
191
+ """A static class for conversion of cloud paths to lamindb local paths."""
192
+
193
+ @staticmethod
194
+ def cloud_to_local_no_update(
195
+ filepath: UPathStr, cache_key: str | None = None
196
+ ) -> UPath:
197
+ """Local (or local cache) filepath from filepath without synchronization."""
198
+ # cache_key is ignored if filepath is a string or a local path
199
+ # ignores a mere string even if it represents a cloud path
200
+ if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
201
+ # settings is defined further in this file
202
+ local_filepath = settings.cache_dir / (
203
+ filepath.path if cache_key is None else cache_key
204
+ )
205
+ else:
206
+ local_filepath = filepath
207
+ return UPath(local_filepath)
208
+
209
+ @staticmethod
210
+ def cloud_to_local(
211
+ filepath: UPathStr, cache_key: str | None = None, **kwargs
212
+ ) -> UPath:
213
+ """Local (or local cache) filepath from filepath."""
214
+ # cache_key is ignored in cloud_to_local_no_update if filepath is local or a string
215
+ local_filepath = SetupPaths.cloud_to_local_no_update(filepath, cache_key)
216
+ if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
217
+ local_filepath.parent.mkdir(parents=True, exist_ok=True)
218
+ filepath.synchronize(local_filepath, **kwargs)
219
+ return local_filepath
220
+
221
+
177
222
  def get_env_name():
178
223
  if "LAMIN_ENV" in os.environ:
179
224
  return os.environ["LAMIN_ENV"]
@@ -322,24 +322,20 @@ class StorageSettings:
322
322
  self, filepath: UPathStr, cache_key: str | None = None, **kwargs
323
323
  ) -> UPath:
324
324
  """Local (or local cache) filepath from filepath."""
325
- # cache_key is ignored in cloud_to_local_no_update if filepath is local
326
- local_filepath = self.cloud_to_local_no_update(filepath, cache_key)
327
- if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
328
- local_filepath.parent.mkdir(parents=True, exist_ok=True)
329
- filepath.synchronize(local_filepath, **kwargs)
330
- return local_filepath
325
+ from lamindb_setup import settings
326
+
327
+ return settings.paths.cloud_to_local(
328
+ filepath=filepath, cache_key=cache_key, **kwargs
329
+ )
331
330
 
332
331
  def cloud_to_local_no_update(
333
332
  self, filepath: UPathStr, cache_key: str | None = None
334
333
  ) -> UPath:
335
- # cache_key is ignored if filepath is local
336
- if isinstance(filepath, UPath) and not isinstance(filepath, LocalPathClasses):
337
- local_filepath = self.cache_dir / (
338
- filepath.path if cache_key is None else cache_key
339
- )
340
- else:
341
- local_filepath = filepath
342
- return UPath(local_filepath)
334
+ from lamindb_setup import settings
335
+
336
+ return settings.paths.cloud_to_local_no_update(
337
+ filepath=filepath, cache_key=cache_key
338
+ )
343
339
 
344
340
  def key_to_filepath(self, filekey: UPathStr) -> UPath:
345
341
  """Cloud or local filepath from filekey."""
@@ -24,9 +24,9 @@ class UserSettings:
24
24
  email: str | None = None
25
25
  """User email."""
26
26
  api_key: str | None = None
27
- """Beta API key."""
27
+ """API key."""
28
28
  password: str | None = None
29
- """API key or legacy password."""
29
+ """legacy API key or legacy password."""
30
30
  access_token: str | None = None
31
31
  """User access token."""
32
32
  uid: str = "null"
@@ -8,14 +8,14 @@ from collections import defaultdict
8
8
  from datetime import datetime, timezone
9
9
  from functools import partial
10
10
  from itertools import islice
11
- from pathlib import Path, PurePosixPath
11
+ from pathlib import Path, PosixPath, PurePosixPath, WindowsPath
12
12
  from typing import TYPE_CHECKING, Any, Literal
13
13
 
14
14
  import fsspec
15
15
  from lamin_utils import logger
16
16
  from upath import UPath
17
17
  from upath.implementations.cloud import CloudPath, S3Path # keep CloudPath!
18
- from upath.implementations.local import LocalPath, PosixUPath, WindowsUPath
18
+ from upath.implementations.local import LocalPath
19
19
 
20
20
  from ._aws_credentials import HOSTED_BUCKETS, get_aws_credentials_manager
21
21
  from .hashing import HASH_LENGTH, b16_to_b64, hash_md5s_from_dir
@@ -23,7 +23,7 @@ from .hashing import HASH_LENGTH, b16_to_b64, hash_md5s_from_dir
23
23
  if TYPE_CHECKING:
24
24
  from .types import UPathStr
25
25
 
26
- LocalPathClasses = (PosixUPath, WindowsUPath, LocalPath)
26
+ LocalPathClasses = (PosixPath, WindowsPath, LocalPath)
27
27
 
28
28
  # also see https://gist.github.com/securifera/e7eed730cbe1ce43d0c29d7cd2d582f4
29
29
  # ".gz" is not listed here as it typically occurs with another suffix
@@ -291,21 +291,25 @@ def upload_from(
291
291
  callback = ProgressCallback(local_path.name, "uploading")
292
292
  kwargs["callback"] = callback
293
293
 
294
+ source: str | list[str]
295
+ destination: str | list[str]
294
296
  if local_path_is_dir and not create_folder:
295
- source = [f for f in local_path.rglob("*") if f.is_file()]
296
- destination = [str(self / f.relative_to(local_path)) for f in source]
297
- source = [str(f) for f in source] # type: ignore
297
+ source = [f.as_posix() for f in local_path.rglob("*") if f.is_file()]
298
+ destination = fsspec.utils.other_paths(
299
+ source, self.as_posix(), exists=False, flatten=False
300
+ )
298
301
  else:
299
- source = str(local_path) # type: ignore
300
- destination = str(self) # type: ignore
302
+ source = local_path.as_posix()
303
+ destination = self.as_posix()
301
304
 
302
305
  # the below lines are to avoid s3fs triggering create_bucket in upload if
303
306
  # dirs are present it allows to avoid permission error
304
307
  # would be easier to just
305
308
  if self.protocol == "s3" and local_path_is_dir and create_folder:
306
- bucket = self._url.netloc
309
+ bucket = self.drive
307
310
  if bucket not in self.fs.dircache:
308
311
  self.fs.dircache[bucket] = [{}]
312
+ assert isinstance(destination, str)
309
313
  if not destination.endswith(TRAILING_SEP): # type: ignore
310
314
  destination += "/"
311
315
  cleanup_cache = True
@@ -399,8 +403,8 @@ def synchronize(
399
403
  callback.set_size(len(files))
400
404
  origin_file_keys = []
401
405
  for file, stat in callback.wrap(files.items()):
402
- file_key = PurePosixPath(file).relative_to(self.path)
403
- origin_file_keys.append(file_key.as_posix())
406
+ file_key = PurePosixPath(file).relative_to(self.path).as_posix()
407
+ origin_file_keys.append(file_key)
404
408
  timestamp = stat[modified_key].timestamp()
405
409
 
406
410
  origin = f"{self.protocol}://{file}"
@@ -615,11 +619,11 @@ def to_url(upath):
615
619
  if upath.protocol != "s3":
616
620
  raise ValueError("The provided UPath must be an S3 path.")
617
621
  key = "/".join(upath.parts[1:])
618
- bucket = upath._url.netloc
622
+ bucket = upath.drive
619
623
  if bucket == "scverse-spatial-eu-central-1":
620
624
  region = "eu-central-1"
621
625
  elif f"s3://{bucket}" not in HOSTED_BUCKETS:
622
- response = upath.fs.call_s3("head_bucket", Bucket=upath._url.netloc)
626
+ response = upath.fs.call_s3("head_bucket", Bucket=bucket)
623
627
  headers = response["ResponseMetadata"]["HTTPHeaders"]
624
628
  region = headers.get("x-amz-bucket-region")
625
629
  else:
@@ -763,13 +767,9 @@ def check_storage_is_empty(
763
767
  if raise_error
764
768
  else "consider deleting them"
765
769
  )
766
- hint = "'_is_initialized'"
767
- if n_offset_objects == 2:
768
- hint += " & SQLite file"
769
- hint += " ignored"
770
770
  message = (
771
- f"Storage {directory_string} contains {n_objects - n_offset_objects} objects "
772
- f"({hint}) - {ask_for_deletion}"
771
+ f"Storage '{directory_string}' contains {n_objects - n_offset_objects} objects"
772
+ f" - {ask_for_deletion}"
773
773
  )
774
774
  if n_diff > 0:
775
775
  if raise_error:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamindb_setup
3
- Version: 0.79.0
3
+ Version: 0.80.1
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Requires-Python: >=3.9
@@ -1,4 +1,4 @@
1
- lamindb_setup/__init__.py,sha256=UEOTdiNVX6I8dLRxhPxeKjfNRyjzd2Kua0notBhVObM,1714
1
+ lamindb_setup/__init__.py,sha256=kc1LSkxZIe6SeFBsho6Xg6WyYxKcsUYoLNgQlQSRnxo,1714
2
2
  lamindb_setup/_cache.py,sha256=1XnM-V_KprbjpgPY7Bg3FYn53Iz_2_fEgcMOaSdKKbg,1332
3
3
  lamindb_setup/_check.py,sha256=28PcG8Kp6OpjSLSi1r2boL2Ryeh6xkaCL87HFbjs6GA,129
4
4
  lamindb_setup/_check_setup.py,sha256=6cSfpmVOSgU7YiVHfJpBTGTQ7rrnwunt1pJT_jkgNM8,3196
@@ -9,39 +9,39 @@ lamindb_setup/_django.py,sha256=DWUTjjVhEViX0S-zIkeqQgKovWqVgWMl4Y0ANwlA3Pw,1505
9
9
  lamindb_setup/_entry_points.py,sha256=Hs2oJQOCTaGUdWn-1mufM6qUZr9W_EJ_Oc3f0_Vc0Yw,616
10
10
  lamindb_setup/_exportdb.py,sha256=43g77-tH-vAlTn8ig1mMD9-KXLKvxUeDLaq0gVu3l-c,2114
11
11
  lamindb_setup/_importdb.py,sha256=yYYShzUajTsR-cTW4CZ-UNDWZY2uE5PAgNbp-wn8Ogc,1874
12
- lamindb_setup/_init_instance.py,sha256=6Db289T2A2464KqW0NsfSKg59zrhfny9RZxBgb9kPVs,14340
12
+ lamindb_setup/_init_instance.py,sha256=zJbkP22h4Yif_VNooL06FFoHqH1EU45CqiLwF8FUaKs,14368
13
13
  lamindb_setup/_migrate.py,sha256=x_b4k4XRfLSD-EEFMc324yK6DIK7goW33wUytbIWlNs,8917
14
14
  lamindb_setup/_register_instance.py,sha256=alQuYp2f8Ct8xvRC1gt8p_HZ0tqCd3gZD3kiPBLPpsI,1269
15
15
  lamindb_setup/_schema.py,sha256=b3uzhhWpV5mQtDwhMINc2MabGCnGLESy51ito3yl6Wc,679
16
16
  lamindb_setup/_schema_metadata.py,sha256=49wDLbhRhatDeADjHOPfQURt65lf_OZ7lob1ZiAT_ac,13773
17
17
  lamindb_setup/_set_managed_storage.py,sha256=4tDxXQMt8Gw028uY3vIQxZQ7qBNXhQMc8saarNK_Z-s,2043
18
- lamindb_setup/_setup_user.py,sha256=LB1MuhMZRpkCJBjvM7U656r1QnYFioJx7QQwxsf-CqY,4584
18
+ lamindb_setup/_setup_user.py,sha256=-g7Xj6510BDyM8kuqAsVBZFwehlhBa_uWBSV1rPeuM8,4586
19
19
  lamindb_setup/_silence_loggers.py,sha256=AKF_YcHvX32eGXdsYK8MJlxEaZ-Uo2f6QDRzjKFCtws,1568
20
20
  lamindb_setup/core/__init__.py,sha256=BxIVMX5HQq8oZ1OuY_saUEJz5Tdd7gaCPngxVu5iou4,417
21
- lamindb_setup/core/_aws_credentials.py,sha256=uKMQO9q42Hnepz8aj3RxwLKDWUJx8pNOYrFnnNh5X40,5325
21
+ lamindb_setup/core/_aws_credentials.py,sha256=E8yanKOq-idaIz5y9D9SazHaYJKX69VLK3pn7jl82do,5815
22
22
  lamindb_setup/core/_aws_storage.py,sha256=nEjeUv4xUVpoV0Lx-zjjmyb9w804bDyaeiM-OqbfwM0,1799
23
23
  lamindb_setup/core/_deprecated.py,sha256=3qxUI1dnDlSeR0BYrv7ucjqRBEojbqotPgpShXs4KF8,2520
24
24
  lamindb_setup/core/_docs.py,sha256=3k-YY-oVaJd_9UIY-LfBg_u8raKOCNfkZQPA73KsUhs,276
25
- lamindb_setup/core/_hub_client.py,sha256=P11Ma0nDsBHlKcnyOmq75dHDzYYJfmfpTePJ-0348Wo,6117
25
+ lamindb_setup/core/_hub_client.py,sha256=cN19XbZmvLCxL_GKdOcKbedNRL7kR47vmLmA--NMv-U,6306
26
26
  lamindb_setup/core/_hub_core.py,sha256=eUxRz9iJj6RA5-MWgQqqZYAU-di5LQDamRZn6t-VOiM,19838
27
27
  lamindb_setup/core/_hub_crud.py,sha256=eZErpq9t1Cp2ULBSi457ekrcqfesw4Y6IJgaqyrINMY,5276
28
28
  lamindb_setup/core/_hub_utils.py,sha256=08NwQsb53-tXa_pr-f0tPTN0FeeVf_i1p3dEbEWD0F4,3016
29
29
  lamindb_setup/core/_private_django_api.py,sha256=KIn43HOhiRjkbTbddyJqv-WNTTa1bAizbM1tWXoXPBg,2869
30
- lamindb_setup/core/_settings.py,sha256=ZIcQ3aLNRsAkoaCmse9QuMc2atDWkiraApZn0ZMOWwQ,6128
30
+ lamindb_setup/core/_settings.py,sha256=mpGsSb98UsBedLsW2RuowZ17EP2tI2XRGPztqrJtrV4,7952
31
31
  lamindb_setup/core/_settings_instance.py,sha256=ajcq9zRNE598tTqyMkMqaEOubVfFeE998DPtbgyzK3A,18801
32
32
  lamindb_setup/core/_settings_load.py,sha256=5OpghcbkrK9KBM_0Iu-61FTI76UbOpPkkJpUittXS-w,4098
33
33
  lamindb_setup/core/_settings_save.py,sha256=rxGxgaK5i9exKqSJERQQyY1WZio20meoQJoYXlVW-1w,3138
34
- lamindb_setup/core/_settings_storage.py,sha256=u9CyOFxtV7M2Cs_L4k3dUVg3_fsl8SqLwBioMu06Acc,12310
34
+ lamindb_setup/core/_settings_storage.py,sha256=15B7taJF1zxJ1_qAb67NuXkTFvO2TRTWMt6KTzDf1mw,11875
35
35
  lamindb_setup/core/_settings_store.py,sha256=WcsgOmgnu9gztcrhp-N4OONNZyxICHV8M0HdJllTaEo,2219
36
- lamindb_setup/core/_settings_user.py,sha256=vmh8-SDJqlF4zRqAH2loS21_TEYWX4tiG-grQys6-0c,1474
36
+ lamindb_setup/core/_settings_user.py,sha256=iz0MqFLKXqm8LYx_CHmr02_oNvYWFLIxKkJLdpS5W08,1476
37
37
  lamindb_setup/core/_setup_bionty_sources.py,sha256=o2L5Ww8TKgSqJtL4cGUcpJwLNYxA9BZgddhCMCu_E2g,3428
38
38
  lamindb_setup/core/cloud_sqlite_locker.py,sha256=i6TrT7HG0lqliPvZTlsZ_uplPaqhPBbabyfeR32SkA8,7107
39
39
  lamindb_setup/core/django.py,sha256=E4U9nUlV2kHd-G5v6iSdFGAAWixlQDxOFwMwOMG9xfw,3864
40
40
  lamindb_setup/core/exceptions.py,sha256=4NpLUNUIfXYVTFX2FvLZF8RW34exk2Vn2X3G4YhnTRg,276
41
41
  lamindb_setup/core/hashing.py,sha256=bkuvZyAuC7-Y_qZumJd_rybF-upJ5J3KxnKiymRUifw,3148
42
42
  lamindb_setup/core/types.py,sha256=zJii2le38BJUmsNVvzDrbzGYr0yaeb-9Rw9IKmsBr3k,523
43
- lamindb_setup/core/upath.py,sha256=EPLLm62q-Y3hZzd-286cynFMttXKDNXNOKL3_QGkeug,27215
44
- lamindb_setup-0.79.0.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
45
- lamindb_setup-0.79.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
46
- lamindb_setup-0.79.0.dist-info/METADATA,sha256=sMW1HnGk3llbrrA1BIvx_bAa6xmnMqTYRjnDTlfaTS4,1743
47
- lamindb_setup-0.79.0.dist-info/RECORD,,
43
+ lamindb_setup/core/upath.py,sha256=q6WvpdXO_-Ajl5qjU4CIf0Q1ZbYxA0Po54LG9iHYn28,27151
44
+ lamindb_setup-0.80.1.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
45
+ lamindb_setup-0.80.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
46
+ lamindb_setup-0.80.1.dist-info/METADATA,sha256=kMZ0UUKGc3sxehsLkXFPedNRYpo_VNNHKA-iu7I5W4I,1743
47
+ lamindb_setup-0.80.1.dist-info/RECORD,,