lamin_cli 1.0.7__py2.py3-none-any.whl → 1.2.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.
lamin_cli/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Lamin CLI."""
2
2
 
3
- __version__ = "1.0.7"
3
+ __version__ = "1.2.0"
lamin_cli/__main__.py CHANGED
@@ -1,12 +1,16 @@
1
1
  from __future__ import annotations
2
+
3
+ import inspect
2
4
  import os
3
5
  import sys
6
+ import warnings
4
7
  from collections import OrderedDict
5
- import inspect
6
- from importlib.metadata import PackageNotFoundError, version
7
- from typing import Optional, Mapping
8
8
  from functools import wraps
9
- import warnings
9
+ from importlib.metadata import PackageNotFoundError, version
10
+ from typing import TYPE_CHECKING
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Mapping
10
14
 
11
15
  # https://github.com/ewels/rich-click/issues/19
12
16
  # Otherwise rich-click takes over the formatting.
@@ -18,11 +22,11 @@ if os.environ.get("NO_RICH"):
18
22
 
19
23
  def __init__(
20
24
  self,
21
- name: Optional[str] = None,
22
- commands: Optional[Mapping[str, click.Command]] = None,
25
+ name: str | None = None,
26
+ commands: Mapping[str, click.Command] | None = None,
23
27
  **kwargs,
24
28
  ):
25
- super(OrderedGroup, self).__init__(name, commands, **kwargs)
29
+ super().__init__(name, commands, **kwargs)
26
30
  self.commands = commands or OrderedDict()
27
31
 
28
32
  def list_commands(self, ctx: click.Context) -> Mapping[str, click.Command]:
@@ -77,12 +81,14 @@ else:
77
81
  return wrapper
78
82
 
79
83
 
80
- from click import Command, Context
81
84
  from lamindb_setup._silence_loggers import silence_loggers
82
85
 
83
- from lamin_cli._settings import settings
84
86
  from lamin_cli._cache import cache
85
87
  from lamin_cli._migration import migrate
88
+ from lamin_cli._settings import settings
89
+
90
+ if TYPE_CHECKING:
91
+ from click import Command, Context
86
92
 
87
93
  try:
88
94
  lamindb_version = version("lamindb")
@@ -100,7 +106,7 @@ def main():
100
106
  @main.command()
101
107
  @click.argument("user", type=str, default=None, required=False)
102
108
  @click.option("--key", type=str, default=None, help="The legacy API key.")
103
- def login(user: str, key: Optional[str]):
109
+ def login(user: str, key: str | None):
104
110
  """Log into LaminHub.
105
111
 
106
112
  `lamin login` prompts for your API key unless you set it via environment variable `LAMIN_API_KEY`.
@@ -142,24 +148,25 @@ def schema_to_modules_callback(ctx, param, value):
142
148
  "The --schema option is deprecated and will be removed in a future version."
143
149
  " Please use --modules instead.",
144
150
  DeprecationWarning,
151
+ stacklevel=2,
145
152
  )
146
153
  return value
147
154
 
148
155
 
149
156
  # fmt: off
150
157
  @main.command()
151
- @click.option("--storage", type=str, help="Local directory, s3://bucket_name, gs://bucket_name.") # noqa: E501
152
- @click.option("--db", type=str, default=None, help="Postgres database connection URL, do not pass for SQLite.") # noqa: E501
153
- @click.option("--modules", type=str, default=None, help="Comma-separated string of modules.") # noqa: E501
158
+ @click.option("--storage", type=str, help="Local directory, s3://bucket_name, gs://bucket_name.")
159
+ @click.option("--db", type=str, default=None, help="Postgres database connection URL, do not pass for SQLite.")
160
+ @click.option("--modules", type=str, default=None, help="Comma-separated string of schema modules.")
154
161
  @click.option("--name", type=str, default=None, help="The instance name.")
155
- @click.option("--schema", type=str, default=None, help="[DEPRECATED] Use --modules instead.", callback=schema_to_modules_callback) # noqa: E501
162
+ @click.option("--schema", type=str, default=None, help="[DEPRECATED] Use --modules instead.", callback=schema_to_modules_callback)
156
163
  # fmt: on
157
164
  def init(
158
165
  storage: str,
159
- db: Optional[str],
160
- modules: Optional[str],
161
- name: Optional[str],
162
- schema: Optional[str],
166
+ db: str | None,
167
+ modules: str | None,
168
+ name: str | None,
169
+ schema: str | None,
163
170
  ):
164
171
  """Init an instance."""
165
172
  from lamindb_setup._init_instance import init as init_
@@ -182,7 +189,8 @@ def connect(instance: str):
182
189
  {attr}`~lamindb.setup.core.SetupSettings.auto_connect` to `True` so that you
183
190
  auto-connect in a Python session upon importing `lamindb`.
184
191
  """
185
- from lamindb_setup import settings as settings_, connect as connect_
192
+ from lamindb_setup import connect as connect_
193
+ from lamindb_setup import settings as settings_
186
194
 
187
195
  settings_.auto_connect = True
188
196
  return connect_(instance, _reload_lamindb=False)
@@ -217,7 +225,7 @@ def info(schema: bool):
217
225
  # fmt: off
218
226
  @main.command()
219
227
  @click.argument("instance", type=str, default=None)
220
- @click.option("--force", is_flag=True, default=False, help="Do not ask for confirmation.") # noqa: E501
228
+ @click.option("--force", is_flag=True, default=False, help="Do not ask for confirmation.")
221
229
  # fmt: on
222
230
  def delete(instance: str, force: bool = False):
223
231
  """Delete an entity.
@@ -236,7 +244,7 @@ def delete(instance: str, force: bool = False):
236
244
  @click.option(
237
245
  "--with-env", is_flag=True, help="Also return the environment for a tranform."
238
246
  )
239
- def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
247
+ def load(entity: str, uid: str | None = None, key: str | None = None, with_env: bool = False):
240
248
  """Load a file or folder.
241
249
 
242
250
  Pass a URL, `artifact`, or `transform`. For example:
@@ -252,7 +260,8 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
252
260
  """
253
261
  is_slug = entity.count("/") == 1
254
262
  if is_slug:
255
- from lamindb_setup import settings as settings_, connect
263
+ from lamindb_setup import connect
264
+ from lamindb_setup import settings as settings_
256
265
 
257
266
  # can decide whether we want to actually deprecate
258
267
  # click.echo(
@@ -270,18 +279,31 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
270
279
  @click.argument("entity", type=str)
271
280
  @click.option("--uid", help="The uid for the entity.")
272
281
  @click.option("--key", help="The key for the entity.")
273
- @click.option(
274
- "--with-env", is_flag=True, help="Also return the environment for a tranform."
275
- )
276
- def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
282
+ def get(entity: str, uid: str | None = None, key: str | None = None):
277
283
  """Query metadata about an entity.
278
284
 
279
- Currently only works for artifact & transform and behaves like `lamin load`.
285
+ Currently only works for artifact.
280
286
  """
281
- from lamin_cli._load import load as load_
287
+ import lamindb_setup as ln_setup
282
288
 
283
- click.echo(f"! to load a file or folder, please use: lamin load {entity}")
284
- return load_(entity, uid=uid, key=key, with_env=with_env)
289
+ from ._load import decompose_url
290
+
291
+ if entity.startswith("https://") and "lamin" in entity:
292
+ url = entity
293
+ instance, entity, uid = decompose_url(url)
294
+ elif entity not in {"artifact"}:
295
+ raise SystemExit("Entity has to be a laminhub URL or 'artifact'")
296
+ else:
297
+ instance = ln_setup.settings.instance.slug
298
+
299
+ ln_setup.connect(instance)
300
+ import lamindb as ln
301
+
302
+ if uid is not None:
303
+ artifact = ln.Artifact.get(uid)
304
+ else:
305
+ artifact = ln.Artifact.get(key=key)
306
+ artifact.describe()
285
307
 
286
308
 
287
309
  @main.command()
@@ -315,7 +337,7 @@ def _generate_help():
315
337
  out: dict[str, dict[str, str | None]] = {}
316
338
 
317
339
  def recursive_help(
318
- cmd: Command, parent: Optional[Context] = None, name: tuple[str, ...] = ()
340
+ cmd: Command, parent: Context | None = None, name: tuple[str, ...] = ()
319
341
  ):
320
342
  ctx = click.Context(cmd, info_name=cmd.name, parent=parent)
321
343
  assert cmd.name
lamin_cli/_cache.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  import os
3
4
 
4
5
  if os.environ.get("NO_RICH"):
lamin_cli/_load.py CHANGED
@@ -1,14 +1,15 @@
1
1
  from __future__ import annotations
2
- from typing import Tuple
3
- from lamin_utils import logger
4
- import shutil
2
+
5
3
  import re
4
+ import shutil
6
5
  from pathlib import Path
7
6
 
7
+ from lamin_utils import logger
8
+
8
9
 
9
- def decompose_url(url: str) -> Tuple[str, str, str]:
10
- assert "transform" in url or "artifact" in url
11
- for entity in ["transform", "artifact"]:
10
+ def decompose_url(url: str) -> tuple[str, str, str]:
11
+ assert any(keyword in url for keyword in ["transform", "artifact", "collection"])
12
+ for entity in ["transform", "artifact", "collection"]:
12
13
  if entity in url:
13
14
  break
14
15
  uid = url.split(f"{entity}/")[1]
@@ -16,14 +17,18 @@ def decompose_url(url: str) -> Tuple[str, str, str]:
16
17
  return instance_slug, entity, uid
17
18
 
18
19
 
19
- def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
20
+ def load(
21
+ entity: str, uid: str | None = None, key: str | None = None, with_env: bool = False
22
+ ):
20
23
  import lamindb_setup as ln_setup
21
24
 
22
25
  if entity.startswith("https://") and "lamin" in entity:
23
26
  url = entity
24
27
  instance, entity, uid = decompose_url(url)
25
- elif entity not in {"artifact", "transform"}:
26
- raise SystemExit("Entity has to be a laminhub URL or 'artifact' or 'transform'")
28
+ elif entity not in {"artifact", "transform", "collection"}:
29
+ raise SystemExit(
30
+ "Entity has to be a laminhub URL or 'artifact', 'collection', or 'transform'"
31
+ )
27
32
  else:
28
33
  instance = ln_setup.settings.instance.slug
29
34
 
@@ -42,11 +47,13 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
42
47
  new_content = transform.source_code.replace(
43
48
  "# # transform.name", f"# # {transform.description}"
44
49
  )
45
- elif transform.source_code.startswith("# %% [markdown]\n#\n"):
46
- new_content = transform.source_code.replace(
47
- "# %% [markdown]\n#\n",
48
- f"# %% [markdown]\n# # {transform.description}\n",
49
- )
50
+ elif transform.source_code.startswith("# %% [markdown]"):
51
+ source_code_split = transform.source_code.split("\n")
52
+ if source_code_split[1] == "#":
53
+ source_code_split[1] = f"# # {transform.description}"
54
+ new_content = "\n".join(source_code_split)
55
+ else:
56
+ new_content = transform.source_code
50
57
  else: # R notebook
51
58
  # Pattern to match title only within YAML header section
52
59
  title_pattern = r'^---\n.*?title:\s*"([^"]*)".*?---'
@@ -83,82 +90,103 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
83
90
 
84
91
  query_by_uid = uid is not None
85
92
 
86
- if entity == "transform":
87
- if query_by_uid:
88
- # we don't use .get here because DoesNotExist is hard to catch
89
- # due to private django API
90
- # here full uid is not expected anymore as before
91
- # via ln.Transform.objects.get(uid=uid)
92
- transforms = ln.Transform.objects.filter(uid__startswith=uid)
93
- else:
94
- # if below, we take is_latest=True as the criterion, we might get draft notebooks
95
- # hence, we use source_code__isnull=False and order by created_at instead
96
- transforms = ln.Transform.objects.filter(key=key, source_code__isnull=False)
97
-
98
- if (n_transforms := len(transforms)) == 0:
99
- err_msg = f"uid {uid}" if query_by_uid else f"key={key} and source_code"
100
- raise SystemExit(f"Transform with {err_msg} does not exist.")
101
-
102
- if n_transforms > 1:
103
- transforms = transforms.order_by("-created_at")
104
- transform = transforms.first()
105
-
106
- target_relpath = Path(transform.key)
107
- if len(target_relpath.parents) > 1:
108
- logger.important(
109
- "preserve the folder structure for versioning:"
110
- f" {target_relpath.parent}/"
111
- )
112
- target_relpath.parent.mkdir(parents=True, exist_ok=True)
113
- if target_relpath.exists():
114
- response = input(f"! {target_relpath} exists: replace? (y/n)")
115
- if response != "y":
116
- raise SystemExit("Aborted.")
117
-
118
- if transform.source_code is not None:
119
- if target_relpath.suffix in (".ipynb", ".Rmd", ".qmd"):
120
- script_to_notebook(transform, target_relpath, bump_revision=True)
93
+ match entity:
94
+ case "transform":
95
+ if query_by_uid:
96
+ # we don't use .get here because DoesNotExist is hard to catch
97
+ # due to private django API
98
+ # here full uid is not expected anymore as before
99
+ # via ln.Transform.objects.get(uid=uid)
100
+ transforms = ln.Transform.objects.filter(uid__startswith=uid)
121
101
  else:
122
- target_relpath.write_text(transform.source_code)
123
- else:
124
- raise SystemExit("No source code available for this transform.")
102
+ # if below, we take is_latest=True as the criterion, we might get draft notebooks
103
+ # hence, we use source_code__isnull=False and order by created_at instead
104
+ transforms = ln.Transform.objects.filter(
105
+ key=key, source_code__isnull=False
106
+ )
125
107
 
126
- logger.important(f"{transform.type} is here: {target_relpath}")
108
+ if (n_transforms := len(transforms)) == 0:
109
+ err_msg = f"uid {uid}" if query_by_uid else f"key={key} and source_code"
110
+ raise SystemExit(f"Transform with {err_msg} does not exist.")
127
111
 
128
- if with_env:
129
- ln.settings.track_run_inputs = False
130
- if (
131
- transform.latest_run is not None
132
- and transform.latest_run.environment is not None
133
- ):
134
- filepath_env_cache = transform.latest_run.environment.cache()
135
- target_env_filename = (
136
- target_relpath.parent / f"{target_relpath.stem}__requirements.txt"
112
+ if n_transforms > 1:
113
+ transforms = transforms.order_by("-created_at")
114
+ transform = transforms.first()
115
+
116
+ target_relpath = Path(transform.key)
117
+ if len(target_relpath.parents) > 1:
118
+ logger.important(
119
+ "preserve the folder structure for versioning:"
120
+ f" {target_relpath.parent}/"
137
121
  )
138
- shutil.move(filepath_env_cache, target_env_filename)
139
- logger.important(f"environment is here: {target_env_filename}")
122
+ target_relpath.parent.mkdir(parents=True, exist_ok=True)
123
+ if target_relpath.exists():
124
+ response = input(f"! {target_relpath} exists: replace? (y/n)")
125
+ if response != "y":
126
+ raise SystemExit("Aborted.")
127
+
128
+ if transform.source_code is not None:
129
+ if target_relpath.suffix in (".ipynb", ".Rmd", ".qmd"):
130
+ script_to_notebook(transform, target_relpath, bump_revision=True)
131
+ else:
132
+ target_relpath.write_text(transform.source_code)
140
133
  else:
141
- logger.warning("latest transform run with environment doesn't exist")
134
+ raise SystemExit("No source code available for this transform.")
135
+
136
+ logger.important(f"{transform.type} is here: {target_relpath}")
137
+
138
+ if with_env:
139
+ ln.settings.track_run_inputs = False
140
+ if (
141
+ transform.latest_run is not None
142
+ and transform.latest_run.environment is not None
143
+ ):
144
+ filepath_env_cache = transform.latest_run.environment.cache()
145
+ target_env_filename = (
146
+ target_relpath.parent
147
+ / f"{target_relpath.stem}__requirements.txt"
148
+ )
149
+ shutil.move(filepath_env_cache, target_env_filename)
150
+ logger.important(f"environment is here: {target_env_filename}")
151
+ else:
152
+ logger.warning(
153
+ "latest transform run with environment doesn't exist"
154
+ )
142
155
 
143
- return target_relpath
144
- elif entity == "artifact":
145
- ln.settings.track_run_inputs = False
156
+ return target_relpath
157
+ case "artifact" | "collection":
158
+ ln.settings.track_run_inputs = False
159
+
160
+ EntityClass = ln.Artifact if entity == "artifact" else ln.Collection
146
161
 
147
- if query_by_uid:
148
162
  # we don't use .get here because DoesNotExist is hard to catch
149
163
  # due to private django API
150
- artifacts = ln.Artifact.filter(uid__startswith=uid)
151
- else:
152
- artifacts = ln.Artifact.filter(key=key)
164
+ if query_by_uid:
165
+ entities = EntityClass.filter(uid__startswith=uid)
166
+ else:
167
+ entities = EntityClass.filter(key=key)
153
168
 
154
- if (n_artifacts := len(artifacts)) == 0:
155
- err_msg = f"uid={uid}" if query_by_uid else f"key={key}"
156
- raise SystemExit(f"Artifact with {err_msg} does not exist.")
169
+ if (n_entities := len(entities)) == 0:
170
+ err_msg = f"uid={uid}" if query_by_uid else f"key={key}"
171
+ raise SystemExit(
172
+ f"{entity.capitalize()} with {err_msg} does not exist."
173
+ )
174
+
175
+ if n_entities > 1:
176
+ entities = entities.order_by("-created_at")
157
177
 
158
- if n_artifacts > 1:
159
- artifacts = artifacts.order_by("-created_at")
160
- artifact = artifacts.first()
178
+ entity_obj = entities.first()
179
+ cache_path = entity_obj.cache()
161
180
 
162
- cache_path = artifact.cache()
163
- logger.important(f"artifact is here: {cache_path}")
164
- return cache_path
181
+ # collection gives us a list of paths
182
+ if isinstance(cache_path, list):
183
+ logger.important(f"{entity} paths ({len(cache_path)} files):")
184
+ for i, path in enumerate(cache_path):
185
+ if i < 5 or i >= len(cache_path) - 5:
186
+ logger.important(f" [{i + 1}/{len(cache_path)}] {path}")
187
+ elif i == 5:
188
+ logger.important(f" ... {len(cache_path) - 10} more files ...")
189
+ else:
190
+ logger.important(f"{entity} is here: {cache_path}")
191
+ case _:
192
+ raise AssertionError(f"unknown entity {entity}")
lamin_cli/_migration.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  import os
3
4
  from typing import Optional
4
5
 
@@ -34,9 +35,9 @@ def deploy():
34
35
  @click.option("--end-number", type=str, default=None)
35
36
  @click.option("--start-number", type=str, default=None)
36
37
  def squash(
37
- package_name: Optional[str],
38
- end_number: Optional[str],
39
- start_number: Optional[str],
38
+ package_name: str | None,
39
+ end_number: str | None,
40
+ start_number: str | None,
40
41
  ):
41
42
  """Squash migrations."""
42
43
  from lamindb_setup._migrate import migrate
lamin_cli/_save.py CHANGED
@@ -1,8 +1,10 @@
1
1
  from __future__ import annotations
2
+
3
+ import re
4
+ import sys
2
5
  from pathlib import Path
3
- from typing import Union
6
+
4
7
  from lamin_utils import logger
5
- import re
6
8
 
7
9
 
8
10
  def parse_uid_from_code(content: str, suffix: str) -> str | None:
@@ -41,7 +43,7 @@ def parse_uid_from_code(content: str, suffix: str) -> str | None:
41
43
 
42
44
 
43
45
  def save_from_filepath_cli(
44
- filepath: Union[str, Path],
46
+ filepath: str | Path,
45
47
  key: str | None,
46
48
  description: str | None,
47
49
  registry: str | None,
@@ -57,13 +59,16 @@ def save_from_filepath_cli(
57
59
  ln_setup.settings.auto_connect = True
58
60
 
59
61
  import lamindb as ln
62
+
63
+ if not ln.setup.core.django.IS_SETUP:
64
+ sys.exit(-1)
60
65
  from lamindb._finish import save_context_core
61
66
 
62
67
  ln_setup.settings.auto_connect = auto_connect_state
63
68
 
64
69
  suffixes_transform = {
65
- "py": set([".py", ".ipynb"]),
66
- "R": set([".R", ".qmd", ".Rmd"]),
70
+ "py": {".py", ".ipynb"},
71
+ "R": {".R", ".qmd", ".Rmd"},
67
72
  }
68
73
 
69
74
  if filepath.suffix in {".qmd", ".Rmd"}:
@@ -80,8 +85,8 @@ def save_from_filepath_cli(
80
85
  and filepath.with_suffix(".nb.html").exists()
81
86
  ):
82
87
  raise SystemExit(
83
- f'Please delete one of\n - {filepath.with_suffix(".html")}\n -'
84
- f' {filepath.with_suffix(".nb.html")}'
88
+ f"Please delete one of\n - {filepath.with_suffix('.html')}\n -"
89
+ f" {filepath.with_suffix('.nb.html')}"
85
90
  )
86
91
 
87
92
  if registry is None:
lamin_cli/_settings.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  import os
3
4
 
4
5
  if os.environ.get("NO_RICH"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamin_cli
3
- Version: 1.0.7
3
+ Version: 1.2.0
4
4
  Summary: Lamin CLI.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,12 @@
1
+ lamin_cli/__init__.py,sha256=2kLtbQt2_3KEeiaePHI1brXcTblfz2N7yIGKsKcAtb4,40
2
+ lamin_cli/__main__.py,sha256=a14UZj5xS66nZXdL_dUkU9M5AAWvs5unQ9lHJx1S5fI,10839
3
+ lamin_cli/_cache.py,sha256=oplwE8AcS_9PYptQUZxff2qTIdNFS81clGPkJNWk098,800
4
+ lamin_cli/_load.py,sha256=lMhV9AMkybjvj4VChJE_v7IMy6qGqisFlo40BJUibsA,8087
5
+ lamin_cli/_migration.py,sha256=xQi6mwnpBzY5wcv1-TJhveD7a3XJIlpiYx6Z3AJ1NF0,1063
6
+ lamin_cli/_save.py,sha256=bt873beNgog5naWITjPb61cjy00aeEtIv9lwqQttRGI,5908
7
+ lamin_cli/_settings.py,sha256=O2tecCf5EIZu98ima4DTJujo4KuywckOLgw8c-Ke3dY,1142
8
+ lamin_cli-1.2.0.dist-info/entry_points.txt,sha256=Qms85i9cZPlu-U7RnVZhFsF7vJ9gaLZUFkCjcGcXTpg,49
9
+ lamin_cli-1.2.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
10
+ lamin_cli-1.2.0.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
11
+ lamin_cli-1.2.0.dist-info/METADATA,sha256=22dRlSUzNnNcaapFD-faPqMrNG5Fi9KZLjuHVe06hEc,337
12
+ lamin_cli-1.2.0.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- lamin_cli/__init__.py,sha256=At34nwmlcGUb1vGmsRLVLk2f_sJhCINkEHKoIbl8lHc,40
2
- lamin_cli/__main__.py,sha256=nmGl8kj9iC1ohjy6JTJc00ZAAkzAWAHVLk5AMFrJDXU,10523
3
- lamin_cli/_cache.py,sha256=kW8rqlMwQeOngm9uq2gjzPVl3EBrwh6W2F2AvyBFABY,799
4
- lamin_cli/_load.py,sha256=fOA2lxEWp2l4oOwr_Y7XXDLqbIs9ivF6kBXU7I1eNww,6792
5
- lamin_cli/_migration.py,sha256=KH0aVRs72ej6ieyM49JaQw1SbT8z24H2heTFnWFcgy4,1071
6
- lamin_cli/_save.py,sha256=gig2BNgE0RfWXTVzv8Y1QJ5UA5fRS1xE5en6Dx0EwX8,5872
7
- lamin_cli/_settings.py,sha256=iS37mcQUHKRWxi2sHnAojEI6sWk3w232qwG-GeY2_Qc,1141
8
- lamin_cli-1.0.7.dist-info/entry_points.txt,sha256=Qms85i9cZPlu-U7RnVZhFsF7vJ9gaLZUFkCjcGcXTpg,49
9
- lamin_cli-1.0.7.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
10
- lamin_cli-1.0.7.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
11
- lamin_cli-1.0.7.dist-info/METADATA,sha256=h1HDG-taHw9WZ9fR-g2KcqioTwkKIPwxhm2JxclLOD0,337
12
- lamin_cli-1.0.7.dist-info/RECORD,,