diff --git a/lamin_cli/_load.py b/lamin_cli/_load.py index f5e1c4e..0843495 100644 --- a/lamin_cli/_load.py +++ b/lamin_cli/_load.py @@ -2,6 +2,7 @@ from typing import Tuple from lamin_utils import logger import shutil +import re from pathlib import Path @@ -35,16 +36,39 @@ def script_to_notebook( import jupytext from lamin_utils._base62 import increment_base62 - py_content = transform.source_code.replace( - "# # transform.name", f"# # {transform.name}" - ) + if notebook_path.suffix == ".ipynb": + new_content = transform.source_code.replace( + "# # transform.name", f"# # {transform.name}" + ) + else: # R notebook + # Pattern to match title only within YAML header section + title_pattern = r'^---\n.*?title:\s*"([^"]*)".*?---' + title_match = re.search( + title_pattern, transform.source_code, flags=re.DOTALL | re.MULTILINE + ) + new_content = transform.source_code + if title_match: + current_title = title_match.group(1) + if current_title != transform.name: + pattern = r'^(---\n.*?title:\s*)"([^"]*)"(.*?---)' + replacement = f'\\1"{transform.name}"\\3' + new_content = re.sub( + pattern, + replacement, + new_content, + flags=re.DOTALL | re.MULTILINE, + ) + logger.important(f"fixed title: {current_title} → {transform.name}") if bump_revision: uid = transform.uid new_uid = f"{uid[:-4]}{increment_base62(uid[-4:])}" - py_content = py_content.replace(uid, new_uid) + new_content = new_content.replace(uid, new_uid) logger.important(f"updated uid: {uid} → {new_uid}") - notebook = jupytext.reads(py_content, fmt="py:percent") - jupytext.write(notebook, notebook_path) + if notebook_path.suffix == ".ipynb": + notebook = jupytext.reads(new_content, fmt="py:percent") + jupytext.write(notebook, notebook_path) + else: + notebook_path.write_text(new_content) query_by_uid = uid is not None @@ -61,11 +85,7 @@ def script_to_notebook( transforms = ln.Transform.objects.filter(key=key, source_code__isnull=False) if (n_transforms := len(transforms)) == 0: - err_msg = ( - f"uid strating with {uid}" - if query_by_uid - else f"key={key} and source_code" - ) + err_msg = f"uid {uid}" if query_by_uid else f"key={key} and source_code" raise SystemExit(f"Transform with {err_msg} does not exist.") if n_transforms > 1: @@ -87,8 +107,8 @@ def script_to_notebook( target_filename += transform._source_code_artifact.suffix shutil.move(filepath_cache, target_filename) elif transform.source_code is not None: - if transform.key.endswith(".ipynb"): - script_to_notebook(transform, target_filename, bump_revision=True) + if transform.key.endswith((".ipynb", ".Rmd", ".qmd")): + script_to_notebook(transform, Path(target_filename), bump_revision=True) else: Path(target_filename).write_text(transform.source_code) else: diff --git a/lamin_cli/_save.py b/lamin_cli/_save.py index f8ceabe..5b720c8 100644 --- a/lamin_cli/_save.py +++ b/lamin_cli/_save.py @@ -94,14 +94,23 @@ def save_from_filepath_cli( "R": set([".R", ".qmd", ".Rmd"]), } - if ( - filepath.suffix in {".qmd", ".Rmd"} - and not filepath.with_suffix(".html").exists() - ): - raise SystemExit( - f"Please export your {filepath.suffix} file as an html file here" - f" {filepath.with_suffix('.html')}" - ) + if filepath.suffix in {".qmd", ".Rmd"}: + if not ( + filepath.with_suffix(".html").exists() + or filepath.with_suffix(".nb.html").exists() + ): + raise SystemExit( + f"Please export your {filepath.suffix} file as an html file here" + f" {filepath.with_suffix('.html')}" + ) + if ( + filepath.with_suffix(".html").exists() + and filepath.with_suffix(".nb.html").exists() + ): + raise SystemExit( + f'Please delete one of\n - {filepath.with_suffix(".html")}\n -' + f' {filepath.with_suffix(".nb.html")}' + ) if registry is None: registry = ( @@ -156,16 +165,6 @@ def save_from_filepath_cli( filepath=filepath, from_cli=True, ) - if filepath.suffix in {".qmd", ".Rmd"}: - report_file = ln.Artifact( - filepath.with_suffix(".html"), # validated at the top that this exists - description=f"Report of run {run.uid}", - visibility=0, # hidden file - run=False, - ) - report_file.save(upload=True, print_progress=False) - run.report = report_file - run.save() return return_code else: raise SystemExit("Allowed values for '--registry' are: 'artifact', 'transform'") diff --git a/tests/test_save_scripts.py b/tests/test_save_scripts.py index cffd46d..0694023 100644 --- a/tests/test_save_scripts.py +++ b/tests/test_save_scripts.py @@ -54,7 +54,6 @@ def test_run_save_cache(): assert "loaded Transform" in result.stdout.decode() assert "m5uCHTTp" in result.stdout.decode() assert "started Run" in result.stdout.decode() - assert "source code is already saved" in result.stdout.decode() # you can re-save the script result = subprocess.run( @@ -66,7 +65,6 @@ def test_run_save_cache(): # print(result.stdout.decode()) # print(result.stderr.decode()) assert result.returncode == 0 - assert "source code is already saved" in result.stdout.decode() assert "run.environment is already saved" in result.stdout.decode() # edit the script @@ -204,7 +202,6 @@ def test_run_save_with_params(): print(result.stdout.decode()) print(result.stderr.decode()) assert result.returncode == 0 - assert "source code is already saved" in result.stdout.decode() assert ( "run-track-with-params.py' on uid 'JjRF4mACd9m00000'" in result.stdout.decode() )