lamin_cli 1.8.0__tar.gz → 1.8.2__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 (43) hide show
  1. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/PKG-INFO +1 -1
  2. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/__init__.py +1 -1
  3. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/__main__.py +16 -7
  4. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_save.py +12 -7
  5. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_annotate_files.py +4 -3
  6. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_notebooks.py +4 -8
  7. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.github/workflows/build.yml +0 -0
  8. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.github/workflows/doc-changes.yml +0 -0
  9. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.gitignore +0 -0
  10. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.pre-commit-config.yaml +0 -0
  11. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/LICENSE +0 -0
  12. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/README.md +0 -0
  13. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_annotate.py +0 -0
  14. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_cache.py +0 -0
  15. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_delete.py +0 -0
  16. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_load.py +0 -0
  17. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_migration.py +0 -0
  18. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_settings.py +0 -0
  19. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/compute/__init__.py +0 -0
  20. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/compute/modal.py +0 -0
  21. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/urls.py +0 -0
  22. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/noxfile.py +0 -0
  23. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/pyproject.toml +0 -0
  24. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/conftest.py +0 -0
  25. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_create_switch_delete_list_settings.py +0 -0
  26. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_load.py +0 -0
  27. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_login.py +0 -0
  28. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_migrate.py +0 -0
  29. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_multi_process.py +0 -0
  30. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_parse_uid_from_code.py +0 -0
  31. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_annotate_scripts.py +0 -0
  32. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_r_code.py +0 -0
  33. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/modal/test_modal.py +0 -0
  34. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/not-initialized.ipynb +0 -0
  35. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
  36. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
  37. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/merely-import-lamindb.py +0 -0
  38. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
  39. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-and-finish.py +0 -0
  40. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-with-params.py +0 -0
  41. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track.R +0 -0
  42. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track.qmd +0 -0
  43. {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/testscript.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamin_cli
3
- Version: 1.8.0
3
+ Version: 1.8.2
4
4
  Summary: Lamin CLI.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -5,7 +5,7 @@ This is the command line interface for interacting with LaminDB & LaminHub.
5
5
  The interface is defined in `__main__.py`. The root API here is used by LaminR to replicate the CLI functionality.
6
6
  """
7
7
 
8
- __version__ = "1.8.0"
8
+ __version__ = "1.8.2"
9
9
 
10
10
  from lamindb_setup import disconnect, logout
11
11
  from lamindb_setup._connect_instance import _connect_cli as connect
@@ -180,8 +180,9 @@ def init(
180
180
  # fmt: off
181
181
  @main.command()
182
182
  @click.argument("instance", type=str)
183
+ @click.option("--use_proxy_db", is_flag=True, help="Use proxy database connection.")
183
184
  # fmt: on
184
- def connect(instance: str):
185
+ def connect(instance: str, use_proxy_db: bool):
185
186
  """Configure default instance for connections.
186
187
 
187
188
  Python/R sessions and CLI commands will then auto-connect to the configured instance.
@@ -190,7 +191,7 @@ def connect(instance: str):
190
191
 
191
192
  See also: Connect in a Python session via {func}`~lamindb.connect`.
192
193
  """
193
- return connect_(instance)
194
+ return connect_(instance, use_proxy_db=use_proxy_db)
194
195
 
195
196
 
196
197
  @main.command()
@@ -424,13 +425,15 @@ def save(path: str, key: str, description: str, stem_uid: str, project: str, spa
424
425
 
425
426
 
426
427
  @main.command()
428
+ @click.argument("entity", type=str, default=None, required=False)
427
429
  @click.option("--key", type=str, default=None, help="The key of an artifact or transform.")
428
430
  @click.option("--uid", type=str, default=None, help="The uid of an artifact or transform.")
429
431
  @click.option("--project", type=str, default=None, help="A valid project name or uid.")
430
432
  @click.option("--features", multiple=True, help="Feature annotations. Supports: feature=value, feature=val1,val2, or feature=\"val1\",\"val2\"")
431
- @click.option("--registry", type=str, default=None, help="Either 'artifact' or 'transform'. If not passed, chooses based on key suffix.")
432
- def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
433
- """Annotate an artifact or a transform.
433
+ def annotate(entity: str | None, key: str, uid: str, project: str, features: tuple):
434
+ """Annotate an artifact or transform.
435
+
436
+ Entity is either 'artifact' or 'transform'. If not passed, chooses based on key suffix.
434
437
 
435
438
  You can annotate with projects and valid features & values. For example,
436
439
 
@@ -445,11 +448,17 @@ def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
445
448
  from lamin_cli._annotate import _parse_features_list
446
449
  from lamin_cli._save import infer_registry_from_path
447
450
 
448
- if registry is None:
451
+ # once we enable passing the URL as entity, then we don't need to throw this error
452
+ if not ln.setup.settings._instance_exists:
453
+ raise click.ClickException("Not connected to an instance. Please run: lamin connect account/name")
454
+
455
+ if entity is None:
449
456
  if key is not None:
450
457
  registry = infer_registry_from_path(key)
451
458
  else:
452
459
  registry = "artifact"
460
+ else:
461
+ registry = entity
453
462
  if registry == "artifact":
454
463
  model = ln.Artifact
455
464
  else:
@@ -459,7 +468,7 @@ def annotate(key: str, uid: str, project: str, registry: str, features: tuple):
459
468
  if key is not None:
460
469
  artifact = model.get(key=key)
461
470
  elif uid is not None:
462
- artifact = model.get(uid=uid)
471
+ artifact = model.get(uid) # do not use uid=uid, because then no truncated uids would work
463
472
  else:
464
473
  raise ln.errors.InvalidArgument("Either --key or --uid must be provided")
465
474
 
@@ -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":
@@ -156,7 +160,8 @@ def save(
156
160
  logger.important(f"labeled with project: {project_record.name}")
157
161
  if ln.setup.settings.instance.is_remote:
158
162
  slug = ln.setup.settings.instance.slug
159
- logger.important(f"go to: https://lamin.ai/{slug}/artifact/{artifact.uid}")
163
+ ui_url = ln.setup.settings.instance.ui_url
164
+ logger.important(f"go to: {ui_url}/{slug}/artifact/{artifact.uid}")
160
165
  return None
161
166
 
162
167
  if registry == "transform":
@@ -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,
@@ -53,7 +54,7 @@ def test_save_and_annotate_local_file():
53
54
  )
54
55
  print(result.stdout.decode())
55
56
  print(result.stderr.decode())
56
- assert "returning existing artifact with same hash" in result.stdout.decode()
57
+ assert "returning artifact with same hash" in result.stdout.decode()
57
58
  assert "key='mytest'" in result.stdout.decode()
58
59
  assert "storage path:" in result.stdout.decode()
59
60
  assert result.returncode == 0
@@ -79,7 +80,7 @@ def test_save_and_annotate_local_file():
79
80
  )
80
81
  print(result.stdout.decode())
81
82
  print(result.stderr.decode())
82
- assert "returning existing artifact with same hash" in result.stdout.decode()
83
+ assert "returning artifact with same hash" in result.stdout.decode()
83
84
  assert "key='mytest'" in result.stdout.decode()
84
85
  assert "storage path:" in result.stdout.decode()
85
86
  assert result.returncode == 0
@@ -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()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes