lamin_cli 0.22.0__tar.gz → 1.0a5__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 (34) hide show
  1. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/.gitignore +1 -11
  2. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/PKG-INFO +2 -2
  3. lamin_cli-1.0a5/lamin_cli/__init__.py +3 -0
  4. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/__main__.py +27 -9
  5. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/_load.py +36 -30
  6. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/_migration.py +1 -1
  7. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/_save.py +15 -36
  8. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/run-track-and-finish.py +2 -2
  9. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_load.py +29 -4
  10. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_migrate.py +7 -7
  11. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_parse_uid_from_code.py +6 -11
  12. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_save_files.py +3 -0
  13. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_save_notebooks.py +5 -11
  14. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_save_scripts.py +18 -3
  15. lamin_cli-0.22.0/lamin_cli/__init__.py +0 -3
  16. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/.github/workflows/doc-changes.yml +0 -0
  17. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/.pre-commit-config.yaml +0 -0
  18. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/LICENSE +0 -0
  19. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/README.md +0 -0
  20. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/_cache.py +0 -0
  21. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/lamin_cli/_settings.py +0 -0
  22. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/pyproject.toml +0 -0
  23. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/conftest.py +0 -0
  24. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/notebooks/not-initialized.ipynb +0 -0
  25. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
  26. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
  27. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/merely-import-lamindb.py +0 -0
  28. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
  29. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/run-track-with-params.py +0 -0
  30. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/run-track.R +0 -0
  31. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/scripts/run-track.qmd +0 -0
  32. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_cli.py +0 -0
  33. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_multi_process.py +0 -0
  34. {lamin_cli-0.22.0 → lamin_cli-1.0a5}/tests/test_save_r_code.py +0 -0
@@ -1,11 +1,5 @@
1
1
  # LaminDB
2
- docs/guide/data-validation.ipynb
3
- docs/guide/knowledge.ipynb
4
- docs/guide/lnschema-bionty.ipynb
5
- docs/guide/lnschema-core.ipynb
6
- docs/paradisi05_laminopathic_nuclei.jpg
7
- lnschema_bionty_docs/
8
- lnschema_core_docs/
2
+ lamindb_docs/
9
3
  _build
10
4
  mydata/
11
5
  lamin-intro/
@@ -202,7 +196,3 @@ _build
202
196
 
203
197
  # Pycharm
204
198
  .idea
205
-
206
- # fred files
207
- docs/guide/insert-some-data-into-frederic-hub.ipynb
208
- docs/guide/insert-data-in-test-user-1-profile.ipynb
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: lamin_cli
3
- Version: 0.22.0
3
+ Version: 1.0a5
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__ = "1.0a5"
@@ -6,6 +6,7 @@ import inspect
6
6
  from importlib.metadata import PackageNotFoundError, version
7
7
  from typing import Optional, Mapping
8
8
  from functools import wraps
9
+ import warnings
9
10
 
10
11
  # https://github.com/ewels/rich-click/issues/19
11
12
  # Otherwise rich-click takes over the formatting.
@@ -135,18 +136,37 @@ def logout():
135
136
  return logout_()
136
137
 
137
138
 
139
+ def schema_to_modules_callback(ctx, param, value):
140
+ if param.name == "schema" and value is not None:
141
+ warnings.warn(
142
+ "The --schema option is deprecated and will be removed in a future version."
143
+ " Please use --modules instead.",
144
+ DeprecationWarning,
145
+ )
146
+ return value
147
+
148
+
138
149
  # fmt: off
139
150
  @main.command()
140
151
  @click.option("--storage", type=str, help="Local directory, s3://bucket_name, gs://bucket_name.") # noqa: E501
141
152
  @click.option("--db", type=str, default=None, help="Postgres database connection URL, do not pass for SQLite.") # noqa: E501
142
- @click.option("--schema", type=str, default=None, help="Comma-separated string of schema modules.") # noqa: E501
153
+ @click.option("--modules", type=str, default=None, help="Comma-separated string of modules.") # noqa: E501
143
154
  @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
144
156
  # fmt: on
145
- def init(storage: str, db: Optional[str], schema: Optional[str], name: Optional[str]):
157
+ def init(
158
+ storage: str,
159
+ db: Optional[str],
160
+ modules: Optional[str],
161
+ name: Optional[str],
162
+ schema: Optional[str],
163
+ ):
146
164
  """Init an instance."""
147
165
  from lamindb_setup._init_instance import init as init_
148
166
 
149
- return init_(storage=storage, db=db, schema=schema, name=name)
167
+ modules = modules if modules is not None else schema
168
+
169
+ return init_(storage=storage, db=db, modules=modules, name=name)
150
170
 
151
171
 
152
172
  # fmt: off
@@ -165,7 +185,7 @@ def connect(instance: str):
165
185
  from lamindb_setup import settings as settings_, connect as connect_
166
186
 
167
187
  settings_.auto_connect = True
168
- return connect_(slug=instance)
188
+ return connect_(slug=instance, _reload_lamindb=False)
169
189
 
170
190
 
171
191
  @main.command()
@@ -180,7 +200,7 @@ def disconnect():
180
200
 
181
201
 
182
202
  @main.command()
183
- @click.option("--schema", is_flag=True, help="View schema.")
203
+ @click.option("--schema", is_flag=True, help="View database schema.")
184
204
  def info(schema: bool):
185
205
  """Show info about current instance."""
186
206
  if schema:
@@ -239,7 +259,7 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
239
259
  # f"! please use: lamin connect {entity}"
240
260
  # )
241
261
  settings_.auto_connect = True
242
- return connect(slug=entity)
262
+ return connect(slug=entity, _reload_lamindb=False)
243
263
  else:
244
264
  from lamin_cli._load import load as load_
245
265
 
@@ -265,9 +285,7 @@ def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
265
285
 
266
286
 
267
287
  @main.command()
268
- @click.argument(
269
- "filepath", type=click.Path(exists=True, dir_okay=False, file_okay=True)
270
- )
288
+ @click.argument("filepath", type=click.Path(exists=True, dir_okay=True, file_okay=True))
271
289
  @click.option("--key", type=str, default=None)
272
290
  @click.option("--description", type=str, default=None)
273
291
  @click.option("--registry", type=str, default=None)
@@ -28,7 +28,7 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
28
28
  instance = ln_setup.settings.instance.slug
29
29
 
30
30
  ln_setup.connect(instance)
31
- from lnschema_core import models as ln
31
+ import lamindb as ln
32
32
 
33
33
  def script_to_notebook(
34
34
  transform: ln.Transform, notebook_path: Path, bump_revision: bool = False
@@ -37,9 +37,16 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
37
37
  from lamin_utils._base62 import increment_base62
38
38
 
39
39
  if notebook_path.suffix == ".ipynb":
40
- new_content = transform.source_code.replace(
41
- "# # transform.name", f"# # {transform.name}"
42
- )
40
+ # below is backward compat
41
+ if "# # transform.name" in transform.source_code:
42
+ new_content = transform.source_code.replace(
43
+ "# # transform.name", f"# # {transform.description}"
44
+ )
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
+ )
43
50
  else: # R notebook
44
51
  # Pattern to match title only within YAML header section
45
52
  title_pattern = r'^---\n.*?title:\s*"([^"]*)".*?---'
@@ -49,16 +56,18 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
49
56
  new_content = transform.source_code
50
57
  if title_match:
51
58
  current_title = title_match.group(1)
52
- if current_title != transform.name:
59
+ if current_title != transform.description:
53
60
  pattern = r'^(---\n.*?title:\s*)"([^"]*)"(.*?---)'
54
- replacement = f'\\1"{transform.name}"\\3'
61
+ replacement = f'\\1"{transform.description}"\\3'
55
62
  new_content = re.sub(
56
63
  pattern,
57
64
  replacement,
58
65
  new_content,
59
66
  flags=re.DOTALL | re.MULTILINE,
60
67
  )
61
- logger.important(f"fixed title: {current_title} → {transform.name}")
68
+ logger.important(
69
+ f"fixed title: {current_title} → {transform.description}"
70
+ )
62
71
  if bump_revision:
63
72
  uid = transform.uid
64
73
  new_uid = f"{uid[:-4]}{increment_base62(uid[-4:])}"
@@ -92,31 +101,29 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
92
101
  transforms = transforms.order_by("-created_at")
93
102
  transform = transforms.first()
94
103
 
95
- target_filename = transform.key
96
- if Path(target_filename).exists():
97
- response = input(f"! {target_filename} exists: replace? (y/n)")
104
+ target_relpath = Path(transform.key)
105
+ if len(target_relpath.parents) > 1:
106
+ logger.important(
107
+ "preserve the folder structure for versioning:"
108
+ f" {target_relpath.parent}/"
109
+ )
110
+ target_relpath.parent.mkdir(parents=True, exist_ok=True)
111
+ if target_relpath.exists():
112
+ response = input(f"! {target_relpath} exists: replace? (y/n)")
98
113
  if response != "y":
99
114
  raise SystemExit("Aborted.")
100
- if transform._source_code_artifact_id is not None: # backward compat
101
- # need lamindb here to have .cache() available
102
- import lamindb as ln
103
115
 
104
- ln.settings.track_run_inputs = False
105
- filepath_cache = transform._source_code_artifact.cache()
106
- if not target_filename.endswith(transform._source_code_artifact.suffix):
107
- target_filename += transform._source_code_artifact.suffix
108
- shutil.move(filepath_cache, target_filename)
109
- elif transform.source_code is not None:
110
- if transform.key.endswith((".ipynb", ".Rmd", ".qmd")):
111
- script_to_notebook(transform, Path(target_filename), bump_revision=True)
116
+ if transform.source_code is not None:
117
+ if target_relpath.suffix in (".ipynb", ".Rmd", ".qmd"):
118
+ script_to_notebook(transform, target_relpath, bump_revision=True)
112
119
  else:
113
- Path(target_filename).write_text(transform.source_code)
120
+ target_relpath.write_text(transform.source_code)
114
121
  else:
115
122
  raise SystemExit("No source code available for this transform.")
116
- logger.important(f"{transform.type} is here: {target_filename}")
117
- if with_env:
118
- import lamindb as ln
119
123
 
124
+ logger.important(f"{transform.type} is here: {target_relpath}")
125
+
126
+ if with_env:
120
127
  ln.settings.track_run_inputs = False
121
128
  if (
122
129
  transform.latest_run is not None
@@ -124,16 +131,15 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
124
131
  ):
125
132
  filepath_env_cache = transform.latest_run.environment.cache()
126
133
  target_env_filename = (
127
- ".".join(target_filename.split(".")[:-1]) + "__requirements.txt"
134
+ target_relpath.parent / f"{target_relpath.stem}__requirements.txt"
128
135
  )
129
136
  shutil.move(filepath_env_cache, target_env_filename)
130
137
  logger.important(f"environment is here: {target_env_filename}")
131
138
  else:
132
139
  logger.warning("latest transform run with environment doesn't exist")
133
- return target_filename
134
- elif entity == "artifact":
135
- import lamindb as ln
136
140
 
141
+ return target_relpath
142
+ elif entity == "artifact":
137
143
  ln.settings.track_run_inputs = False
138
144
 
139
145
  if query_by_uid:
@@ -144,7 +150,7 @@ def load(entity: str, uid: str = None, key: str = None, with_env: bool = False):
144
150
  artifacts = ln.Artifact.filter(key=key)
145
151
 
146
152
  if (n_artifacts := len(artifacts)) == 0:
147
- err_msg = f"uid strating with {uid}" if query_by_uid else f"key={key}"
153
+ err_msg = f"uid={uid}" if query_by_uid else f"key={key}"
148
154
  raise SystemExit(f"Artifact with {err_msg} does not exist.")
149
155
 
150
156
  if n_artifacts > 1:
@@ -10,7 +10,7 @@ else:
10
10
 
11
11
  @click.group()
12
12
  def migrate():
13
- """Manage metadata schema migrations."""
13
+ """Manage database schema migrations."""
14
14
 
15
15
 
16
16
  @migrate.command("create")
@@ -1,43 +1,27 @@
1
1
  from __future__ import annotations
2
2
  from pathlib import Path
3
3
  from typing import Union
4
- import lamindb_setup as ln_setup
5
4
  from lamin_utils import logger
6
5
  import re
7
6
 
8
7
 
9
- def parse_uid_from_code(
10
- content: str, suffix: str
11
- ) -> tuple[str | None, str | None, str | None]:
8
+ def parse_uid_from_code(content: str, suffix: str) -> str | None:
12
9
  if suffix == ".py":
13
10
  track_pattern = re.compile(
14
11
  r'ln\.track\(\s*(?:transform\s*=\s*)?(["\'])([a-zA-Z0-9]{16})\1'
15
12
  )
16
- # backward compat
17
13
  uid_pattern = re.compile(r'\.context\.uid\s*=\s*["\']([^"\']+)["\']')
18
- stem_uid_pattern = re.compile(
19
- r'\.transform\.stem_uid\s*=\s*["\']([^"\']+)["\']'
20
- )
21
- version_pattern = re.compile(r'\.transform\.version\s*=\s*["\']([^"\']+)["\']')
22
14
  elif suffix == ".ipynb":
23
15
  track_pattern = re.compile(
24
16
  r'ln\.track\(\s*(?:transform\s*=\s*)?(?:\\"|\')([a-zA-Z0-9]{16})(?:\\"|\')'
25
17
  )
26
18
  # backward compat
27
19
  uid_pattern = re.compile(r'\.context\.uid\s*=\s*\\["\']([^"\']+)\\["\']')
28
- stem_uid_pattern = re.compile(
29
- r'\.transform\.stem_uid\s*=\s*\\["\']([^"\']+)\\["\']'
30
- )
31
- version_pattern = re.compile(
32
- r'\.transform\.version\s*=\s*\\["\']([^"\']+)\\["\']'
33
- )
34
20
  elif suffix in {".R", ".qmd", ".Rmd"}:
35
21
  track_pattern = re.compile(
36
22
  r'track\(\s*(?:transform\s*=\s*)?([\'"])([a-zA-Z0-9]{16})\1'
37
23
  )
38
24
  uid_pattern = None
39
- stem_uid_pattern = None
40
- version_pattern = None
41
25
  else:
42
26
  raise SystemExit(
43
27
  "Only .py, .ipynb, .R, .qmd, .Rmd files are supported for saving"
@@ -48,26 +32,12 @@ def parse_uid_from_code(
48
32
  uid_match = track_pattern.search(content)
49
33
  group_index = 1 if suffix == ".ipynb" else 2
50
34
  uid = uid_match.group(group_index) if uid_match else None
51
- stem_uid = None
52
- version = None
53
35
 
54
36
  if uid_pattern is not None and uid is None:
55
37
  uid_match = uid_pattern.search(content)
56
38
  uid = uid_match.group(1) if uid_match else None
57
- if stem_uid_pattern is not None:
58
- stem_uid_match = stem_uid_pattern.search(content)
59
- stem_uid = stem_uid_match.group(1) if stem_uid_match else None
60
- if version_pattern is not None:
61
- version_match = version_pattern.search(content)
62
- version = version_match.group(1) if version_match else None
63
39
 
64
- if uid is None and (stem_uid is None or version is None):
65
- target = "script" if suffix in {".py", ".R"} else "notebook"
66
- raise SystemExit(
67
- f"Cannot infer transform uid. Did you run `ln.track()` in your {target}?"
68
- )
69
-
70
- return uid, stem_uid, version
40
+ return uid
71
41
 
72
42
 
73
43
  def save_from_filepath_cli(
@@ -76,6 +46,8 @@ def save_from_filepath_cli(
76
46
  description: str | None,
77
47
  registry: str | None,
78
48
  ) -> str | None:
49
+ import lamindb_setup as ln_setup
50
+
79
51
  if not isinstance(filepath, Path):
80
52
  filepath = Path(filepath)
81
53
 
@@ -137,9 +109,9 @@ def save_from_filepath_cli(
137
109
  elif registry == "transform":
138
110
  with open(filepath) as file:
139
111
  content = file.read()
140
- uid, stem_uid, version = parse_uid_from_code(content, filepath.suffix)
141
- logger.important(f"mapped '{filepath}' on uid '{uid}'")
112
+ uid = parse_uid_from_code(content, filepath.suffix)
142
113
  if uid is not None:
114
+ logger.important(f"mapped '{filepath}' on uid '{uid}'")
143
115
  transform = ln.Transform.filter(uid=uid).one_or_none()
144
116
  if transform is None:
145
117
  logger.error(
@@ -148,10 +120,17 @@ def save_from_filepath_cli(
148
120
  )
149
121
  return "not-tracked-in-transform-registry"
150
122
  else:
151
- transform = ln.Transform.get(uid__startswith=stem_uid, version=version)
123
+ transform = ln.Transform.filter(key=filepath.name).one_or_none()
124
+ if transform is None:
125
+ transform = ln.Transform(
126
+ name=filepath.name,
127
+ key=filepath.name,
128
+ type="script" if filepath.suffix in {".R", ".py"} else "notebook",
129
+ ).save()
130
+ logger.important(f"created Transform('{transform.uid}')")
152
131
  # latest run of this transform by user
153
132
  run = ln.Run.filter(transform=transform).order_by("-started_at").first()
154
- if run.created_by.id != ln_setup.settings.user.id:
133
+ if run is not None and run.created_by.id != ln_setup.settings.user.id:
155
134
  response = input(
156
135
  "You are trying to save a transform created by another user: Source"
157
136
  " and report files will be tagged with *your* user id. Proceed?"
@@ -1,7 +1,7 @@
1
1
  import lamindb as ln
2
2
 
3
- ln.context.name = "My good script 2"
4
- ln.track("VFYCIuaw2GsX0000")
3
+ # purposefully do not pass uid
4
+ ln.track()
5
5
 
6
6
 
7
7
  if __name__ == "__main__":
@@ -1,4 +1,5 @@
1
1
  from lamin_cli._load import decompose_url
2
+ from pathlib import Path
2
3
  import subprocess
3
4
 
4
5
 
@@ -15,26 +16,50 @@ def test_decompose_url():
15
16
  assert uid == "1GCKs8zLtkc85zKv"
16
17
 
17
18
 
18
- def test_get_transform():
19
+ def test_load_transform():
20
+ import lamindb_setup as ln_setup
21
+
22
+ print(ln_setup.settings.instance.slug)
19
23
  result = subprocess.run(
20
24
  "lamin load"
21
- " 'https://lamin.ai/laminlabs/arrayloader-benchmarks/transform/1GCKs8zLtkc85zKv'"
25
+ " 'https://lamin.ai/laminlabs/lamin-dev/transform/VFYCIuaw2GsX0000'"
22
26
  " --with-env", # noqa
23
27
  shell=True,
24
28
  capture_output=True,
25
29
  )
30
+ print(result.stdout.decode())
31
+ print(result.stderr.decode())
26
32
  assert result.returncode == 0
27
33
 
34
+ print(ln_setup.settings.instance.slug)
35
+
36
+ path1 = Path("run-track-and-finish.py")
37
+ path2 = Path("run-track-and-finish__requirements.txt")
38
+ assert path1.exists()
39
+ assert path2.exists()
40
+
41
+ # below will fail because it will say "these files already exist"
42
+ result = subprocess.run(
43
+ "lamin load transform --uid VFYCIuaw2GsX --with-env",
44
+ shell=True,
45
+ capture_output=True,
46
+ )
47
+ assert result.returncode == 1
48
+ path1.unlink()
49
+ path2.unlink()
50
+
28
51
  # partial uid
29
52
  result = subprocess.run(
30
- "lamin load transform --uid 1GCKs8zLtkc85z --with-env",
53
+ "lamin load transform --uid VFYCIuaw2GsX --with-env",
31
54
  shell=True,
32
55
  capture_output=True,
33
56
  )
34
57
  assert result.returncode == 0
58
+ path1.unlink()
59
+ path2.unlink()
35
60
 
36
61
 
37
- def test_get_artifact():
62
+ def test_load_artifact():
38
63
  result = subprocess.run(
39
64
  "lamin load"
40
65
  " 'https://lamin.ai/laminlabs/lamin-site-assets/artifact/e2G7k9EVul4JbfsEYAy5'", # noqa
@@ -15,12 +15,12 @@ def test_migrate_deploy():
15
15
  import lamindb as ln
16
16
 
17
17
  instance_slug = ln.setup.settings.instance.slug
18
- exit_status = os.system(
19
- "lamin connect testuser1/static-test-instance-private-sqlite"
20
- )
21
- assert exit_status == 0
22
- exit_status = os.system("lamin migrate deploy")
23
- assert exit_status == 0
18
+ # exit_status = os.system(
19
+ # "lamin connect testuser1/static-test-instance-private-sqlite"
20
+ # )
21
+ # assert exit_status == 0
22
+ # exit_status = os.system("lamin migrate deploy")
23
+ # assert exit_status == 0
24
24
  # now test that the hub got populated with the correct lamindb version
25
25
  # test it once we integrated it in the CLI output
26
26
  # instance = call_with_fallback_auth(
@@ -35,6 +35,6 @@ def test_migrate_deploy():
35
35
 
36
36
  # def test_migrate_squash():
37
37
  # exit_status = os.system(
38
- # "yes | lamin migrate squash --package-name lnschema_core --end-number 0023"
38
+ # "yes | lamin migrate squash --package-name lamindb --end-number 0023"
39
39
  # )
40
40
  # assert exit_status == 0
@@ -1,4 +1,3 @@
1
- import pytest
2
1
  from lamin_cli._save import parse_uid_from_code
3
2
 
4
3
 
@@ -33,13 +32,12 @@ def test_python_track_pattern():
33
32
 
34
33
  # Test valid cases
35
34
  for content, expected_uid in valid_cases:
36
- uid, _, _ = parse_uid_from_code(content, ".py")
35
+ uid = parse_uid_from_code(content, ".py")
37
36
  assert uid == expected_uid, f"Failed for valid content: {content}"
38
37
 
39
38
  # Test invalid cases
40
39
  for content in invalid_cases:
41
- with pytest.raises(SystemExit):
42
- uid, _, _ = parse_uid_from_code(content, ".py")
40
+ assert parse_uid_from_code(content, ".py") is None
43
41
 
44
42
 
45
43
  def test_jupyter_track_pattern():
@@ -70,14 +68,12 @@ def test_jupyter_track_pattern():
70
68
 
71
69
  # Test valid cases
72
70
  for content, expected_uid in valid_cases:
73
- uid, _, _ = parse_uid_from_code(content, ".ipynb")
71
+ uid = parse_uid_from_code(content, ".ipynb")
74
72
  assert uid == expected_uid, f"Failed for valid content: {content}"
75
73
 
76
74
  # Test invalid cases
77
75
  for content in invalid_cases:
78
- print(content)
79
- with pytest.raises(SystemExit):
80
- uid, _, _ = parse_uid_from_code(content, ".py")
76
+ assert parse_uid_from_code(content, ".py") is None
81
77
 
82
78
 
83
79
  def test_edge_cases():
@@ -99,8 +95,7 @@ def test_edge_cases():
99
95
  ]
100
96
 
101
97
  for content, expected_uid, suffix in test_cases:
102
- print(content)
103
- uid, _, _ = parse_uid_from_code(content, suffix)
98
+ uid = parse_uid_from_code(content, suffix)
104
99
  assert uid == expected_uid, f"Failed for content: {content}"
105
100
 
106
101
 
@@ -116,7 +111,7 @@ def test_r_track_pattern():
116
111
  # Test valid cases across all R-related suffixes
117
112
  for suffix in suffixes:
118
113
  for content, expected_uid in valid_cases:
119
- uid, _, _ = parse_uid_from_code(content, suffix)
114
+ uid = parse_uid_from_code(content, suffix)
120
115
  assert (
121
116
  uid == expected_uid
122
117
  ), f"Failed for valid content with {suffix}: {content}"
@@ -1,4 +1,5 @@
1
1
  import subprocess
2
+ import lamindb_setup as ln_setup
2
3
  from pathlib import Path
3
4
 
4
5
  test_file = Path(__file__).parent.parent.resolve() / ".gitignore"
@@ -21,6 +22,8 @@ def test_save_file():
21
22
  )
22
23
  assert result.returncode == 1
23
24
 
25
+ print(ln_setup.settings.instance.slug)
26
+
24
27
  result = subprocess.run(
25
28
  f"lamin save {filepath} --key mytest",
26
29
  shell=True,
@@ -20,11 +20,7 @@ def test_save_not_initialized():
20
20
  capture_output=True,
21
21
  env=env,
22
22
  )
23
- assert result.returncode == 1
24
- assert (
25
- "Cannot infer transform uid. Did you run `ln.track()` in your notebook?"
26
- in result.stderr.decode()
27
- )
23
+ assert result.returncode == 0
28
24
 
29
25
 
30
26
  def test_save_non_consecutive():
@@ -87,7 +83,7 @@ def test_save_consecutive():
87
83
  transform = ln.Transform.filter(uid="hlsFXswrJjtt0000").one_or_none()
88
84
  assert transform is not None
89
85
  assert transform.latest_run.report is None
90
- assert transform._source_code_artifact is None
86
+ assert transform.source_code is None
91
87
  assert transform.latest_run.environment is None
92
88
 
93
89
  # and save again
@@ -107,7 +103,7 @@ def test_save_consecutive():
107
103
  assert (
108
104
  transform.source_code
109
105
  == """# %% [markdown]
110
- # # transform.name
106
+ #
111
107
 
112
108
  # %%
113
109
  import lamindb as ln
@@ -119,7 +115,7 @@ ln.track("hlsFXswrJjtt0000")
119
115
  print("my consecutive cell")
120
116
  """
121
117
  )
122
- assert transform.hash == "OwVL-0-_gmk8heR3zV7BkA"
118
+ assert transform.hash == "ik5Dilxs2RmwOGydohFolQ"
123
119
  # below is the test that we can use if store the run repot as `.ipynb`
124
120
  # and not as html as we do right now
125
121
  assert transform.latest_run.report.suffix == ".html"
@@ -133,7 +129,6 @@ print("my consecutive cell")
133
129
  # }
134
130
  # testing for the hash of the report makes no sense because it contains timestamps
135
131
  assert transform.latest_run.environment.path.exists()
136
- assert transform._source_code_artifact is None
137
132
 
138
133
  # edit the notebook
139
134
  nb = read_notebook(notebook_path)
@@ -167,9 +162,8 @@ print("my consecutive cell")
167
162
  transform = ln.Transform.get("hlsFXswrJjtt0000")
168
163
  assert transform.latest_run.report.path.exists()
169
164
  assert transform.latest_run.report.path == transform.latest_run.report.path
170
- assert transform.hash == "BhQpym0JfeypqhVMPlQ0ng"
165
+ assert transform.hash == "Jv0_TrZfzM-0erbp1FGdrQ"
171
166
  assert transform.latest_run.environment.path.exists()
172
- assert transform._source_code_artifact is None
173
167
 
174
168
  # get the the source code via command line
175
169
  result = subprocess.run(
@@ -8,7 +8,23 @@ from lamindb_setup import settings
8
8
  scripts_dir = Path(__file__).parent.resolve() / "scripts"
9
9
 
10
10
 
11
- def test_run_save_cache():
11
+ def test_save_without_uid():
12
+ env = os.environ
13
+ env["LAMIN_TESTING"] = "true"
14
+ filepath = scripts_dir / "run-track-and-finish.py"
15
+
16
+ # attempt to save the script without it yet being run
17
+ result = subprocess.run(
18
+ f"lamin save {filepath}",
19
+ shell=True,
20
+ capture_output=True,
21
+ )
22
+ # print(result.stdout.decode())
23
+ assert result.returncode == 0
24
+ assert "created Transform" in result.stdout.decode()
25
+
26
+
27
+ def test_run_save_cache_with_git_and_uid():
12
28
  env = os.environ
13
29
  env["LAMIN_TESTING"] = "true"
14
30
  filepath = scripts_dir / "run-track-and-finish-sync-git.py"
@@ -39,7 +55,6 @@ def test_run_save_cache():
39
55
  transform = ln.Transform.get("m5uCHTTpJnjQ")
40
56
  assert transform.hash == "MoIciBQ0lpVPCKQGofPX6g"
41
57
  assert transform.latest_run.environment.path.exists()
42
- assert transform._source_code_artifact is None
43
58
 
44
59
  # you can rerun the same script
45
60
  result = subprocess.run(
@@ -103,7 +118,7 @@ def test_run_save_cache():
103
118
  # print(result.stdout.decode())
104
119
  # print(result.stderr.decode())
105
120
  assert result.returncode == 1
106
- assert "Source code changed, bump revision by setting" in result.stderr.decode()
121
+ assert " source code changed, run:" in result.stderr.decode()
107
122
 
108
123
  # update the uid
109
124
  content = filepath.read_text()
@@ -1,3 +0,0 @@
1
- """Lamin CLI."""
2
-
3
- __version__ = "0.22.0"
File without changes
File without changes
File without changes
File without changes
File without changes