mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-04 15:28:27 +01:00
dvc.run does not expand variables. It is only done when it's actually read from dvc.yaml file. So during dvc run, the shell will try to expand the variable, which does not exist. I don't think that the intention was to use shell variables. But I don't think we should ever use them, as they will fail on some shells (eg: fish) and keep the scripts as simple as possible.
156 lines
4.6 KiB
Python
156 lines
4.6 KiB
Python
import pytest
|
|
from funcy import first
|
|
|
|
from dvc.repo.experiments.exceptions import ExperimentExistsError, InvalidArgumentError
|
|
from dvc.repo.experiments.utils import exp_refs_by_rev
|
|
from dvc.scm import resolve_rev
|
|
|
|
|
|
def setup_stage(tmp_dir, dvc, scm):
|
|
tmp_dir.gen("params.yaml", "foo: 1")
|
|
dvc.run(name="echo-foo", outs=["bar"], cmd="echo foo > bar")
|
|
scm.add(["dvc.yaml", "dvc.lock", ".gitignore", "params.yaml"])
|
|
scm.commit("init")
|
|
|
|
|
|
def test_exp_save_unchanged(tmp_dir, dvc, scm):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
dvc.experiments.save()
|
|
|
|
|
|
@pytest.mark.parametrize("name", (None, "test"))
|
|
def test_exp_save(tmp_dir, dvc, scm, name):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
baseline = scm.get_rev()
|
|
|
|
exp = dvc.experiments.save(name=name)
|
|
ref_info = first(exp_refs_by_rev(scm, exp))
|
|
assert ref_info
|
|
assert ref_info.baseline_sha == baseline
|
|
|
|
exp_name = name if name else ref_info.name
|
|
assert dvc.experiments.get_exact_name([exp])[exp] == exp_name
|
|
assert resolve_rev(scm, exp_name) == exp
|
|
|
|
|
|
def test_exp_save_overwrite_experiment(tmp_dir, dvc, scm):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
name = "dummy"
|
|
dvc.experiments.save(name=name)
|
|
|
|
tmp_dir.gen("params.yaml", "foo: 2")
|
|
with pytest.raises(ExperimentExistsError):
|
|
dvc.experiments.save(name=name)
|
|
|
|
dvc.experiments.save(name=name, force=True)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"name",
|
|
(
|
|
"invalid/name",
|
|
"invalid..name",
|
|
"invalid~name",
|
|
"invalid?name",
|
|
"invalidname.",
|
|
),
|
|
)
|
|
def test_exp_save_invalid_name(tmp_dir, dvc, scm, name):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
with pytest.raises(InvalidArgumentError):
|
|
dvc.experiments.save(name=name, force=True)
|
|
|
|
|
|
def test_exp_save_after_commit(tmp_dir, dvc, scm):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
baseline = scm.get_rev()
|
|
dvc.experiments.save(name="exp-1", force=True)
|
|
|
|
tmp_dir.scm_gen({"new_file": "new_file"}, commit="new baseline")
|
|
dvc.experiments.save(name="exp-2", force=True)
|
|
|
|
all_exps = dvc.experiments.ls(all_commits=True)
|
|
assert all_exps[baseline[:7]] == ["exp-1"]
|
|
assert all_exps["master"] == ["exp-2"]
|
|
|
|
|
|
def test_exp_save_with_staged_changes(tmp_dir, dvc, scm):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
tmp_dir.gen({"deleted": "deleted", "modified": "modified"})
|
|
scm.add_commit(["deleted", "modified"], "init")
|
|
|
|
(tmp_dir / "deleted").unlink()
|
|
tmp_dir.gen({"new_file": "new_file"})
|
|
(tmp_dir / "modified").write_text("foo")
|
|
scm.add(["deleted", "new_file", "modified"])
|
|
|
|
exp_rev = dvc.experiments.save(name="exp")
|
|
scm.checkout(exp_rev, force=True)
|
|
assert not (tmp_dir / "deleted").exists()
|
|
assert (tmp_dir / "new_file").exists()
|
|
assert (tmp_dir / "modified").read_text() == "foo"
|
|
|
|
|
|
def test_exp_save_include_untracked(tmp_dir, dvc, scm):
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
|
|
new_file = tmp_dir / "new_file"
|
|
new_file.write_text("new_file")
|
|
dvc.experiments.save(name="exp", include_untracked=["new_file"])
|
|
|
|
_, _, unstaged = scm.status()
|
|
assert "new_file" in unstaged
|
|
assert new_file.read_text() == "new_file"
|
|
|
|
|
|
def test_exp_save_include_untracked_warning(tmp_dir, dvc, scm, mocker):
|
|
"""Regression test for https://github.com/iterative/dvc/issues/9061"""
|
|
setup_stage(tmp_dir, dvc, scm)
|
|
|
|
new_dir = tmp_dir / "new_dir"
|
|
new_dir.mkdir()
|
|
(new_dir / "foo").write_text("foo")
|
|
(new_dir / "bar").write_text("bar")
|
|
|
|
logger = mocker.patch("dvc.repo.experiments.executor.base.logger")
|
|
|
|
dvc.experiments.save(name="exp", include_untracked=["new_dir"])
|
|
assert not logger.warning.called
|
|
|
|
|
|
def test_untracked_top_level_files_are_included_in_exp(tmp_dir, scm, dvc):
|
|
(tmp_dir / "dvc.yaml").dump(
|
|
{
|
|
"metrics": ["metrics.json"],
|
|
"params": ["params.yaml"],
|
|
"plots": ["plots.csv"],
|
|
}
|
|
)
|
|
stage = dvc.stage.add(
|
|
cmd="touch metrics.json && touch params.yaml && touch plots.csv",
|
|
name="top-level",
|
|
)
|
|
scm.add_commit(["dvc.yaml"], message="add dvc.yaml")
|
|
dvc.reproduce(stage.addressing)
|
|
exp = dvc.experiments.save()
|
|
fs = scm.get_fs(exp)
|
|
for file in ["metrics.json", "params.yaml", "plots.csv", "dvc.lock"]:
|
|
assert fs.exists(file)
|
|
|
|
|
|
def test_untracked_dvclock_is_included_in_exp(tmp_dir, scm, dvc):
|
|
stage = dvc.stage.add(
|
|
cmd="echo foo",
|
|
name="foo",
|
|
)
|
|
scm.add_commit(["dvc.yaml"], message="add dvc.yaml")
|
|
dvc.reproduce(stage.addressing)
|
|
|
|
# dvc.reproduce automatically stages `dvc.lock`
|
|
# force it to be untracked
|
|
scm.reset()
|
|
|
|
exp = dvc.experiments.save()
|
|
fs = scm.get_fs(exp)
|
|
assert fs.exists("dvc.lock")
|