diff --git a/tests/func/experiments/test_apply.py b/tests/func/experiments/test_apply.py new file mode 100644 index 000000000..c9da618ac --- /dev/null +++ b/tests/func/experiments/test_apply.py @@ -0,0 +1,104 @@ +import dulwich.errors +import pytest +from funcy import first + +from dvc.repo.experiments.refs import CELERY_STASH + + +def test_apply(tmp_dir, scm, dvc, exp_stage): + from dvc.exceptions import InvalidArgumentError + + results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"], tmp_dir=True) + exp_a = first(results) + + dvc.experiments.run( + exp_stage.addressing, params=["foo=3"], tmp_dir=True, name="foo" + ) + + with pytest.raises(InvalidArgumentError): + dvc.experiments.apply("bar") + + dvc.experiments.apply(exp_a) + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" + assert (tmp_dir / "metrics.yaml").read_text().strip() == "foo: 2" + + dvc.experiments.apply("foo") + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" + assert (tmp_dir / "metrics.yaml").read_text().strip() == "foo: 3" + + +@pytest.mark.xfail( + raises=( + dulwich.errors.CommitError, + dulwich.file.FileLocked, + ), + strict=False, + reason="See https://github.com/iterative/dvc/issues/8570", +) +def test_apply_failed(tmp_dir, scm, dvc, failed_exp_stage, test_queue): + from dvc.exceptions import InvalidArgumentError + + dvc.experiments.run(failed_exp_stage.addressing, params=["foo=2"], queue=True) + exp_rev = dvc.experiments.scm.resolve_rev(f"{CELERY_STASH}@{{0}}") + + dvc.experiments.run( + failed_exp_stage.addressing, params=["foo=3"], queue=True, name="foo" + ) + dvc.experiments.run(run_all=True) + + with pytest.raises(InvalidArgumentError): + dvc.experiments.apply("bar") + + dvc.experiments.apply(exp_rev) + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" + + dvc.experiments.apply("foo") + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" + + +def test_apply_queued(tmp_dir, scm, dvc, exp_stage): + metrics_original = (tmp_dir / "metrics.yaml").read_text().strip() + dvc.experiments.run( + exp_stage.addressing, params=["foo=2"], name="exp-a", queue=True + ) + dvc.experiments.run( + exp_stage.addressing, params=["foo=3"], name="exp-b", queue=True + ) + queue_revs = { + entry.name: entry.stash_rev + for entry in dvc.experiments.celery_queue.iter_queued() + } + + dvc.experiments.apply(queue_revs["exp-a"]) + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" + assert (tmp_dir / "metrics.yaml").read_text().strip() == metrics_original + + dvc.experiments.apply(queue_revs["exp-b"]) + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" + assert (tmp_dir / "metrics.yaml").read_text().strip() == metrics_original + + +def test_apply_untracked(tmp_dir, scm, dvc, exp_stage): + results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"]) + exp = first(results) + tmp_dir.gen("untracked", "untracked") + tmp_dir.gen("params.yaml", "conflict") + + dvc.experiments.apply(exp) + assert (tmp_dir / "untracked").read_text() == "untracked" + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" + + +def test_apply_unchanged_head(tmp_dir, scm, dvc, exp_stage): + # see https://github.com/iterative/dvc/issues/8764 + tmp_dir.gen("params.yaml", "foo: 2") + scm.add(["dvc.yaml", "dvc.lock", "params.yaml", "metrics.yaml"]) + scm.commit("commit foo=2") + results = dvc.experiments.run(exp_stage.addressing) + # workspace now contains unchanged (git-committed) params.yaml w/foo: 2 + exp = first(results) + dvc.experiments.run(exp_stage.addressing, params=["foo=3"]) + # workspace now contains changed params.yaml w/foo: 3 + + dvc.experiments.apply(exp) + assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" diff --git a/tests/func/experiments/test_experiments.py b/tests/func/experiments/test_experiments.py index 3996ae315..fc340e005 100644 --- a/tests/func/experiments/test_experiments.py +++ b/tests/func/experiments/test_experiments.py @@ -4,8 +4,6 @@ import os import stat from textwrap import dedent -import dulwich.errors -import dulwich.file import pytest from funcy import first @@ -108,90 +106,6 @@ def test_failed_exp_workspace( ) -def test_apply(tmp_dir, scm, dvc, exp_stage): - from dvc.exceptions import InvalidArgumentError - - results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"], tmp_dir=True) - exp_a = first(results) - - dvc.experiments.run( - exp_stage.addressing, params=["foo=3"], tmp_dir=True, name="foo" - ) - - with pytest.raises(InvalidArgumentError): - dvc.experiments.apply("bar") - - dvc.experiments.apply(exp_a) - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" - assert (tmp_dir / "metrics.yaml").read_text().strip() == "foo: 2" - - dvc.experiments.apply("foo") - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" - assert (tmp_dir / "metrics.yaml").read_text().strip() == "foo: 3" - - -@pytest.mark.xfail( - raises=( - dulwich.errors.CommitError, - dulwich.file.FileLocked, - ), - strict=False, - reason="See https://github.com/iterative/dvc/issues/8570", -) -def test_apply_failed(tmp_dir, scm, dvc, failed_exp_stage, test_queue): - from dvc.exceptions import InvalidArgumentError - - dvc.experiments.run(failed_exp_stage.addressing, params=["foo=2"], queue=True) - exp_rev = dvc.experiments.scm.resolve_rev(f"{CELERY_STASH}@{{0}}") - - dvc.experiments.run( - failed_exp_stage.addressing, params=["foo=3"], queue=True, name="foo" - ) - dvc.experiments.run(run_all=True) - - with pytest.raises(InvalidArgumentError): - dvc.experiments.apply("bar") - - dvc.experiments.apply(exp_rev) - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" - - dvc.experiments.apply("foo") - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" - - -def test_apply_queued(tmp_dir, scm, dvc, exp_stage): - metrics_original = (tmp_dir / "metrics.yaml").read_text().strip() - dvc.experiments.run( - exp_stage.addressing, params=["foo=2"], name="exp-a", queue=True - ) - dvc.experiments.run( - exp_stage.addressing, params=["foo=3"], name="exp-b", queue=True - ) - queue_revs = { - entry.name: entry.stash_rev - for entry in dvc.experiments.celery_queue.iter_queued() - } - - dvc.experiments.apply(queue_revs["exp-a"]) - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" - assert (tmp_dir / "metrics.yaml").read_text().strip() == metrics_original - - dvc.experiments.apply(queue_revs["exp-b"]) - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 3" - assert (tmp_dir / "metrics.yaml").read_text().strip() == metrics_original - - -def test_apply_untracked(tmp_dir, scm, dvc, exp_stage): - results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"]) - exp = first(results) - tmp_dir.gen("untracked", "untracked") - tmp_dir.gen("params.yaml", "conflict") - - dvc.experiments.apply(exp) - assert (tmp_dir / "untracked").read_text() == "untracked" - assert (tmp_dir / "params.yaml").read_text().strip() == "foo: 2" - - def test_get_baseline(tmp_dir, scm, dvc, exp_stage): init_rev = scm.get_rev() assert dvc.experiments.get_baseline(init_rev) is None