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.
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/PKG-INFO +1 -1
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/__init__.py +1 -1
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/__main__.py +16 -7
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_save.py +12 -7
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_annotate_files.py +4 -3
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_notebooks.py +4 -8
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.github/workflows/build.yml +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.github/workflows/doc-changes.yml +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.gitignore +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/.pre-commit-config.yaml +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/LICENSE +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/README.md +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_annotate.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_cache.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_delete.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_load.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_migration.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/_settings.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/compute/__init__.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/compute/modal.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/lamin_cli/urls.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/noxfile.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/pyproject.toml +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/conftest.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_create_switch_delete_list_settings.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_load.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_login.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_migrate.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_multi_process.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_parse_uid_from_code.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_annotate_scripts.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/core/test_save_r_code.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/modal/test_modal.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/not-initialized.ipynb +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/merely-import-lamindb.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-and-finish.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track-with-params.py +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track.R +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/run-track.qmd +0 -0
- {lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/scripts/testscript.py +0 -0
|
@@ -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.
|
|
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
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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
|
-
|
|
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(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-consecutive.ipynb
RENAMED
|
File without changes
|
{lamin_cli-1.8.0 → lamin_cli-1.8.2}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|