lamindb_setup 0.76.8__py2.py3-none-any.whl → 0.77.0__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,10 +34,10 @@ Modules & settings:
34
34
 
35
35
  """
36
36
 
37
- __version__ = "0.76.8" # denote a release candidate for 0.1.0 with 0.1rc1
37
+ __version__ = "0.77.0" # denote a release candidate for 0.1.0 with 0.1rc1
38
38
 
39
- import sys
40
- from os import name as _os_name
39
+ import os as _os
40
+ import sys as _sys
41
41
 
42
42
  from . import core
43
43
  from ._check_setup import _check_instance_setup
@@ -51,12 +51,11 @@ from ._register_instance import register
51
51
  from ._setup_user import login, logout
52
52
  from .core._settings import settings
53
53
 
54
- dev = core # backward compat
55
- _TESTING = False # used in lamindb tests
54
+ _TESTING = _os.getenv("LAMIN_TESTING") is not None
56
55
 
57
56
  # hide the supabase error in a thread on windows
58
- if _os_name == "nt":
59
- if sys.version_info.minor > 7:
57
+ if _os.name == "nt":
58
+ if _sys.version_info.minor > 7:
60
59
  import threading
61
60
 
62
61
  _original_excepthook = threading.excepthook
@@ -124,7 +124,11 @@ def _connect_instance(
124
124
  if make_hub_request:
125
125
  # the following will return a string if the instance does not exist
126
126
  # on the hub
127
- hub_result = load_instance_from_hub(owner=owner, name=name)
127
+ # do not call hub if the user is anonymous
128
+ if owner != "anonymous":
129
+ hub_result = load_instance_from_hub(owner=owner, name=name)
130
+ else:
131
+ hub_result = "anonymous-user"
128
132
  # if hub_result is not a string, it means it made a request
129
133
  # that successfully returned metadata
130
134
  if not isinstance(hub_result, str):
@@ -155,9 +159,12 @@ def _connect_instance(
155
159
  )
156
160
  check_whether_migrations_in_sync(instance_result["lamindb_version"])
157
161
  else:
158
- message = INSTANCE_NOT_FOUND_MESSAGE.format(
159
- owner=owner, name=name, hub_result=hub_result
160
- )
162
+ if hub_result != "anonymous-user":
163
+ message = INSTANCE_NOT_FOUND_MESSAGE.format(
164
+ owner=owner, name=name, hub_result=hub_result
165
+ )
166
+ else:
167
+ message = "It is not possible to load an anonymous-owned instance from the hub"
161
168
  if settings_file.exists():
162
169
  isettings = load_instance_settings(settings_file)
163
170
  if isettings.is_remote:
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Optional, Union
3
+ import os
4
+ from typing import TYPE_CHECKING, Optional, Union
4
5
 
5
6
  from lamin_utils import logger
6
7
 
@@ -15,8 +16,11 @@ from .core._settings_store import (
15
16
  user_settings_file_handle,
16
17
  )
17
18
 
19
+ if TYPE_CHECKING:
20
+ from lamindb_setup.core._settings_save import UserSettings
18
21
 
19
- def load_user(email: str | None = None, handle: str | None = None) -> str | None:
22
+
23
+ def load_user(email: str | None = None, handle: str | None = None) -> UserSettings:
20
24
  if email is not None:
21
25
  settings_file = user_settings_file_email(email)
22
26
  if handle is not None:
@@ -28,8 +32,8 @@ def load_user(email: str | None = None, handle: str | None = None) -> str | None
28
32
  else:
29
33
  user_settings = load_or_create_user_settings()
30
34
  if email is None:
31
- raise RuntimeError(
32
- "Use your email for your first login in a compute environment. "
35
+ raise SystemExit(
36
+ "Use your email for your first login in a compute environment. "
33
37
  "After that, you can use your handle."
34
38
  )
35
39
  user_settings.email = email
@@ -40,59 +44,68 @@ def load_user(email: str | None = None, handle: str | None = None) -> str | None
40
44
 
41
45
  settings._user_settings = None # this is to refresh a settings instance
42
46
 
43
- return None
47
+ return user_settings
44
48
 
45
49
 
46
50
  def login(
47
- user: str,
48
- *,
49
- key: str | None = None,
50
- password: str | None = None, # for backward compat
51
+ user: str | None = None, *, key: str | None = None, api_key: str | None = None
51
52
  ) -> None:
52
53
  """Log in user.
53
54
 
54
55
  Args:
55
56
  user: handle or email
56
- key: API key or legacy passward
57
- password: Backward compat, will be removed
57
+ key: API key
58
+ api_key: Beta API key
58
59
  """
59
- if "@" in user:
60
- email, handle = user, None
60
+ if user is None and api_key is None:
61
+ if "LAMIN_API_KEY" in os.environ:
62
+ api_key = os.environ["LAMIN_API_KEY"]
63
+ else:
64
+ raise ValueError("Both `user` and `api_key` should not be `None`.")
65
+
66
+ if api_key is None:
67
+ if "@" in user: # type: ignore
68
+ email, handle = user, None
69
+ else:
70
+ email, handle = None, user
71
+ user_settings = load_user(email, handle)
72
+
73
+ if key is not None:
74
+ # within UserSettings, we still call it "password" for a while
75
+ user_settings.password = key
76
+
77
+ if user_settings.email is None:
78
+ raise SystemExit(f"✗ No stored user email, please call: lamin login {user}")
79
+
80
+ if user_settings.password is None:
81
+ raise SystemExit(
82
+ "✗ No stored API key, please call: lamin login <your-email> --key <API-key>"
83
+ )
61
84
  else:
62
- email, handle = None, user
63
- load_user(email, handle)
64
-
65
- user_settings = load_or_create_user_settings()
66
-
67
- if password is not None:
68
- logger.warning(
69
- "please use --key instead of --password, "
70
- "passwords are deprecated and replaced with API keys"
71
- )
72
- key = password
73
-
74
- if key is not None:
75
- # within UserSettings, we still call it "password" for a while
76
- user_settings.password = key
85
+ user_settings = load_or_create_user_settings()
77
86
 
78
- if user_settings.email is None:
79
- raise RuntimeError("No stored user email, please call: lamin login {user}")
87
+ from .core._hub_core import sign_in_hub, sign_in_hub_api_key
80
88
 
81
- if user_settings.password is None:
82
- raise RuntimeError(
83
- "No stored API key, please call: lamin login <your-email> --key <API-key>"
89
+ if api_key is None:
90
+ response = sign_in_hub(
91
+ user_settings.email, # type: ignore
92
+ user_settings.password, # type: ignore
93
+ user_settings.handle,
84
94
  )
95
+ else:
96
+ response = sign_in_hub_api_key(api_key)
85
97
 
86
- from .core._hub_core import sign_in_hub
87
-
88
- response = sign_in_hub(
89
- user_settings.email, user_settings.password, user_settings.handle
90
- )
91
98
  if isinstance(response, Exception):
92
99
  raise response
100
+ elif isinstance(response, str):
101
+ raise SystemExit(f"✗ Unsuccessful login: {response}.")
93
102
  else:
94
103
  user_uuid, user_id, user_handle, user_name, access_token = response
95
- if handle is None:
104
+ if api_key is not None:
105
+ logger.success(
106
+ f"logged in with API key (handle: {user_handle}, uid: {user_id})"
107
+ )
108
+ elif handle is None:
96
109
  logger.success(f"logged in with handle {user_handle} (uid: {user_id})")
97
110
  else:
98
111
  logger.success(f"logged in with email {user_settings.email} (uid: {user_id})")
@@ -101,6 +114,7 @@ def login(
101
114
  user_settings.name = user_name
102
115
  user_settings._uuid = user_uuid
103
116
  user_settings.access_token = access_token
117
+ user_settings.api_key = api_key
104
118
  save_user_settings(user_settings)
105
119
 
106
120
  if settings._instance_exists and _check_instance_setup():
@@ -113,6 +127,8 @@ def login(
113
127
  def logout():
114
128
  if current_user_settings_file().exists():
115
129
  current_user_settings_file().unlink()
130
+ # update user info
131
+ settings._user_settings = None
116
132
  logger.success("logged out")
117
133
  else:
118
134
  logger.important("already logged out")
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import json
3
4
  import os
4
5
  from urllib.request import urlretrieve
5
6
 
@@ -78,7 +79,7 @@ def connect_hub_with_auth(
78
79
 
79
80
  if renew_token:
80
81
  settings.user.access_token = get_access_token(
81
- settings.user.email, settings.user.password
82
+ settings.user.email, settings.user.password, settings.user.api_key
82
83
  )
83
84
  access_token = settings.user.access_token
84
85
  hub.postgrest.auth(access_token)
@@ -87,9 +88,17 @@ def connect_hub_with_auth(
87
88
 
88
89
 
89
90
  # runs ~0.5s
90
- def get_access_token(email: str | None = None, password: str | None = None):
91
+ def get_access_token(
92
+ email: str | None = None, password: str | None = None, api_key: str | None = None
93
+ ):
91
94
  hub = connect_hub()
92
95
  try:
96
+ if api_key is not None:
97
+ auth_response = hub.functions.invoke(
98
+ "create-jwt",
99
+ invoke_options={"body": {"api_key": api_key}},
100
+ )
101
+ return json.loads(auth_response)["accessToken"]
93
102
  auth_response = hub.auth.sign_in_with_password(
94
103
  {
95
104
  "email": email,
@@ -436,10 +436,11 @@ def _sign_in_hub(email: str, password: str, handle: str | None, client: Client):
436
436
  )
437
437
  data = client.table("account").select("*").eq("id", auth.user.id).execute().data
438
438
  if data: # sync data from hub to local cache in case it was updated on the hub
439
- user_uuid = UUID(data[0]["id"])
440
- user_id = data[0]["lnid"]
441
- user_handle = data[0]["handle"]
442
- user_name = data[0]["name"]
439
+ user = data[0]
440
+ user_uuid = UUID(user["id"])
441
+ user_id = user["lnid"]
442
+ user_handle = user["handle"]
443
+ user_name = user["name"]
443
444
  if handle is not None and handle != user_handle:
444
445
  logger.warning(
445
446
  f"using account handle {user_handle} (cached handle was {handle})"
@@ -458,7 +459,7 @@ def _sign_in_hub(email: str, password: str, handle: str | None, client: Client):
458
459
 
459
460
  def sign_in_hub(
460
461
  email: str, password: str, handle: str | None = None
461
- ) -> Exception | tuple[UUID, str, str, str, str]:
462
+ ) -> Exception | str | tuple[UUID, str, str, str, str]:
462
463
  try:
463
464
  result = call_with_fallback(
464
465
  _sign_in_hub, email=email, password=password, handle=handle
@@ -471,3 +472,53 @@ def sign_in_hub(
471
472
  )
472
473
  return exception
473
474
  return result
475
+
476
+
477
+ def _sign_in_hub_api_key(api_key: str, client: Client):
478
+ response = client.functions.invoke(
479
+ "create-jwt",
480
+ invoke_options={"body": {"api_key": api_key}},
481
+ )
482
+ access_token = json.loads(response)["accessToken"]
483
+ # probably need more info here to avoid additional queries
484
+ # like handle, uid etc
485
+ account_id = client.auth._decode_jwt(access_token)["sub"]
486
+ client.postgrest.auth(access_token)
487
+ # normally public.account.id is equal to auth.user.id
488
+ data = client.table("account").select("*").eq("id", account_id).execute().data
489
+ if data:
490
+ user = data[0]
491
+ user_uuid = UUID(user["id"])
492
+ user_id = user["lnid"]
493
+ user_handle = user["handle"]
494
+ user_name = user["name"]
495
+ else:
496
+ logger.error("Invalid API key.")
497
+ return "invalid-api-key"
498
+ return (user_uuid, user_id, user_handle, user_name, access_token)
499
+
500
+
501
+ def sign_in_hub_api_key(
502
+ api_key: str,
503
+ ) -> Exception | str | tuple[UUID, str, str, str, str]:
504
+ try:
505
+ result = call_with_fallback(_sign_in_hub_api_key, api_key=api_key)
506
+ except Exception as exception:
507
+ logger.error(exception)
508
+ logger.error("Could not login. Probably your API key is wrong.")
509
+ return exception
510
+ return result
511
+
512
+
513
+ def _create_api_key(body: dict, client: Client) -> str:
514
+ response = client.functions.invoke(
515
+ "create-api-key",
516
+ invoke_options={"body": body},
517
+ )
518
+ api_key = json.loads(response)["apiKey"]
519
+ return api_key
520
+
521
+
522
+ def create_api_key(body: dict) -> str:
523
+ api_key = call_with_fallback_auth(_create_api_key, body=body)
524
+ return api_key
@@ -71,30 +71,35 @@ def load_user_settings(user_settings_file: Path):
71
71
  return settings
72
72
 
73
73
 
74
+ def _null_to_value(field, value=None):
75
+ return field if field != "null" else value
76
+
77
+
74
78
  def setup_instance_from_store(store: InstanceSettingsStore) -> InstanceSettings:
75
79
  ssettings = StorageSettings(
76
80
  root=store.storage_root,
77
- region=store.storage_region if store.storage_region != "null" else None,
81
+ region=_null_to_value(store.storage_region),
78
82
  )
79
83
  return InstanceSettings(
80
84
  id=UUID(store.id),
81
85
  owner=store.owner,
82
86
  name=store.name,
83
87
  storage=ssettings,
84
- db=store.db if store.db != "null" else None, # type: ignore
85
- schema=store.schema_str if store.schema_str != "null" else None,
86
- git_repo=store.git_repo if store.git_repo != "null" else None,
88
+ db=_null_to_value(store.db),
89
+ schema=_null_to_value(store.schema_str),
90
+ git_repo=_null_to_value(store.git_repo),
87
91
  keep_artifacts_local=store.keep_artifacts_local, # type: ignore
88
92
  )
89
93
 
90
94
 
91
95
  def setup_user_from_store(store: UserSettingsStore) -> UserSettings:
92
96
  settings = UserSettings()
93
- settings.email = store.email
94
- settings.password = store.password if store.password != "null" else None
97
+ settings.email = _null_to_value(store.email)
98
+ settings.password = _null_to_value(store.password)
95
99
  settings.access_token = store.access_token
100
+ settings.api_key = _null_to_value(store.api_key)
96
101
  settings.uid = store.uid
97
- settings.handle = store.handle if store.handle != "null" else "anonymous"
98
- settings.name = store.name if store.name != "null" else None
102
+ settings.handle = _null_to_value(store.handle, value="anonymous")
103
+ settings.name = _null_to_value(store.name)
99
104
  settings._uuid = UUID(store.uuid) if store.uuid != "null" else None
100
105
  return settings
@@ -65,6 +65,7 @@ class UserSettingsStore(BaseSettings):
65
65
  email: str
66
66
  password: str
67
67
  access_token: str
68
+ api_key: Optional[str] = None
68
69
  uid: str
69
70
  uuid: str
70
71
  handle: str
@@ -21,8 +21,10 @@ class UserSettings:
21
21
 
22
22
  handle: str = "anonymous"
23
23
  """Unique handle."""
24
- email: str = None # type: ignore
24
+ email: str | None = None
25
25
  """User email."""
26
+ api_key: str | None = None
27
+ """Beta API key."""
26
28
  password: str | None = None
27
29
  """API key or legacy password."""
28
30
  access_token: str | None = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamindb_setup
3
- Version: 0.76.8
3
+ Version: 0.77.0
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -1,9 +1,9 @@
1
- lamindb_setup/__init__.py,sha256=kQrdnR18O5ztr_aI5pTm9X9hB1RD6aJXYT29cB7kiIM,1542
1
+ lamindb_setup/__init__.py,sha256=si77fb-FM3YtS5mR_apN1fteFqtzFd3fI7j2UREy4XM,1515
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
5
5
  lamindb_setup/_close.py,sha256=cXNwK7QTTyNFt2XTpLnO3KHljJ7ShOcISk95np_dltE,1239
6
- lamindb_setup/_connect_instance.py,sha256=kAZMTP3w5Vgw-pgZDX9RhYl3TKHaxBuTczTVIsy8Xms,16069
6
+ lamindb_setup/_connect_instance.py,sha256=TaY317ufYYAVWoEAfeGI_P8IJDP4AYTcHxA4w0-CIqU,16386
7
7
  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
@@ -14,25 +14,25 @@ lamindb_setup/_register_instance.py,sha256=alQuYp2f8Ct8xvRC1gt8p_HZ0tqCd3gZD3kiP
14
14
  lamindb_setup/_schema.py,sha256=b3uzhhWpV5mQtDwhMINc2MabGCnGLESy51ito3yl6Wc,679
15
15
  lamindb_setup/_schema_metadata.py,sha256=XfKCcpQXoatx4Dm2pflp-mPhZ9tpqjn2Cq4ip3MOFSY,13715
16
16
  lamindb_setup/_set_managed_storage.py,sha256=4tDxXQMt8Gw028uY3vIQxZQ7qBNXhQMc8saarNK_Z-s,2043
17
- lamindb_setup/_setup_user.py,sha256=6Oc7Rke-yRQSZbuntdUAz8QbJ6UuPzYHI9FnYlf_q-A,3670
17
+ lamindb_setup/_setup_user.py,sha256=vvmzotU_6C-fFLIZ85mevdkKMV9qXHsQFIXoXV3GUEk,4395
18
18
  lamindb_setup/_silence_loggers.py,sha256=AKF_YcHvX32eGXdsYK8MJlxEaZ-Uo2f6QDRzjKFCtws,1568
19
19
  lamindb_setup/core/__init__.py,sha256=BxIVMX5HQq8oZ1OuY_saUEJz5Tdd7gaCPngxVu5iou4,417
20
20
  lamindb_setup/core/_aws_credentials.py,sha256=uKMQO9q42Hnepz8aj3RxwLKDWUJx8pNOYrFnnNh5X40,5325
21
21
  lamindb_setup/core/_aws_storage.py,sha256=nEjeUv4xUVpoV0Lx-zjjmyb9w804bDyaeiM-OqbfwM0,1799
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
- lamindb_setup/core/_hub_client.py,sha256=4FcZBIuKhIWT0hggi3fm3bObOz7j7uhMU6bC0-98kgE,5785
25
- lamindb_setup/core/_hub_core.py,sha256=2Ni7vIkUcZw9ryBLgjercvLsdAL8-3xZNmrxyzNCU98,17049
24
+ lamindb_setup/core/_hub_client.py,sha256=nhdF9qYABRzVkDQMFI-Ft4KVZPDJXrZiyHIvAE5e2j4,6103
25
+ lamindb_setup/core/_hub_core.py,sha256=IOH8yI60xYel42aXTk2yYlF5Z2jJPsHFhvn9cguA-FY,18690
26
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
30
  lamindb_setup/core/_settings_instance.py,sha256=QkhBeDrnM86WDq_FL6KwBIkQxW9mqLjwNW7FSBoKXxs,17608
31
- lamindb_setup/core/_settings_load.py,sha256=bRkGgaEnLZmnOlU5ptDoSM-YXzC2l0Cb7RBoBY6VH9k,3717
31
+ lamindb_setup/core/_settings_load.py,sha256=n7-_vg7YfuoMo4wdwwL2hdBjorywTq0GiprsfILWCko,3720
32
32
  lamindb_setup/core/_settings_save.py,sha256=n_tYfb9EBSxwm4LHyPRHJptE5uB8lmHhcRkz1JkAmhg,2781
33
33
  lamindb_setup/core/_settings_storage.py,sha256=jFdoIkSn1gPDDZKjAlgKyrlsHBqZDOvv-UnuUI7aD_4,14249
34
- lamindb_setup/core/_settings_store.py,sha256=VEE8Ff2A7y4j8ksOaa7g48jNaOqe1PBnBjb1PKKGUKU,2115
35
- lamindb_setup/core/_settings_user.py,sha256=P2lC4WDRAFfT-Xq3MlXJ-wMKIHCoGNhMTQfRGIAyUNQ,1344
34
+ lamindb_setup/core/_settings_store.py,sha256=tEpHPEqg58ZMyCZUKRkekQ3VzTByqsRTnWh_esTWUVY,2149
35
+ lamindb_setup/core/_settings_user.py,sha256=N3a3CjZSCs0TW5Q0A_HVUaKBCpb0_82wZMoa5C_YsbA,1390
36
36
  lamindb_setup/core/_setup_bionty_sources.py,sha256=o2L5Ww8TKgSqJtL4cGUcpJwLNYxA9BZgddhCMCu_E2g,3428
37
37
  lamindb_setup/core/cloud_sqlite_locker.py,sha256=reu02M4aE2BT_A5AFqwhv48l91mOMyQ4zTd-hh-wtuU,6922
38
38
  lamindb_setup/core/django.py,sha256=QUQm3zt5QIiD8uv6o9vbSm_bshqiSWzKSkgD3z2eJCg,3542
@@ -40,7 +40,7 @@ lamindb_setup/core/exceptions.py,sha256=eoI7AXgATgDVzgArtN7CUvpaMUC067vsBg5LHCsW
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
42
  lamindb_setup/core/upath.py,sha256=EPLLm62q-Y3hZzd-286cynFMttXKDNXNOKL3_QGkeug,27215
43
- lamindb_setup-0.76.8.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
44
- lamindb_setup-0.76.8.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
45
- lamindb_setup-0.76.8.dist-info/METADATA,sha256=oqDAk3PGTipph7_JezoeXlST0hucIKVreA9VRWUzcBA,1667
46
- lamindb_setup-0.76.8.dist-info/RECORD,,
43
+ lamindb_setup-0.77.0.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
44
+ lamindb_setup-0.77.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
45
+ lamindb_setup-0.77.0.dist-info/METADATA,sha256=n4t0efsUWS3gfVZOGhDWQtL6QpHAEqQJUJskEXg14qE,1667
46
+ lamindb_setup-0.77.0.dist-info/RECORD,,