Repository: microsoft/hi-ml

Issue:
Submitting to AML with `health_azure` removes the trailing line from `.amlignore`



Discussion:

Resolving patch:
diff --git a/hi-ml-azure/src/health_azure/himl.py b/hi-ml-azure/src/health_azure/himl.py
--- a/hi-ml-azure/src/health_azure/himl.py
+++ b/hi-ml-azure/src/health_azure/himl.py
@@ -1196,13 +1196,14 @@ def append_to_amlignore(lines_to_append: List[str], amlignore: Optional[Path] =
     amlignore_exists_already = amlignore.exists()
     old_contents = amlignore.read_text() if amlignore_exists_already else ""
     new_lines = old_contents.splitlines() + lines_to_append
-    new_text = "\n".join(new_lines)
-    if new_text:
-        amlignore.write_text(new_text)
+    linefeed = "\n"
+    new_text = linefeed.join(new_lines)
+    if new_lines:
+        amlignore.write_text(new_text + linefeed)
     yield
     if amlignore_exists_already:
         amlignore.write_text(old_contents)
-    elif new_text:
+    elif new_lines:
         amlignore.unlink()
 
 


Test patch:
diff --git a/hi-ml-azure/testazure/testazure/test_himl.py b/hi-ml-azure/testazure/testazure/test_himl.py
--- a/hi-ml-azure/testazure/testazure/test_himl.py
+++ b/hi-ml-azure/testazure/testazure/test_himl.py
@@ -614,7 +614,7 @@ def test_append_to_amlignore(tmp_path: Path) -> None:
     amlignore_path = tmp_path / Path(uuid4().hex)
     with himl.append_to_amlignore(amlignore=amlignore_path, lines_to_append=["1st line", "2nd line"]):
         amlignore_text = amlignore_path.read_text()
-    assert "1st line\n2nd line" == amlignore_text
+    assert "1st line\n2nd line\n" == amlignore_text
     assert not amlignore_path.exists()
 
     # If there is no .amlignore file before the test, and there are no lines to append, then there should be no
@@ -625,23 +625,49 @@ def test_append_to_amlignore(tmp_path: Path) -> None:
     assert not amlignore_exists_during_test
     assert not amlignore_path.exists()
 
-    # If there is an empty .amlignore file before the test, it should be there afterwards
+
+@pytest.mark.fast
+def test_append_to_amlignore_empty(tmp_path: Path) -> None:
+    """If there is an empty .amlignore file before the test, it should be there afterwards"""
     amlignore_path = tmp_path / Path(uuid4().hex)
     amlignore_path.touch()
     with himl.append_to_amlignore(amlignore=amlignore_path, lines_to_append=["1st line", "2nd line"]):
         amlignore_text = amlignore_path.read_text()
-    assert "1st line\n2nd line" == amlignore_text
+    assert "1st line\n2nd line\n" == amlignore_text
     assert amlignore_path.exists()
     assert amlignore_path.read_text() == ""
 
-    # If there is a .amlignore file before the test, it should be identical afterwards
+
+@pytest.mark.fast
+@pytest.mark.parametrize("aml_ignore_contents", ["0th line", "0th line\n"])
+def test_append_to_amlignore_exists1(tmp_path: Path, aml_ignore_contents: str) -> None:
+    """
+    If there is a .amlignore file before the test, it should be identical afterwards.
+    In particular, this should be the case even if there's a linebreak at the end or not
+    """
     amlignore_path = tmp_path / Path(uuid4().hex)
-    amlignore_path.write_text("0th line")
+    amlignore_path.write_text(aml_ignore_contents)
     with himl.append_to_amlignore(amlignore=amlignore_path, lines_to_append=["1st line", "2nd line"]):
         amlignore_text = amlignore_path.read_text()
-    assert "0th line\n1st line\n2nd line" == amlignore_text
+    assert "0th line\n1st line\n2nd line\n" == amlignore_text
+    amlignore_text = amlignore_path.read_text()
+    assert amlignore_text == aml_ignore_contents
+
+
+@pytest.mark.fast
+@pytest.mark.parametrize("aml_ignore_contents", ["0th line", "0th line\n"])
+def test_append_to_amlignore_exists2(tmp_path: Path, aml_ignore_contents: str) -> None:
+    """
+    If there is a .amlignore file before the test, it should be identical afterwards.
+    In particular, this should be the case even if there's a linebreak at the end or not, and if nothing is added
+    to the file.
+    """
+    amlignore_path = tmp_path / Path(uuid4().hex)
+    amlignore_path.write_text(aml_ignore_contents)
+    with himl.append_to_amlignore(amlignore=amlignore_path, lines_to_append=[]):
+        amlignore_text = amlignore_path.read_text()
     amlignore_text = amlignore_path.read_text()
-    assert "0th line" == amlignore_text
+    assert amlignore_text == aml_ignore_contents
 
 
 class TestTagOption(Enum):