mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-04 23:09:44 +01:00
* experiments: move executor into a module * experiments: separate executor into base/local * rename LocalExecutor to TempDirExecutor, run in .dvc/tmp by default * git: restore HEAD using reset not checkout in detached_head() * experiments: support calling BaseExecutor.reproduce directly for workspace runs * experiments: run single experiments in local workspace by default * update experiments tests for workspace changes * experiments: update checkpoints for workspace runs * update checkpoints tests * update test_show * add force param for apply * exp apply: add --force option * exp run/res: add --temp option to force tempdir execution for single experiments * force apply in non-apply specific tests
212 lines
6.4 KiB
Python
212 lines
6.4 KiB
Python
import logging
|
|
|
|
import pytest
|
|
from funcy import first
|
|
|
|
from dvc.exceptions import DvcException
|
|
from dvc.repo.experiments import Experiments, MultipleBranchError
|
|
from dvc.repo.experiments.base import EXEC_APPLY, EXEC_CHECKPOINT
|
|
|
|
|
|
@pytest.mark.parametrize("workspace", [True, False])
|
|
def test_new_checkpoint(
|
|
tmp_dir, scm, dvc, checkpoint_stage, mocker, workspace
|
|
):
|
|
new_mock = mocker.spy(dvc.experiments, "new")
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing, params=["foo=2"], tmp_dir=not workspace
|
|
)
|
|
exp = first(results)
|
|
|
|
new_mock.assert_called_once()
|
|
for rev in dvc.brancher([exp]):
|
|
if rev == "workspace":
|
|
continue
|
|
tree = dvc.repo_tree
|
|
with tree.open(tmp_dir / "foo") as fobj:
|
|
assert fobj.read().strip() == "5"
|
|
with tree.open(tmp_dir / "metrics.yaml") as fobj:
|
|
assert fobj.read().strip() == "foo: 2"
|
|
|
|
if workspace:
|
|
assert scm.get_ref(EXEC_APPLY) == exp
|
|
assert scm.get_ref(EXEC_CHECKPOINT) == exp
|
|
if workspace:
|
|
assert (tmp_dir / "foo").read_text().strip() == "5"
|
|
assert (tmp_dir / "metrics.yaml").read_text().strip() == "foo: 2"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"checkpoint_resume, workspace",
|
|
[
|
|
(Experiments.LAST_CHECKPOINT, True),
|
|
(Experiments.LAST_CHECKPOINT, False),
|
|
("foo", True),
|
|
("foo", False),
|
|
],
|
|
)
|
|
def test_resume_checkpoint(
|
|
tmp_dir, scm, dvc, checkpoint_stage, checkpoint_resume, workspace
|
|
):
|
|
with pytest.raises(DvcException):
|
|
dvc.experiments.run(
|
|
checkpoint_stage=checkpoint_stage.addressing,
|
|
checkpoint_resume=checkpoint_resume,
|
|
tmp_dir=not workspace,
|
|
)
|
|
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing, params=["foo=2"], tmp_dir=not workspace
|
|
)
|
|
|
|
with pytest.raises(DvcException):
|
|
dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
checkpoint_resume="abc1234",
|
|
tmp_dir=not workspace,
|
|
)
|
|
|
|
if checkpoint_resume != Experiments.LAST_CHECKPOINT:
|
|
checkpoint_resume = first(results)
|
|
|
|
if not workspace:
|
|
dvc.experiments.apply(first(results))
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
checkpoint_resume=checkpoint_resume,
|
|
tmp_dir=not workspace,
|
|
)
|
|
exp = first(results)
|
|
|
|
for rev in dvc.brancher([exp]):
|
|
if rev == "workspace":
|
|
continue
|
|
tree = dvc.repo_tree
|
|
with tree.open(tmp_dir / "foo") as fobj:
|
|
assert fobj.read().strip() == "10"
|
|
with tree.open(tmp_dir / "metrics.yaml") as fobj:
|
|
assert fobj.read().strip() == "foo: 2"
|
|
|
|
if workspace:
|
|
assert scm.get_ref(EXEC_APPLY) == exp
|
|
assert scm.get_ref(EXEC_CHECKPOINT) == exp
|
|
|
|
|
|
@pytest.mark.parametrize("workspace", [True, False])
|
|
def test_reset_checkpoint(
|
|
tmp_dir, scm, dvc, checkpoint_stage, caplog, workspace
|
|
):
|
|
from dvc.repo.experiments.base import CheckpointExistsError
|
|
|
|
dvc.experiments.run(
|
|
checkpoint_stage.addressing, name="foo", tmp_dir=not workspace,
|
|
)
|
|
|
|
if workspace:
|
|
scm.reset(hard=True)
|
|
scm.gitpython.repo.git.clean(force=True)
|
|
|
|
if workspace:
|
|
with caplog.at_level(logging.ERROR):
|
|
dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
name="foo",
|
|
params=["foo=2"],
|
|
tmp_dir=not workspace,
|
|
)
|
|
assert "checkpoint experiment conflicts with existing" in caplog.text
|
|
|
|
scm.reset(hard=True)
|
|
scm.gitpython.repo.git.clean(force=True)
|
|
else:
|
|
with pytest.raises(CheckpointExistsError):
|
|
dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
name="foo",
|
|
params=["foo=2"],
|
|
tmp_dir=not workspace,
|
|
)
|
|
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
params=["foo=2"],
|
|
name="foo",
|
|
force=True,
|
|
tmp_dir=not workspace,
|
|
)
|
|
exp = first(results)
|
|
|
|
for rev in dvc.brancher([exp]):
|
|
if rev == "workspace":
|
|
continue
|
|
tree = dvc.repo_tree
|
|
with tree.open(tmp_dir / "foo") as fobj:
|
|
assert fobj.read().strip() == "5"
|
|
with tree.open(tmp_dir / "metrics.yaml") as fobj:
|
|
assert fobj.read().strip() == "foo: 2"
|
|
|
|
if workspace:
|
|
assert scm.get_ref(EXEC_APPLY) == exp
|
|
assert scm.get_ref(EXEC_CHECKPOINT) == exp
|
|
|
|
|
|
@pytest.mark.parametrize("workspace", [True, False])
|
|
def test_resume_branch(tmp_dir, scm, dvc, checkpoint_stage, workspace):
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing, params=["foo=2"], tmp_dir=not workspace
|
|
)
|
|
branch_rev = first(results)
|
|
if not workspace:
|
|
dvc.experiments.apply(branch_rev)
|
|
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
checkpoint_resume=branch_rev,
|
|
tmp_dir=not workspace,
|
|
)
|
|
checkpoint_a = first(results)
|
|
if not workspace:
|
|
dvc.experiments.apply(checkpoint_a, force=True)
|
|
|
|
with pytest.raises(DvcException):
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
checkpoint_resume=branch_rev,
|
|
params=["foo=100"],
|
|
tmp_dir=not workspace,
|
|
)
|
|
|
|
dvc.experiments.apply(branch_rev, force=True)
|
|
results = dvc.experiments.run(
|
|
checkpoint_stage.addressing,
|
|
checkpoint_resume=branch_rev,
|
|
params=["foo=100"],
|
|
tmp_dir=not workspace,
|
|
)
|
|
checkpoint_b = first(results)
|
|
|
|
for rev in dvc.brancher([checkpoint_a]):
|
|
if rev == "workspace":
|
|
continue
|
|
tree = dvc.repo_tree
|
|
with tree.open(tmp_dir / "foo") as fobj:
|
|
assert fobj.read().strip() == "10"
|
|
with tree.open(tmp_dir / "metrics.yaml") as fobj:
|
|
assert fobj.read().strip() == "foo: 2"
|
|
|
|
for rev in dvc.brancher([checkpoint_b]):
|
|
if rev == "workspace":
|
|
continue
|
|
tree = dvc.repo_tree
|
|
with tree.open(tmp_dir / "foo") as fobj:
|
|
assert fobj.read().strip() == "10"
|
|
with tree.open(tmp_dir / "metrics.yaml") as fobj:
|
|
assert fobj.read().strip() == "foo: 100"
|
|
|
|
with pytest.raises(MultipleBranchError):
|
|
dvc.experiments.get_branch_by_rev(branch_rev)
|
|
|
|
assert branch_rev == dvc.experiments.scm.gitpython.repo.git.merge_base(
|
|
checkpoint_a, checkpoint_b
|
|
)
|