lamin_cli 0.16.2__tar.gz → 0.17.0__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 (27) hide show
  1. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/PKG-INFO +1 -1
  2. lamin_cli-0.17.0/lamin_cli/__init__.py +3 -0
  3. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/lamin_cli/__main__.py +14 -14
  4. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/lamin_cli/_cache.py +1 -1
  5. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/lamin_cli/_get.py +18 -5
  6. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/lamin_cli/_save.py +3 -7
  7. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_cli.py +0 -6
  8. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_save_notebooks.py +42 -6
  9. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_save_scripts.py +6 -6
  10. lamin_cli-0.16.2/lamin_cli/__init__.py +0 -3
  11. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/.github/workflows/doc-changes.yml +0 -0
  12. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/.gitignore +0 -0
  13. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/.pre-commit-config.yaml +0 -0
  14. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/README.md +0 -0
  15. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/lamin_cli/_migration.py +0 -0
  16. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/pyproject.toml +0 -0
  17. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/conftest.py +0 -0
  18. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/notebooks/not-initialized.ipynb +0 -0
  19. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
  20. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
  21. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/scripts/merely-import-lamindb.py +0 -0
  22. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
  23. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/scripts/run-track-and-finish.py +0 -0
  24. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_get.py +0 -0
  25. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_migrate.py +0 -0
  26. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_multi_process.py +0 -0
  27. {lamin_cli-0.16.2 → lamin_cli-0.17.0}/tests/test_save_files.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamin_cli
3
- Version: 0.16.2
3
+ Version: 0.17.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,3 @@
1
+ """Lamin CLI."""
2
+
3
+ __version__ = "0.17.0"
@@ -52,7 +52,7 @@ else:
52
52
  },
53
53
  {
54
54
  "name": "Configuration commands",
55
- "commands": ["register", "cache", "set"],
55
+ "commands": ["cache", "set"],
56
56
  },
57
57
  {
58
58
  "name": "Schema commands",
@@ -72,6 +72,7 @@ else:
72
72
  @wraps(f)
73
73
  def wrapper(*args, **kwargs):
74
74
  return f(*args, **kwargs)
75
+
75
76
  return wrapper
76
77
 
77
78
 
@@ -97,15 +98,22 @@ def main():
97
98
  @main.command()
98
99
  @click.argument("user", type=str)
99
100
  @click.option("--key", type=str, default=None, help="API key")
100
- @click.option("--password", type=str, default=None, help="legacy password")
101
- def login(user: str, key: Optional[str], password: Optional[str]):
102
- """Login using a user email address or handle.
101
+ def login(user: str, key: Optional[str]):
102
+ """Log into LaminHub.
103
+
104
+ Upon logging in the first time, you need to pass your API key via
105
+
106
+ ```
107
+ lamin login myemail@acme.com --key YOUR_API_KEY
108
+ ```
109
+
110
+ You'll find your API key in the top right corner under "Settings".
103
111
 
104
- Examples: `lamin login marge` or `lamin login marge@acme.com`
112
+ After this, you can either use `lamin login myhandle` or `lamin login myemail@acme.com`
105
113
  """
106
114
  from lamindb_setup._setup_user import login
107
115
 
108
- return login(user, key=key, password=password)
116
+ return login(user, key=key)
109
117
 
110
118
 
111
119
  # fmt: off
@@ -202,14 +210,6 @@ def save(filepath: str, key: str, description: str):
202
210
  sys.exit(1)
203
211
 
204
212
 
205
- @main.command()
206
- def register():
207
- """Register an instance on the hub."""
208
- from lamindb_setup._register_instance import register as register_
209
-
210
- return register_()
211
-
212
-
213
213
  main.add_command(cache)
214
214
 
215
215
 
@@ -37,4 +37,4 @@ def get_cache():
37
37
  """Get the cache directory."""
38
38
  from lamindb_setup._cache import get_cache_dir
39
39
 
40
- click.echo(f"The cache directory is {get_cache_dir()}.")
40
+ click.echo(f"The cache directory is {get_cache_dir()}")
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
  from typing import Tuple
3
3
  from lamin_utils import logger
4
4
  import lamindb_setup as ln_setup
5
+ from pathlib import Path
5
6
 
6
7
 
7
8
  def decompose_url(url: str) -> Tuple[str, str, str]:
@@ -25,6 +26,7 @@ def get(url: str):
25
26
  ln_setup.settings.auto_connect = False
26
27
 
27
28
  import lamindb as ln
29
+ from lamindb._finish import script_to_notebook
28
30
 
29
31
  ln_setup.settings.auto_connect = auto_connect
30
32
  ln.connect(instance_slug)
@@ -32,12 +34,23 @@ def get(url: str):
32
34
 
33
35
  if entity == "transform":
34
36
  transform = ln.Transform.get(uid)
35
- filepath_cache = transform._source_code_artifact.cache()
36
37
  target_filename = transform.key
37
- if not target_filename.endswith(transform._source_code_artifact.suffix):
38
- target_filename += transform._source_code_artifact.suffix
39
- filepath_cache.rename(target_filename)
40
- logger.success(f"cached source code of transform {uid} as {target_filename}")
38
+ if transform._source_code_artifact_id is not None:
39
+ # backward compat
40
+ filepath_cache = transform._source_code_artifact.cache()
41
+ if not target_filename.endswith(transform._source_code_artifact.suffix):
42
+ target_filename += transform._source_code_artifact.suffix
43
+ filepath_cache.rename(target_filename)
44
+ elif transform.source_code is not None:
45
+ if transform.key.endswith(".ipynb"):
46
+ script_to_notebook(transform, target_filename)
47
+ else:
48
+ Path(target_filename).write_text(transform.source_code)
49
+ else:
50
+ raise ValueError("No source code available for this transform.")
51
+ logger.success(
52
+ f"downloaded source code of transform {uid} as {target_filename}"
53
+ )
41
54
  elif entity == "artifact":
42
55
  artifact = ln.Artifact.get(uid)
43
56
  cache_path = artifact.cache()
@@ -90,13 +90,10 @@ def save_from_filepath_cli(
90
90
  " in Transform registry. Did you run ln.context.track()?"
91
91
  )
92
92
  return "not-tracked-in-transform-registry"
93
- # refactor this, save_context_core should not depend on transform_family
94
- transform_family = transform.versions
95
93
  else:
96
- # the corresponding transform family in the transform table
97
- transform_family = ln.Transform.filter(uid__startswith=stem_uid).all()
98
- # the specific version
99
- transform = transform_family.filter(version=transform_version).one()
94
+ transform = ln.Transform.get(
95
+ uid__startswith=stem_uid, version=transform_version
96
+ )
100
97
  # latest run of this transform by user
101
98
  run = ln.Run.filter(transform=transform).order_by("-started_at").first()
102
99
  if run.created_by.id != ln_setup.settings.user.id:
@@ -110,6 +107,5 @@ def save_from_filepath_cli(
110
107
  run=run,
111
108
  transform=transform,
112
109
  filepath=filepath,
113
- transform_family=transform_family,
114
110
  from_cli=True,
115
111
  )
@@ -14,9 +14,3 @@ def test_login():
14
14
  "lamin login testuser1 --key cEvcwMJFX4OwbsYVaMt2Os6GxxGgDUlBGILs2RyS"
15
15
  )
16
16
  assert exit_status == 0
17
-
18
- # backward compat
19
- exit_status = os.system(
20
- "lamin login testuser1 --password cEvcwMJFX4OwbsYVaMt2Os6GxxGgDUlBGILs2RyS"
21
- )
22
- assert exit_status == 0
@@ -5,6 +5,7 @@ import nbproject_test
5
5
  import pytest
6
6
  from nbproject.dev import read_notebook, write_notebook
7
7
  from nbclient.exceptions import CellExecutionError
8
+ import json
8
9
  import lamindb as ln
9
10
 
10
11
  notebook_dir = "./sub/lamin-cli/tests/notebooks/"
@@ -62,6 +63,8 @@ def test_save_consecutive():
62
63
  env = os.environ
63
64
  env["LAMIN_TESTING"] = "true"
64
65
 
66
+ assert not Path("./with-title-and-initialized-consecutive.ipynb").exists()
67
+
65
68
  transform = ln.Transform.filter(uid="hlsFXswrJjtt0000").one_or_none()
66
69
  assert transform is None
67
70
 
@@ -92,16 +95,44 @@ def test_save_consecutive():
92
95
  capture_output=True,
93
96
  env=env,
94
97
  )
98
+ print(result.stdout.decode())
99
+ print(result.stderr.decode())
95
100
  assert result.returncode == 0
96
101
 
97
102
  # now, we have the associated artifacts
98
103
  transform = ln.Transform.filter(uid="hlsFXswrJjtt0000").one_or_none()
99
104
  assert transform is not None
100
- assert transform.latest_run.report.path.exists()
101
- assert transform.latest_run.report.path == transform.latest_run.report.path
102
- assert transform._source_code_artifact.hash == "EQrdZpS-fPaz5MKk_g02AA"
105
+ assert (
106
+ transform.source_code
107
+ == """# %% [markdown]
108
+ # # transform.name
109
+
110
+ # %%
111
+ import lamindb as ln
112
+
113
+ # %%
114
+ ln.context.uid = "hlsFXswrJjtt0000"
115
+ ln.context.track()
116
+
117
+ # %%
118
+ print("my consecutive cell")
119
+ """
120
+ )
121
+ assert transform.hash == "fHpHnC_pScmOl3ZR8x5cTQ"
122
+ # below is the test that we can use if store the run repot as `.ipynb`
123
+ # and not as html as we do right now
124
+ assert transform.latest_run.report.suffix == ".html"
125
+ # with open(transform.latest_run.report.path, "r") as f:
126
+ # json_notebook = json.load(f)
127
+ # # test that title is stripped from notebook
128
+ # assert json_notebook["cells"][0] == {
129
+ # "cell_type": "markdown",
130
+ # "metadata": {},
131
+ # "source": [],
132
+ # }
133
+ # testing for the hash of the report makes no sense because it contains timestamps
103
134
  assert transform.latest_run.environment.path.exists()
104
- assert transform._source_code_artifact.path.exists()
135
+ assert transform._source_code_artifact is None
105
136
 
106
137
  # now, assume the user modifies the notebook
107
138
  nb = read_notebook(notebook_path)
@@ -130,9 +161,9 @@ def test_save_consecutive():
130
161
  transform = ln.Transform.get("hlsFXswrJjtt0000")
131
162
  assert transform.latest_run.report.path.exists()
132
163
  assert transform.latest_run.report.path == transform.latest_run.report.path
133
- assert transform._source_code_artifact.hash == "DMVEHVQqmY3ektOg2KtKKA"
164
+ assert transform.hash == "b63gPnGqNWBE0G4G3pOghw"
134
165
  assert transform.latest_run.environment.path.exists()
135
- assert transform._source_code_artifact.path.exists()
166
+ assert transform._source_code_artifact is None
136
167
 
137
168
  # get the the source code via command line
138
169
  result = subprocess.run(
@@ -142,6 +173,11 @@ def test_save_consecutive():
142
173
  capture_output=True,
143
174
  )
144
175
  # print(result.stderr.decode())
176
+ assert Path("./with-title-and-initialized-consecutive.ipynb").exists()
177
+ with open("./with-title-and-initialized-consecutive.ipynb", "r") as f:
178
+ json_notebook = json.load(f)
179
+ print(json_notebook["cells"][0])
180
+ assert json_notebook["cells"][0]["source"] == ["# My test notebook (consecutive)"]
145
181
  assert result.returncode == 0
146
182
 
147
183
  # now, assume the user renames the notebook
@@ -37,9 +37,9 @@ def test_run_save_cache():
37
37
  assert "created Run" in result.stdout.decode()
38
38
 
39
39
  transform = ln.Transform.get("m5uCHTTpJnjQ")
40
- assert transform._source_code_artifact.hash == "Cwk0OPOyUH5nzTiU2ISlDQ"
40
+ assert transform.hash == "Cwk0OPOyUH5nzTiU2ISlDQ"
41
41
  assert transform.latest_run.environment.path.exists()
42
- assert transform._source_code_artifact.path.exists()
42
+ assert transform._source_code_artifact is None
43
43
 
44
44
  # you can rerun the same script
45
45
  result = subprocess.run(
@@ -73,7 +73,7 @@ def test_run_save_cache():
73
73
  content = filepath.read_text() + "\n # edited"
74
74
  filepath.write_text(content)
75
75
 
76
- # re-run the script without commiting
76
+ # re-run the script without committing
77
77
  result = subprocess.run(
78
78
  f"python {filepath}",
79
79
  shell=True,
@@ -101,10 +101,10 @@ def test_run_save_cache():
101
101
  capture_output=True,
102
102
  env=env,
103
103
  )
104
- # print(result.stdout.decode())
105
- # print(result.stderr.decode())
104
+ print(result.stdout.decode())
105
+ print(result.stderr.decode())
106
106
  assert result.returncode == 1
107
- assert "Source code changed, bump version by setting" in result.stderr.decode()
107
+ assert "Source code changed, bump revision by setting" in result.stderr.decode()
108
108
 
109
109
  # try to get the the source code via command line
110
110
  result = subprocess.run(
@@ -1,3 +0,0 @@
1
- """Lamin CLI."""
2
-
3
- __version__ = "0.16.2"
File without changes
File without changes
File without changes
File without changes
File without changes