lamin_cli 1.7.2__tar.gz → 1.8.1__tar.gz

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.
Files changed (45) hide show
  1. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/PKG-INFO +1 -1
  2. lamin_cli-1.8.1/lamin_cli/__init__.py +18 -0
  3. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/__main__.py +38 -62
  4. lamin_cli-1.8.1/lamin_cli/_delete.py +43 -0
  5. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/_save.py +17 -13
  6. lamin_cli-1.8.1/lamin_cli/_settings.py +96 -0
  7. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/conftest.py +0 -1
  8. lamin_cli-1.7.2/tests/core/test_create_switch_delete_list.py → lamin_cli-1.8.1/tests/core/test_create_switch_delete_list_settings.py +41 -0
  9. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_save_annotate_files.py +2 -1
  10. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_save_notebooks.py +4 -8
  11. lamin_cli-1.7.2/lamin_cli/__init__.py +0 -12
  12. lamin_cli-1.7.2/lamin_cli/_settings.py +0 -62
  13. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/.github/workflows/build.yml +0 -0
  14. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/.github/workflows/doc-changes.yml +0 -0
  15. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/.gitignore +0 -0
  16. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/.pre-commit-config.yaml +0 -0
  17. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/LICENSE +0 -0
  18. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/README.md +0 -0
  19. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/_annotate.py +0 -0
  20. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/_cache.py +0 -0
  21. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/_load.py +0 -0
  22. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/_migration.py +0 -0
  23. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/compute/__init__.py +0 -0
  24. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/compute/modal.py +0 -0
  25. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/lamin_cli/urls.py +0 -0
  26. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/noxfile.py +0 -0
  27. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/pyproject.toml +0 -0
  28. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_load.py +0 -0
  29. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_login.py +0 -0
  30. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_migrate.py +0 -0
  31. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_multi_process.py +0 -0
  32. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_parse_uid_from_code.py +0 -0
  33. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_save_annotate_scripts.py +0 -0
  34. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/core/test_save_r_code.py +0 -0
  35. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/modal/test_modal.py +0 -0
  36. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/notebooks/not-initialized.ipynb +0 -0
  37. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
  38. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
  39. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/merely-import-lamindb.py +0 -0
  40. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
  41. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/run-track-and-finish.py +0 -0
  42. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/run-track-with-params.py +0 -0
  43. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/run-track.R +0 -0
  44. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/run-track.qmd +0 -0
  45. {lamin_cli-1.7.2 → lamin_cli-1.8.1}/tests/scripts/testscript.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamin_cli
3
- Version: 1.7.2
3
+ Version: 1.8.1
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,18 @@
1
+ """Lamin CLI.
2
+
3
+ This is the command line interface for interacting with LaminDB & LaminHub.
4
+
5
+ The interface is defined in `__main__.py`. The root API here is used by LaminR to replicate the CLI functionality.
6
+ """
7
+
8
+ __version__ = "1.8.1"
9
+
10
+ from lamindb_setup import disconnect, logout
11
+ from lamindb_setup._connect_instance import _connect_cli as connect
12
+ from lamindb_setup._init_instance import init
13
+ from lamindb_setup._setup_user import login
14
+
15
+ from ._delete import delete
16
+ from ._save import save
17
+
18
+ __all__ = ["save", "init", "connect", "delete", "login", "disconnect"]
@@ -11,6 +11,7 @@ from importlib.metadata import PackageNotFoundError, version
11
11
  from pathlib import Path
12
12
  from typing import TYPE_CHECKING, Literal
13
13
 
14
+ import lamindb_setup as ln_setup
14
15
  from lamin_utils import logger
15
16
  from lamindb_setup._init_instance import (
16
17
  DOC_DB,
@@ -19,6 +20,13 @@ from lamindb_setup._init_instance import (
19
20
  DOC_STORAGE_ARG,
20
21
  )
21
22
 
23
+ from lamin_cli import connect as connect_
24
+ from lamin_cli import disconnect as disconnect_
25
+ from lamin_cli import init as init_
26
+ from lamin_cli import login as login_
27
+ from lamin_cli import logout as logout_
28
+ from lamin_cli import save as save_
29
+
22
30
  from .urls import decompose_url
23
31
 
24
32
  if TYPE_CHECKING:
@@ -129,16 +137,12 @@ def login(user: str, key: str | None):
129
137
 
130
138
  See also: Login in a Python session via {func}`~lamindb.setup.login`.
131
139
  """
132
- from lamindb_setup._setup_user import login as login_
133
-
134
140
  return login_(user, key=key)
135
141
 
136
142
 
137
143
  @main.command()
138
144
  def logout():
139
145
  """Log out of LaminHub."""
140
- from lamindb_setup import logout as logout_
141
-
142
146
  return logout_()
143
147
 
144
148
 
@@ -170,8 +174,6 @@ def init(
170
174
 
171
175
  See also: Init in a Python session via {func}`~lamindb.setup.init`.
172
176
  """
173
- from lamindb_setup._init_instance import init as init_
174
-
175
177
  return init_(storage=storage, db=db, modules=modules, name=name)
176
178
 
177
179
 
@@ -188,8 +190,7 @@ def connect(instance: str):
188
190
 
189
191
  See also: Connect in a Python session via {func}`~lamindb.connect`.
190
192
  """
191
- from lamindb_setup._connect_instance import _connect_cli
192
- return _connect_cli(instance)
193
+ return connect_(instance)
193
194
 
194
195
 
195
196
  @main.command()
@@ -198,8 +199,6 @@ def disconnect():
198
199
 
199
200
  See also: Disconnect in a Python session via {func}`~lamindb.setup.disconnect`.
200
201
  """
201
- from lamindb_setup import disconnect as disconnect_
202
-
203
202
  return disconnect_()
204
203
 
205
204
 
@@ -211,18 +210,22 @@ def disconnect():
211
210
  def create(entity: Literal["branch"], name: str | None = None):
212
211
  """Create a record for an entity.
213
212
 
214
- Currently only supports creating a branch.
213
+ Currently only supports creating branches and projects.
215
214
 
216
215
  ```
217
216
  lamin create branch --name my_branch
217
+ lamin create project --name my_project
218
218
  ```
219
219
  """
220
- assert entity == "branch", "Currently only supports creating a branch."
221
-
222
- from lamindb.models import Branch
220
+ from lamindb.models import Branch, Project
223
221
 
224
- branch = Branch(name=name).save()
225
- logger.important(f"created branch: {branch.name}")
222
+ if entity == "branch":
223
+ record = Branch(name=name).save()
224
+ elif entity == "project":
225
+ record = Project(name=name).save()
226
+ else:
227
+ raise NotImplementedError(f"Creating {entity} is not implemented.")
228
+ logger.important(f"created {entity}: {record.name}")
226
229
 
227
230
 
228
231
  # fmt: off
@@ -243,9 +246,9 @@ def list_(entity: Literal["branch"], name: str | None = None):
243
246
  from lamindb.models import Branch, Space
244
247
 
245
248
  if entity == "branch":
246
- print(Branch.df())
249
+ print(Branch.to_dataframe())
247
250
  else:
248
- print(Space.df())
251
+ print(Space.to_dataframe())
249
252
 
250
253
 
251
254
  # fmt: off
@@ -303,38 +306,9 @@ def delete(entity: str, name: str | None = None, uid: str | None = None, slug: s
303
306
  lamin delete instance --slug account/name
304
307
  ```
305
308
  """
306
- from lamindb_setup import connect, delete
309
+ from lamin_cli._delete import delete as delete_
307
310
 
308
- # TODO: refactor to abstract getting and deleting across entities
309
- if entity.startswith("https://") and "lamin" in entity:
310
- url = entity
311
- instance, entity, uid = decompose_url(url)
312
- connect(instance)
313
-
314
- if entity == "branch":
315
- assert name is not None, "You have to pass a name for deleting a branch."
316
- from lamindb import Branch
317
-
318
- Branch.get(name=name).delete()
319
- elif entity == "artifact":
320
- assert uid is not None, "You have to pass a uid for deleting an artifact."
321
- from lamindb import Artifact
322
-
323
- Artifact.get(uid).delete()
324
- elif entity == "transform":
325
- assert uid is not None, "You have to pass a uid for deleting an transform."
326
- from lamindb import Transform
327
-
328
- Transform.get(uid).delete()
329
- elif entity == "collection":
330
- assert uid is not None, "You have to pass a uid for deleting an collection."
331
- from lamindb import Collection
332
-
333
- Collection.get(uid).delete()
334
- elif entity == "instance":
335
- return delete(slug, force=force)
336
- else: # backwars compatibility
337
- return delete(entity, force=force)
311
+ return delete_(entity=entity, name=name, uid=uid, slug=slug, force=force)
338
312
 
339
313
 
340
314
  @main.command()
@@ -350,9 +324,9 @@ def load(entity: str, uid: str | None = None, key: str | None = None, with_env:
350
324
  Pass a URL, `artifact`, or `transform`. For example:
351
325
 
352
326
  ```
353
- lamin load https://lamin.ai/account/instance/artifact/e2G7k9EVul4JbfsEYAy5
327
+ lamin load https://lamin.ai/account/instance/artifact/e2G7k9EVul4JbfsE
354
328
  lamin load artifact --key mydatasets/mytable.parquet
355
- lamin load artifact --uid e2G7k9EVul4JbfsEYAy5
329
+ lamin load artifact --uid e2G7k9EVul4JbfsE
356
330
  lamin load transform --key analysis.ipynb
357
331
  lamin load transform --uid Vul4JbfsEYAy5
358
332
  lamin load transform --uid Vul4JbfsEYAy5 --with-env
@@ -370,10 +344,6 @@ def load(entity: str, uid: str | None = None, key: str | None = None, with_env:
370
344
 
371
345
 
372
346
  def _describe(entity: str = "artifact", uid: str | None = None, key: str | None = None):
373
- import lamindb_setup as ln_setup
374
-
375
- from ._load import decompose_url
376
-
377
347
  if entity.startswith("https://") and "lamin" in entity:
378
348
  url = entity
379
349
  instance, entity, uid = decompose_url(url)
@@ -449,20 +419,20 @@ def save(path: str, key: str, description: str, stem_uid: str, project: str, spa
449
419
  other file types and folders as {class}`~lamindb.Artifact`. You can enforce saving a file as
450
420
  an {class}`~lamindb.Artifact` by passing `--registry artifact`.
451
421
  """
452
- from lamin_cli import save as save_
453
-
454
422
  if save_(path=path, key=key, description=description, stem_uid=stem_uid, project=project, space=space, branch=branch, registry=registry) is not None:
455
423
  sys.exit(1)
456
424
 
457
425
 
458
426
  @main.command()
427
+ @click.argument("entity", type=str, default=None, required=False)
459
428
  @click.option("--key", type=str, default=None, help="The key of an artifact or transform.")
460
429
  @click.option("--uid", type=str, default=None, help="The uid of an artifact or transform.")
461
430
  @click.option("--project", type=str, default=None, help="A valid project name or uid.")
462
431
  @click.option("--features", multiple=True, help="Feature annotations. Supports: feature=value, feature=val1,val2, or feature=\"val1\",\"val2\"")
463
- @click.option("--registry", type=str, default=None, help="Either 'artifact' or 'transform'. If not passed, chooses based on key suffix.")
464
- def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
465
- """Annotate an artifact or a transform.
432
+ def annotate(entity: str | None, key: str, uid: str, project: str, features: tuple):
433
+ """Annotate an artifact or transform.
434
+
435
+ Entity is either 'artifact' or 'transform'. If not passed, chooses based on key suffix.
466
436
 
467
437
  You can annotate with projects and valid features & values. For example,
468
438
 
@@ -477,11 +447,17 @@ def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
477
447
  from lamin_cli._annotate import _parse_features_list
478
448
  from lamin_cli._save import infer_registry_from_path
479
449
 
480
- if registry is None:
450
+ # once we enable passing the URL as entity, then we don't need to throw this error
451
+ if not ln.setup.settings._instance_exists:
452
+ raise click.ClickException("Not connected to an instance. Please run: lamin connect account/name")
453
+
454
+ if entity is None:
481
455
  if key is not None:
482
456
  registry = infer_registry_from_path(key)
483
457
  else:
484
458
  registry = "artifact"
459
+ else:
460
+ registry = entity
485
461
  if registry == "artifact":
486
462
  model = ln.Artifact
487
463
  else:
@@ -491,7 +467,7 @@ def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
491
467
  if key is not None:
492
468
  artifact = model.get(key=key)
493
469
  elif uid is not None:
494
- artifact = model.get(uid=uid)
470
+ artifact = model.get(uid) # do not use uid=uid, because then no truncated uids would work
495
471
  else:
496
472
  raise ln.errors.InvalidArgument("Either --key or --uid must be provided")
497
473
 
@@ -0,0 +1,43 @@
1
+ from lamindb_setup import connect
2
+ from lamindb_setup import delete as delete_instance
3
+
4
+ from .urls import decompose_url
5
+
6
+
7
+ def delete(
8
+ entity: str,
9
+ name: str | None = None,
10
+ uid: str | None = None,
11
+ slug: str | None = None,
12
+ force: bool = False,
13
+ ):
14
+ # TODO: refactor to abstract getting and deleting across entities
15
+ if entity.startswith("https://") and "lamin" in entity:
16
+ url = entity
17
+ instance, entity, uid = decompose_url(url)
18
+ connect(instance)
19
+
20
+ if entity == "branch":
21
+ assert name is not None, "You have to pass a name for deleting a branch."
22
+ from lamindb import Branch
23
+
24
+ Branch.get(name=name).delete()
25
+ elif entity == "artifact":
26
+ assert uid is not None, "You have to pass a uid for deleting an artifact."
27
+ from lamindb import Artifact
28
+
29
+ Artifact.get(uid).delete()
30
+ elif entity == "transform":
31
+ assert uid is not None, "You have to pass a uid for deleting an transform."
32
+ from lamindb import Transform
33
+
34
+ Transform.get(uid).delete()
35
+ elif entity == "collection":
36
+ assert uid is not None, "You have to pass a uid for deleting an collection."
37
+ from lamindb import Collection
38
+
39
+ Collection.get(uid).delete()
40
+ elif entity == "instance":
41
+ return delete_instance(slug, force=force)
42
+ else: # backwards compatibility
43
+ return delete_instance(entity, force=force)
@@ -73,13 +73,13 @@ def parse_title_r_notebook(content: str) -> str | None:
73
73
 
74
74
  def save(
75
75
  path: Path | str,
76
- key: str | None,
77
- description: str | None,
78
- stem_uid: str | None,
79
- project: str | None,
80
- space: str | None,
81
- branch: str | None,
82
- registry: str | None,
76
+ key: str | None = None,
77
+ description: str | None = None,
78
+ stem_uid: str | None = None,
79
+ project: str | None = None,
80
+ space: str | None = None,
81
+ branch: str | None = None,
82
+ registry: str | None = None,
83
83
  ) -> str | None:
84
84
  import lamindb as ln
85
85
  from lamindb._finish import save_context_core
@@ -104,12 +104,14 @@ def save(
104
104
  raise ln.errors.InvalidArgument(
105
105
  f"Project '{project}' not found, either create it with `ln.Project(name='...').save()` or fix typos."
106
106
  )
107
+ space_record = None
107
108
  if space is not None:
108
109
  space_record = ln.Space.filter(ln.Q(name=space) | ln.Q(uid=space)).one_or_none()
109
110
  if space_record is None:
110
111
  raise ln.errors.InvalidArgument(
111
112
  f"Space '{space}' not found, either create it on LaminHub or fix typos."
112
113
  )
114
+ branch_record = None
113
115
  if branch is not None:
114
116
  branch_record = ln.Branch.filter(
115
117
  ln.Q(name=branch) | ln.Q(uid=branch)
@@ -141,12 +143,14 @@ def save(
141
143
  logger.error("Please pass a key or description via --key or --description")
142
144
  return "missing-key-or-description"
143
145
 
144
- artifact = ln.Artifact(path, key=key, description=description, revises=revises)
145
- if space is not None:
146
- artifact.space = space_record
147
- if branch is not None:
148
- artifact.branch = branch_record
149
- artifact.save()
146
+ artifact = ln.Artifact(
147
+ path,
148
+ key=key,
149
+ description=description,
150
+ revises=revises,
151
+ branch=branch_record,
152
+ space=space_record,
153
+ ).save()
150
154
  logger.important(f"saved: {artifact}")
151
155
  logger.important(f"storage path: {artifact.path}")
152
156
  if artifact.storage.type == "s3":
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ if os.environ.get("NO_RICH"):
7
+ import click as click
8
+ else:
9
+ import rich_click as click
10
+
11
+
12
+ @click.group(invoke_without_command=True)
13
+ @click.pass_context
14
+ def settings(ctx):
15
+ """Manage settings.
16
+
17
+ Call without subcommands and options to show settings:
18
+
19
+ ```
20
+ lamin settings
21
+ ```
22
+
23
+ Allows to get and set these settings:
24
+
25
+ - `work-dir` → {attr}`~lamindb.setup.core.SetupSettings.work_dir`
26
+ - `private-django-api` → {attr}`~lamindb.setup.core.SetupSettings.private_django_api`
27
+ - `branch` → current branch (use `lamin switch --branch` to change)
28
+ - `space` → current space (use `lamin switch --space` to change)
29
+
30
+ Examples for getting a setting:
31
+
32
+ ```
33
+ lamin settings get work-dir
34
+ lamin settings get branch
35
+ ```
36
+
37
+ Examples for setting the working directory:
38
+
39
+ ```
40
+ lamin settings set work-dir . # set work-dir to current directory
41
+ lamin settings set work-dir ~/my-project # set work-dir to ~/my-project
42
+ lamin settings set work-dir none # unset work-dir
43
+ ```
44
+ """
45
+ if ctx.invoked_subcommand is None:
46
+ from lamindb_setup import settings as settings_
47
+
48
+ click.echo("Configure: see `lamin settings --help`")
49
+ click.echo(settings_)
50
+
51
+
52
+ @settings.command("set")
53
+ @click.argument(
54
+ "setting",
55
+ type=click.Choice(
56
+ ["auto-connect", "private-django-api", "work-dir"], case_sensitive=False
57
+ ),
58
+ )
59
+ @click.argument("value") # No explicit type - let Click handle it
60
+ def set(setting: str, value: str):
61
+ """Set a setting."""
62
+ from lamindb_setup import settings as settings_
63
+
64
+ if setting == "auto-connect":
65
+ settings_.auto_connect = click.BOOL(value)
66
+ if setting == "private-django-api":
67
+ settings_.private_django_api = click.BOOL(value)
68
+ if setting == "work-dir":
69
+ if value.lower() == "none":
70
+ value = None # type: ignore[assignment]
71
+ settings_.work_dir = value
72
+
73
+
74
+ @settings.command("get")
75
+ @click.argument(
76
+ "setting",
77
+ type=click.Choice(
78
+ ["auto-connect", "private-django-api", "space", "branch", "work-dir"],
79
+ case_sensitive=False,
80
+ ),
81
+ )
82
+ def get(setting: str):
83
+ """Get a setting."""
84
+ from lamindb_setup import settings as settings_
85
+
86
+ if setting == "branch":
87
+ _, value = settings_._read_branch_idlike_name()
88
+ elif setting == "space":
89
+ _, value = settings_._read_space_idlike_name()
90
+ elif setting == "work-dir":
91
+ value = settings_.work_dir
92
+ if value is None:
93
+ value = "None"
94
+ else:
95
+ value = getattr(settings_, setting.replace("-", "_"))
96
+ click.echo(value)
@@ -10,7 +10,6 @@ def pytest_sessionstart(session: pytest.Session):
10
10
  storage="./default_storage_cli",
11
11
  name="lamin-cli-unit-tests",
12
12
  )
13
- ln.setup.settings.auto_connect = True
14
13
 
15
14
 
16
15
  def pytest_sessionfinish(session: pytest.Session):
@@ -1,10 +1,16 @@
1
1
  import os
2
2
  import subprocess
3
+ from pathlib import Path
3
4
 
4
5
  import lamindb as ln
5
6
  import lamindb_setup as ln_setup
6
7
 
7
8
 
9
+ def test_create_project():
10
+ exit_status = os.system("lamin create project --name testproject")
11
+ assert exit_status == 0
12
+
13
+
8
14
  def test_branch():
9
15
  exit_status = os.system("lamin switch --branch archive")
10
16
  assert exit_status == 0
@@ -40,3 +46,38 @@ def test_space():
40
46
  exit_status = os.system("lamin switch --space all")
41
47
  assert exit_status == 0
42
48
  assert ln_setup.settings.space.uid == 12 * "a"
49
+
50
+
51
+ def test_work_dir():
52
+ # default work-dir is None
53
+ result = subprocess.run(
54
+ "lamin settings get work-dir",
55
+ capture_output=True,
56
+ text=True,
57
+ shell=True,
58
+ )
59
+ assert result.stdout.strip() == "None"
60
+ assert ln_setup.settings.work_dir is None
61
+ # set work-dir to tmp_path
62
+ this_path = Path(__file__).resolve()
63
+ exit_status = os.system(f"lamin settings set work-dir {this_path.parent}")
64
+ assert exit_status == 0
65
+ result = subprocess.run(
66
+ "lamin settings get work-dir",
67
+ capture_output=True,
68
+ text=True,
69
+ shell=True,
70
+ )
71
+ assert result.stdout.strip() == str(this_path.parent)
72
+ assert ln_setup.settings.work_dir == this_path.parent
73
+ # unset work-dir
74
+ exit_status = os.system("lamin settings set work-dir none")
75
+ assert exit_status == 0
76
+ result = subprocess.run(
77
+ "lamin settings get work-dir",
78
+ capture_output=True,
79
+ text=True,
80
+ shell=True,
81
+ )
82
+ assert result.stdout.strip() == "None"
83
+ assert ln_setup.settings.work_dir is None
@@ -45,7 +45,8 @@ def test_save_and_annotate_local_file():
45
45
  assert artifact.branch == branch
46
46
  assert project in artifact.projects.all()
47
47
 
48
- # test passing the registry and saving the same file
48
+ # test passing the registry and saving the same file on the main branch
49
+ # it should recognize the file on the contrib1 branch
49
50
  result = subprocess.run(
50
51
  f"lamin save {filepath} --key mytest --registry artifact",
51
52
  shell=True,
@@ -94,10 +94,8 @@ def test_save_consecutive_user_passes_uid():
94
94
  env=env,
95
95
  )
96
96
  assert result.returncode == 0
97
- assert (
98
- "loaded Transform('hlsFXswrJjtt0000'), started new Run"
99
- in notebook_path.read_text()
100
- )
97
+ assert "loaded Transform('hlsFXswrJjtt0000'" in notebook_path.read_text()
98
+ assert "started new Run" in notebook_path.read_text()
101
99
 
102
100
  # now let's simulate the interactive use case and use nbproject_test again
103
101
  # use the stem uid instead and it will bump the version
@@ -107,10 +105,8 @@ def test_save_consecutive_user_passes_uid():
107
105
  assert r"ln.track(\"hlsFXswrJjtt\")" in notebook_path.read_text()
108
106
 
109
107
  nbproject_test.execute_notebooks(notebook_path, print_outputs=True)
110
- assert (
111
- "created Transform('hlsFXswrJjtt0001'), started new"
112
- in notebook_path.read_text()
113
- )
108
+ assert "created Transform('hlsFXswrJjtt0001'" in notebook_path.read_text()
109
+ assert "started new Run" in notebook_path.read_text()
114
110
 
115
111
  # now, there is a transform record, but we're missing all artifacts because ln.finish() wasn't called
116
112
  transform = ln.Transform.filter(uid="hlsFXswrJjtt0001").one_or_none()
@@ -1,12 +0,0 @@
1
- """Lamin CLI.
2
-
3
- This is the command line interface for interacting with LaminDB & LaminHub.
4
-
5
- The interface is defined in `__main__.py`. The root API here is used by LaminR to replicate the CLI functionality.
6
- """
7
-
8
- __version__ = "1.7.2"
9
-
10
- from ._save import save
11
-
12
- __all__ = ["save"]
@@ -1,62 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import os
4
-
5
- if os.environ.get("NO_RICH"):
6
- import click as click
7
- else:
8
- import rich_click as click
9
-
10
-
11
- @click.group(invoke_without_command=True)
12
- @click.pass_context
13
- def settings(ctx):
14
- """Manage settings.
15
-
16
- Call without subcommands and options to show settings.
17
- """
18
- if ctx.invoked_subcommand is None:
19
- from lamindb_setup import settings as settings_
20
-
21
- click.echo("Configure: see `lamin settings --help`")
22
- click.echo(settings_)
23
-
24
-
25
- @settings.command("set")
26
- @click.argument(
27
- "setting",
28
- type=click.Choice(["auto-connect", "private-django-api"], case_sensitive=False),
29
- )
30
- @click.argument("value", type=click.BOOL)
31
- def set(setting: str, value: bool):
32
- """Update settings.
33
-
34
- - `auto-connect` → {attr}`~lamindb.setup.core.SetupSettings.auto_connect`
35
- - `private-django-api` → {attr}`~lamindb.setup.core.SetupSettings.private_django_api`
36
- """
37
- from lamindb_setup import settings as settings_
38
-
39
- if setting == "auto-connect":
40
- settings_.auto_connect = value
41
- if setting == "private-django-api":
42
- settings_.private_django_api = value
43
-
44
-
45
- @settings.command("get")
46
- @click.argument(
47
- "setting",
48
- type=click.Choice(
49
- ["auto-connect", "private-django-api", "space", "branch"], case_sensitive=False
50
- ),
51
- )
52
- def get(setting: str):
53
- """Get a setting."""
54
- from lamindb_setup import settings as settings_
55
-
56
- if setting == "branch":
57
- _, value = settings_._read_branch_idlike_name()
58
- elif setting == "space":
59
- _, value = settings_._read_space_idlike_name()
60
- else:
61
- value = getattr(settings_, setting.replace("-", "_"))
62
- click.echo(value)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes