mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
exp: use new collection in show/cli commands
- Updates 'dvc exp show --json' to use new data format
This commit is contained in:
committed by
Peter Rowlands (변기호)
parent
58f74ae543
commit
ec090c5680
@@ -255,17 +255,14 @@ def test_auto_push_self_remote(
|
||||
|
||||
|
||||
def test_tmp_dir_failed_checkpoint(tmp_dir, scm, dvc, failed_checkpoint_stage, caplog):
|
||||
baseline = scm.get_rev()
|
||||
|
||||
results = dvc.experiments.run(
|
||||
dvc.experiments.run(
|
||||
failed_checkpoint_stage.addressing, params=["foo=2"], tmp_dir=True
|
||||
)
|
||||
exp = first(results)
|
||||
|
||||
result = dvc.experiments.show()[baseline]
|
||||
# Assert 4 rows: baseline, 2 checkpoints, and final commit
|
||||
assert len(result) == 4
|
||||
assert exp in result
|
||||
result = dvc.experiments.show()[1]
|
||||
assert len(result.experiments) == 1
|
||||
# Assert 2 checkpoints and final commit
|
||||
assert len(result.experiments[0]) == 3
|
||||
assert (
|
||||
"Checkpoint stage 'failed-checkpoint-file' was interrupted remaining "
|
||||
"stages in pipeline will not be reproduced." in caplog.text
|
||||
|
||||
+287
-464
@@ -1,21 +1,17 @@
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
from datetime import datetime
|
||||
from unittest.mock import ANY
|
||||
|
||||
import pytest
|
||||
from funcy import first, get_in
|
||||
from funcy import first
|
||||
from scmrepo.exceptions import SCMError
|
||||
|
||||
from dvc.cli import main
|
||||
from dvc.repo.experiments.executor.base import BaseExecutor, ExecutorInfo, TaskStatus
|
||||
from dvc.repo.experiments.queue.base import QueueEntry
|
||||
from dvc.repo.experiments.refs import CELERY_STASH, ExpRefInfo
|
||||
from dvc.repo.experiments.show import _CachedError
|
||||
from dvc.repo.experiments.refs import CELERY_STASH
|
||||
from dvc.repo.experiments.utils import EXEC_PID_DIR, EXEC_TMP_DIR, exp_refs_by_rev
|
||||
from dvc.utils import relpath
|
||||
from dvc.utils.serialize import YAMLFileCorruptedError
|
||||
|
||||
LOCK_CONTENTS = {
|
||||
"read": {
|
||||
@@ -41,42 +37,73 @@ def make_executor_info(**kwargs):
|
||||
return ExecutorInfo(**kwargs)
|
||||
|
||||
|
||||
def make_executor(local=None, **kwargs):
|
||||
if local:
|
||||
local_executor = {
|
||||
"root": ANY,
|
||||
"log": ANY,
|
||||
"pid": ANY,
|
||||
"returncode": ANY,
|
||||
"task_id": ANY,
|
||||
}
|
||||
local_executor.update(local)
|
||||
else:
|
||||
local_executor = ANY
|
||||
data = {
|
||||
"state": ANY,
|
||||
"local": local_executor,
|
||||
"name": ANY,
|
||||
}
|
||||
data.update(kwargs)
|
||||
return data
|
||||
|
||||
|
||||
def make_data(params=None, **kwargs):
|
||||
params = {"data": params or {"foo": 1}}
|
||||
data = {
|
||||
"rev": ANY,
|
||||
"deps": {
|
||||
"copy.py": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
}
|
||||
},
|
||||
"metrics": {"metrics.yaml": params},
|
||||
"outs": {},
|
||||
"params": {"params.yaml": params},
|
||||
"timestamp": ANY,
|
||||
"meta": ANY,
|
||||
}
|
||||
data.update(kwargs)
|
||||
return data
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_branch_and_tag_name(tmp_dir, scm, dvc, exp_stage):
|
||||
with tmp_dir.branch("new/branch", new=True):
|
||||
tmp_dir.scm_gen("branch", "branch", "commit")
|
||||
branch_rev = scm.get_rev()
|
||||
|
||||
result = dvc.experiments.show(all_branches=True)
|
||||
assert result[branch_rev]["baseline"]["data"]["name"] == "new/branch"
|
||||
expected = [None, "master", "new/branch"]
|
||||
assert [exp.name for exp in result] == expected
|
||||
|
||||
scm.tag("new/tag")
|
||||
tag_rev = scm.get_rev()
|
||||
result = dvc.experiments.show(all_tags=True)
|
||||
assert result[tag_rev]["baseline"]["data"]["name"] == "new/tag"
|
||||
with scm.detach_head(tag_rev):
|
||||
result = dvc.experiments.show(all_tags=True)
|
||||
expected = [None, "new/tag"]
|
||||
assert [exp.name for exp in result] == expected
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_simple(tmp_dir, scm, dvc, exp_stage):
|
||||
assert dvc.experiments.show()["workspace"] == {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"rev": "workspace",
|
||||
"deps": {
|
||||
"copy.py": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
}
|
||||
},
|
||||
"metrics": {"metrics.yaml": {"data": {"foo": 1}}},
|
||||
"outs": {},
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"timestamp": None,
|
||||
}
|
||||
}
|
||||
assert dvc.experiments.show()[0].dumpd() == {
|
||||
"rev": "workspace",
|
||||
"name": None,
|
||||
"data": make_data(rev="workspace"),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
|
||||
|
||||
@@ -88,39 +115,33 @@ def test_show_experiment(tmp_dir, scm, dvc, exp_stage, workspace):
|
||||
scm.gitpython.repo.rev_parse(baseline_rev).committed_date
|
||||
)
|
||||
|
||||
dvc.experiments.run(exp_stage.addressing, params=["foo=2"], tmp_dir=not workspace)
|
||||
exp_rev = first(
|
||||
dvc.experiments.run(
|
||||
exp_stage.addressing, params=["foo=2"], tmp_dir=not workspace
|
||||
)
|
||||
)
|
||||
results = dvc.experiments.show()
|
||||
|
||||
expected_baseline = {
|
||||
"data": {
|
||||
"rev": ANY,
|
||||
"deps": {
|
||||
"copy.py": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
}
|
||||
},
|
||||
"metrics": {"metrics.yaml": {"data": {"foo": 1}}},
|
||||
"outs": {},
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"timestamp": timestamp,
|
||||
"name": "master",
|
||||
}
|
||||
assert results[1].dumpd() == {
|
||||
"rev": baseline_rev,
|
||||
"name": "master",
|
||||
"data": make_data(rev=baseline_rev, timestamp=timestamp),
|
||||
"error": None,
|
||||
"experiments": [
|
||||
{
|
||||
"revs": [
|
||||
{
|
||||
"rev": exp_rev,
|
||||
"name": ANY,
|
||||
"data": make_data(rev=exp_rev, params={"foo": 2}),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
],
|
||||
"executor": None,
|
||||
"name": ANY,
|
||||
}
|
||||
],
|
||||
}
|
||||
expected_params = {"data": {"foo": 2}}
|
||||
|
||||
assert set(results.keys()) == {"workspace", baseline_rev}
|
||||
experiments = results[baseline_rev]
|
||||
assert len(experiments) == 2
|
||||
for rev, exp in experiments.items():
|
||||
if rev == "baseline":
|
||||
assert exp == expected_baseline
|
||||
else:
|
||||
assert exp["data"]["metrics"]["metrics.yaml"] == expected_params
|
||||
assert exp["data"]["params"]["params.yaml"] == expected_params
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
@@ -132,12 +153,28 @@ def test_show_queued(tmp_dir, scm, dvc, exp_stage):
|
||||
)
|
||||
exp_rev = dvc.experiments.scm.resolve_rev(f"{CELERY_STASH}@{{0}}")
|
||||
|
||||
results = dvc.experiments.show()[baseline_rev]
|
||||
assert len(results) == 2
|
||||
exp = results[exp_rev]["data"]
|
||||
assert exp["name"] == "test_name"
|
||||
assert exp["status"] == "Queued"
|
||||
assert exp["params"]["params.yaml"] == {"data": {"foo": 2}}
|
||||
results = dvc.experiments.show()
|
||||
assert results[1].dumpd() == {
|
||||
"rev": baseline_rev,
|
||||
"name": "master",
|
||||
"data": make_data(rev=baseline_rev),
|
||||
"error": None,
|
||||
"experiments": [
|
||||
{
|
||||
"revs": [
|
||||
{
|
||||
"rev": exp_rev,
|
||||
"name": "test_name",
|
||||
"data": make_data(rev=exp_rev, params={"foo": 2}, metrics=ANY),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
],
|
||||
"executor": make_executor(state="queued"),
|
||||
"name": "test_name",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
# test that only queued experiments for the current baseline are returned
|
||||
tmp_dir.gen("foo", "foo")
|
||||
@@ -148,99 +185,85 @@ def test_show_queued(tmp_dir, scm, dvc, exp_stage):
|
||||
dvc.experiments.run(exp_stage.addressing, params=["foo=3"], queue=True)
|
||||
exp_rev = dvc.experiments.scm.resolve_rev(f"{CELERY_STASH}@{{0}}")
|
||||
|
||||
results = dvc.experiments.show()[new_rev]
|
||||
assert len(results) == 2
|
||||
exp = results[exp_rev]["data"]
|
||||
assert exp["status"] == "Queued"
|
||||
assert exp["params"]["params.yaml"] == {"data": {"foo": 3}}
|
||||
results = dvc.experiments.show()
|
||||
assert results[1].dumpd() == {
|
||||
"rev": new_rev,
|
||||
"name": "master",
|
||||
"data": make_data(rev=new_rev),
|
||||
"error": None,
|
||||
"experiments": [
|
||||
{
|
||||
"revs": [
|
||||
{
|
||||
"rev": exp_rev,
|
||||
"name": ANY,
|
||||
"data": make_data(rev=exp_rev, params={"foo": 3}, metrics=ANY),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
],
|
||||
"executor": make_executor(state="queued"),
|
||||
"name": ANY,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_failed_experiment(tmp_dir, scm, dvc, failed_exp_stage, test_queue):
|
||||
baseline_rev = scm.get_rev()
|
||||
timestamp = datetime.fromtimestamp(
|
||||
scm.gitpython.repo.rev_parse(baseline_rev).committed_date
|
||||
)
|
||||
|
||||
dvc.experiments.run(
|
||||
failed_exp_stage.addressing, params=["foo=2"], queue=True, name="show-failed"
|
||||
)
|
||||
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(run_all=True)
|
||||
test_queue.wait(["show-failed"])
|
||||
experiments = dvc.experiments.show()[baseline_rev]
|
||||
|
||||
expected_baseline = {
|
||||
"data": {
|
||||
"rev": ANY,
|
||||
"deps": {
|
||||
"copy.py": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
}
|
||||
},
|
||||
"metrics": {},
|
||||
"outs": {},
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"timestamp": timestamp,
|
||||
"name": "master",
|
||||
}
|
||||
results = dvc.experiments.show()
|
||||
assert results[1].dumpd() == {
|
||||
"rev": baseline_rev,
|
||||
"name": "master",
|
||||
"data": make_data(rev=baseline_rev, metrics=ANY),
|
||||
"error": None,
|
||||
"experiments": [
|
||||
{
|
||||
"revs": [
|
||||
{
|
||||
"rev": exp_rev,
|
||||
"name": ANY,
|
||||
"data": make_data(rev=exp_rev, params={"foo": 2}, metrics=ANY),
|
||||
"error": {"msg": "Experiment run failed", "type": ANY},
|
||||
"experiments": None,
|
||||
}
|
||||
],
|
||||
"executor": make_executor(
|
||||
state="failed",
|
||||
local={"returncode": 255},
|
||||
),
|
||||
"name": ANY,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
expected_failed = {
|
||||
"data": {
|
||||
"rev": ANY,
|
||||
"timestamp": ANY,
|
||||
"params": {"params.yaml": {"data": {"foo": 2}}},
|
||||
"deps": {"copy.py": {"hash": None, "size": None, "nfiles": None}},
|
||||
"metrics": {},
|
||||
"outs": {},
|
||||
"status": "Failed",
|
||||
"executor": None,
|
||||
"error": {
|
||||
"msg": "Experiment run failed.",
|
||||
"type": "",
|
||||
},
|
||||
"name": ANY,
|
||||
}
|
||||
}
|
||||
|
||||
assert len(experiments) == 2
|
||||
for rev, exp in experiments.items():
|
||||
if rev == "baseline":
|
||||
assert exp == expected_baseline
|
||||
else:
|
||||
assert rev == exp_rev
|
||||
assert exp == expected_failed
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
@pytest.mark.parametrize("workspace", [True, False])
|
||||
def test_show_checkpoint(tmp_dir, scm, dvc, checkpoint_stage, capsys, workspace):
|
||||
baseline_rev = scm.get_rev()
|
||||
results = dvc.experiments.run(
|
||||
checkpoint_stage.addressing, params=["foo=2"], tmp_dir=not workspace
|
||||
)
|
||||
exp_rev = first(results)
|
||||
|
||||
results = dvc.experiments.show()[baseline_rev]
|
||||
# Assert 4 rows: baseline, 2 checkpoints, and final commit
|
||||
assert len(results) == checkpoint_stage.iterations + 2
|
||||
|
||||
checkpoints = []
|
||||
for rev, exp in results.items():
|
||||
if rev != "baseline":
|
||||
checkpoints.append(rev)
|
||||
assert exp["data"]["checkpoint_tip"] == exp_rev
|
||||
baseline = dvc.experiments.show()[1]
|
||||
assert baseline.data.meta.get("has_checkpoints")
|
||||
checkpoints = first(baseline.experiments)
|
||||
# 2 checkpoints + final commit
|
||||
assert len(checkpoints) == checkpoint_stage.iterations + 1
|
||||
assert first(checkpoints).rev == exp_rev
|
||||
|
||||
capsys.readouterr()
|
||||
assert main(["exp", "show", "--no-pager"]) == 0
|
||||
cap = capsys.readouterr()
|
||||
|
||||
for i, rev in enumerate(checkpoints):
|
||||
for i, exp in enumerate(checkpoints):
|
||||
rev = exp.rev
|
||||
if i == 0:
|
||||
name = dvc.experiments.get_exact_name([rev])[rev]
|
||||
name = f"{rev[:7]} [{name}]"
|
||||
@@ -254,44 +277,6 @@ def test_show_checkpoint(tmp_dir, scm, dvc, checkpoint_stage, capsys, workspace)
|
||||
assert f"{fs} {name}" in cap.out
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
@pytest.mark.parametrize("workspace", [True, False])
|
||||
def test_show_checkpoint_branch(tmp_dir, scm, dvc, checkpoint_stage, capsys, 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)
|
||||
|
||||
dvc.experiments.apply(branch_rev)
|
||||
results = dvc.experiments.run(
|
||||
checkpoint_stage.addressing,
|
||||
checkpoint_resume=branch_rev,
|
||||
params=["foo=100"],
|
||||
tmp_dir=not workspace,
|
||||
)
|
||||
checkpoint_b = first(results)
|
||||
|
||||
capsys.readouterr()
|
||||
assert main(["exp", "show", "--no-pager"]) == 0
|
||||
cap = capsys.readouterr()
|
||||
|
||||
for rev in (checkpoint_a, checkpoint_b):
|
||||
ref = dvc.experiments.get_branch_by_rev(rev)
|
||||
ref_info = ExpRefInfo.from_ref(ref)
|
||||
name = f"{rev[:7]} [{ref_info.name}]"
|
||||
assert f"╓ {name}" in cap.out
|
||||
assert f"({branch_rev[:7]})" in cap.out
|
||||
|
||||
|
||||
def test_show_filter(
|
||||
tmp_dir,
|
||||
scm,
|
||||
@@ -373,19 +358,21 @@ def test_show_multiple_commits(tmp_dir, scm, dvc, exp_stage):
|
||||
|
||||
dvc.experiments.show(num=-2)
|
||||
|
||||
expected = {"workspace", init_rev, next_rev}
|
||||
expected = ["workspace", next_rev, init_rev]
|
||||
results = dvc.experiments.show(num=2)
|
||||
assert set(results.keys()) == expected
|
||||
assert [exp.rev for exp in results] == expected
|
||||
|
||||
expected = {"workspace"} | set(scm.branch_revs("master"))
|
||||
expected = ["workspace", *scm.branch_revs("master")]
|
||||
results = dvc.experiments.show(all_commits=True)
|
||||
assert set(results.keys()) == expected
|
||||
assert [exp.rev for exp in results] == expected
|
||||
|
||||
results = dvc.experiments.show(num=100)
|
||||
assert set(results.keys()) == expected
|
||||
assert [exp.rev for exp in results] == expected
|
||||
|
||||
|
||||
def test_show_sort(tmp_dir, scm, dvc, exp_stage, caplog):
|
||||
dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
assert main(["exp", "show", "--no-pager", "--sort-by=bar"]) != 0
|
||||
assert "Unknown sort column" in caplog.text
|
||||
@@ -408,14 +395,20 @@ def test_show_sort(tmp_dir, scm, dvc, exp_stage, caplog):
|
||||
(TaskStatus.FAILED, False),
|
||||
],
|
||||
)
|
||||
def test_show_running_workspace(
|
||||
def test_show_running(
|
||||
tmp_dir, scm, dvc, exp_stage, capsys, caplog, status, pid_exists, mocker
|
||||
):
|
||||
from dvc.rwlock import RWLOCK_FILE
|
||||
from dvc_task.proc.process import ProcessInfo
|
||||
|
||||
baseline_rev = scm.get_rev()
|
||||
pid_dir = os.path.join(dvc.tmp_dir, EXEC_TMP_DIR, EXEC_PID_DIR)
|
||||
lock_file = relpath(os.path.join(dvc.tmp_dir, RWLOCK_FILE), str(tmp_dir))
|
||||
info = make_executor_info(location=BaseExecutor.DEFAULT_LOCATION, status=status)
|
||||
info = make_executor_info(
|
||||
location=BaseExecutor.DEFAULT_LOCATION,
|
||||
status=status,
|
||||
baseline_rev=baseline_rev,
|
||||
)
|
||||
pidfile = os.path.join(
|
||||
pid_dir,
|
||||
"workspace",
|
||||
@@ -425,195 +418,42 @@ def test_show_running_workspace(
|
||||
(tmp_dir / pidfile).dump_json(info.asdict())
|
||||
(tmp_dir / lock_file).dump_json(LOCK_CONTENTS)
|
||||
|
||||
mocker.patch.object(ProcessInfo, "load", return_value=mocker.Mock(pid=123))
|
||||
mocker.patch("psutil.pid_exists", return_value=pid_exists)
|
||||
|
||||
assert dvc.experiments.show().get("workspace") == {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"rev": "workspace",
|
||||
"deps": {
|
||||
"copy.py": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
}
|
||||
},
|
||||
"metrics": {"metrics.yaml": {"data": {"foo": 1}}},
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"outs": {},
|
||||
"status": (
|
||||
"Running"
|
||||
if status == TaskStatus.RUNNING and pid_exists
|
||||
else "Success"
|
||||
),
|
||||
"executor": (
|
||||
info.location
|
||||
if status == TaskStatus.RUNNING and pid_exists
|
||||
else None
|
||||
),
|
||||
"timestamp": None,
|
||||
tempdir_active = mocker.spy(dvc.experiments.tempdir_queue, "collect_active_data")
|
||||
celery_active = mocker.spy(dvc.experiments.celery_queue, "collect_active_data")
|
||||
results = dvc.experiments.show()
|
||||
assert results[1].dumpd() == {
|
||||
"rev": ANY,
|
||||
"name": "master",
|
||||
"data": make_data(),
|
||||
"error": None,
|
||||
"experiments": [
|
||||
{
|
||||
"revs": ANY,
|
||||
"executor": make_executor(state="running"),
|
||||
"name": ANY,
|
||||
}
|
||||
}
|
||||
]
|
||||
if pid_exists
|
||||
else None,
|
||||
}
|
||||
capsys.readouterr()
|
||||
assert main(["exp", "show", "--csv"]) == 0
|
||||
cap = capsys.readouterr()
|
||||
if status == TaskStatus.RUNNING:
|
||||
if pid_exists:
|
||||
assert "Running" in cap.out
|
||||
assert info.location in cap.out
|
||||
else:
|
||||
cmd = LOCK_CONTENTS["read"]["data/MNIST"][0]["cmd"]
|
||||
pid = LOCK_CONTENTS["read"]["data/MNIST"][0]["pid"]
|
||||
assert (
|
||||
f"Process '{cmd}' with (Pid {pid}), in RWLock-file "
|
||||
f"'{lock_file}' had been killed." in caplog.text
|
||||
)
|
||||
assert f"Delete corrupted RWLock-file '{lock_file}'" in caplog.text
|
||||
|
||||
|
||||
def test_show_running_tempdir(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
run_results = dvc.experiments.run(
|
||||
exp_stage.addressing, params=["foo=2"], tmp_dir=True
|
||||
)
|
||||
exp_rev = first(run_results)
|
||||
exp_ref = first(exp_refs_by_rev(scm, exp_rev))
|
||||
|
||||
queue = dvc.experiments.tempdir_queue
|
||||
stash_rev = "abc123"
|
||||
entries = [
|
||||
QueueEntry(
|
||||
str(tmp_dir / ".dvc" / "tmp" / "foo"),
|
||||
str(tmp_dir / ".dvc" / "tmp" / "foo"),
|
||||
str(exp_ref),
|
||||
stash_rev,
|
||||
exp_ref.baseline_sha,
|
||||
None,
|
||||
exp_ref.name,
|
||||
None,
|
||||
)
|
||||
]
|
||||
mocker.patch.object(
|
||||
dvc.experiments.tempdir_queue,
|
||||
"iter_active",
|
||||
return_value=entries,
|
||||
)
|
||||
info = make_executor_info(location=BaseExecutor.DEFAULT_LOCATION)
|
||||
pidfile = queue.get_infofile_path(stash_rev)
|
||||
os.makedirs(os.path.dirname(pidfile), exist_ok=True)
|
||||
(tmp_dir / pidfile).dump_json(info.asdict())
|
||||
mock_fetch = mocker.patch.object(
|
||||
dvc.experiments.tempdir_queue,
|
||||
"get_running_exps",
|
||||
return_value={exp_rev: info.asdict()},
|
||||
)
|
||||
|
||||
results = dvc.experiments.show()
|
||||
mock_fetch.assert_has_calls(
|
||||
[mocker.call(True)],
|
||||
)
|
||||
exp_data = get_in(results, [baseline_rev, exp_rev, "data"])
|
||||
assert exp_data["status"] == "Running"
|
||||
assert exp_data["executor"] == info.location
|
||||
|
||||
assert results["workspace"]["baseline"]["data"]["status"] == "Success"
|
||||
|
||||
|
||||
def test_show_running_celery(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
dvc.experiments.run(exp_stage.addressing, params=["foo=2"], queue=True)
|
||||
exp_rev = dvc.experiments.scm.resolve_rev(f"{CELERY_STASH}@{{0}}")
|
||||
|
||||
queue = dvc.experiments.celery_queue
|
||||
entries = list(queue.iter_queued())
|
||||
mocker.patch.object(
|
||||
dvc.experiments.celery_queue,
|
||||
"iter_active",
|
||||
return_value=entries,
|
||||
)
|
||||
info = make_executor_info(location=BaseExecutor.DEFAULT_LOCATION)
|
||||
pidfile = queue.get_infofile_path(entries[0].stash_rev)
|
||||
os.makedirs(os.path.dirname(pidfile), exist_ok=True)
|
||||
(tmp_dir / pidfile).dump_json(info.asdict())
|
||||
|
||||
results = dvc.experiments.show()
|
||||
exp_data = get_in(results, [baseline_rev, exp_rev, "data"])
|
||||
assert exp_data["status"] == "Running"
|
||||
assert exp_data["executor"] == info.location
|
||||
|
||||
assert results["workspace"]["baseline"]["data"]["status"] == "Success"
|
||||
|
||||
|
||||
def test_show_running_checkpoint(
|
||||
tmp_dir, scm, dvc, checkpoint_stage, mocker, test_queue
|
||||
):
|
||||
from dvc.repo.experiments.executor.local import TempDirExecutor
|
||||
|
||||
baseline_rev = scm.get_rev()
|
||||
dvc.experiments.run(
|
||||
checkpoint_stage.addressing, params=["foo=2"], queue=True, name="foo"
|
||||
)
|
||||
queue = dvc.experiments.celery_queue
|
||||
entries = list(queue.iter_queued())
|
||||
|
||||
run_results = dvc.experiments.run(run_all=True)
|
||||
test_queue.wait(["foo"])
|
||||
checkpoint_rev = first(run_results)
|
||||
exp_ref = first(exp_refs_by_rev(scm, checkpoint_rev))
|
||||
|
||||
mocker.patch.object(
|
||||
dvc.experiments.celery_queue,
|
||||
"iter_active",
|
||||
return_value=entries,
|
||||
)
|
||||
mocker.patch.object(
|
||||
dvc.experiments.celery_queue,
|
||||
"iter_failed",
|
||||
return_value=[],
|
||||
)
|
||||
pidfile = queue.get_infofile_path(entries[0].stash_rev)
|
||||
info = make_executor_info(
|
||||
git_url="foo.git",
|
||||
baseline_rev=baseline_rev,
|
||||
location=TempDirExecutor.DEFAULT_LOCATION,
|
||||
status=TaskStatus.RUNNING,
|
||||
)
|
||||
os.makedirs(os.path.dirname(pidfile), exist_ok=True)
|
||||
(tmp_dir / pidfile).dump_json(info.asdict())
|
||||
|
||||
mocker.patch.object(BaseExecutor, "fetch_exps", return_value=[str(exp_ref)])
|
||||
|
||||
results = dvc.experiments.show()
|
||||
|
||||
checkpoint_res = get_in(results, [baseline_rev, checkpoint_rev, "data"])
|
||||
assert checkpoint_res["status"] == "Running"
|
||||
assert checkpoint_res["executor"] == info.location
|
||||
|
||||
assert results["workspace"]["baseline"]["data"]["status"] == "Success"
|
||||
tempdir_active.assert_called_once()
|
||||
celery_active.assert_called_once()
|
||||
|
||||
|
||||
def test_show_with_broken_repo(tmp_dir, scm, dvc, exp_stage, caplog):
|
||||
baseline_rev = scm.get_rev()
|
||||
exp1 = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
exp2 = dvc.experiments.run(exp_stage.addressing, params=["foo=3"])
|
||||
|
||||
dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
with open("dvc.yaml", "a", encoding="utf-8") as fd:
|
||||
fd.write("breaking the yaml!")
|
||||
|
||||
result = dvc.experiments.show()
|
||||
rev1 = first(exp1)
|
||||
rev2 = first(exp2)
|
||||
results = dvc.experiments.show()
|
||||
assert results[0].error
|
||||
assert results[0].error.type == "YAMLSyntaxError"
|
||||
|
||||
baseline = result[baseline_rev]
|
||||
|
||||
paths = ["data", "params", "params.yaml"]
|
||||
assert get_in(baseline[rev1], paths) == {"data": {"foo": 2}}
|
||||
assert get_in(baseline[rev2], paths) == {"data": {"foo": 3}}
|
||||
|
||||
paths = ["workspace", "baseline", "error"]
|
||||
assert isinstance(get_in(result, paths), (_CachedError, YAMLFileCorruptedError))
|
||||
assert "YAML file structure is corrupted" in str(get_in(result, paths))
|
||||
for exp_range in results[1].experiments:
|
||||
assert not any(exp.error for exp in exp_range)
|
||||
|
||||
|
||||
def test_show_csv(tmp_dir, scm, dvc, exp_stage, capsys):
|
||||
@@ -646,8 +486,8 @@ def test_show_csv(tmp_dir, scm, dvc, exp_stage, capsys):
|
||||
assert "metrics.yaml:foo,params.yaml:foo,copy.py" in cap.out
|
||||
assert f",workspace,baseline,,,3,3,{data_hash}" in cap.out
|
||||
assert (
|
||||
"master,{},baseline,{},,1,1,{}".format(
|
||||
baseline_rev[:7], _get_rev_isotimestamp(baseline_rev), data_hash
|
||||
",master,baseline,{},,1,1,{}".format(
|
||||
_get_rev_isotimestamp(baseline_rev), data_hash
|
||||
)
|
||||
in cap.out
|
||||
)
|
||||
@@ -810,35 +650,52 @@ def test_show_outs(tmp_dir, dvc, scm, erepo_dir, copy_script):
|
||||
|
||||
scm.commit("init")
|
||||
|
||||
outs = dvc.experiments.show()["workspace"]["baseline"]["data"]["outs"]
|
||||
assert outs == {
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
}
|
||||
results = dvc.experiments.show()
|
||||
assert results[0].dumpd() == {
|
||||
"rev": "workspace",
|
||||
"name": None,
|
||||
"data": make_data(
|
||||
params=ANY,
|
||||
outs={
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
}
|
||||
},
|
||||
),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
|
||||
tmp_dir.dvc_gen("out_add", "foo", commit="dvc add output")
|
||||
|
||||
outs = dvc.experiments.show()["workspace"]["baseline"]["data"]["outs"]
|
||||
assert outs == {
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
},
|
||||
"out_add": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
results = dvc.experiments.show()
|
||||
assert results[0].dumpd() == {
|
||||
"rev": "workspace",
|
||||
"name": None,
|
||||
"data": make_data(
|
||||
params=ANY,
|
||||
outs={
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
},
|
||||
"out_add": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
},
|
||||
),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
|
||||
with erepo_dir.chdir():
|
||||
@@ -846,29 +703,38 @@ def test_show_outs(tmp_dir, dvc, scm, erepo_dir, copy_script):
|
||||
|
||||
dvc.imp(os.fspath(erepo_dir), "out", "out_imported")
|
||||
|
||||
outs = dvc.experiments.show()["workspace"]["baseline"]["data"]["outs"]
|
||||
assert outs == {
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
},
|
||||
"out_add": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
"out_imported": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
results = dvc.experiments.show()
|
||||
assert results[0].dumpd() == {
|
||||
"rev": "workspace",
|
||||
"name": None,
|
||||
"data": make_data(
|
||||
params=ANY,
|
||||
outs={
|
||||
"out": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": False,
|
||||
},
|
||||
"out_add": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
"out_imported": {
|
||||
"hash": ANY,
|
||||
"size": ANY,
|
||||
"nfiles": None,
|
||||
"use_cache": True,
|
||||
"is_data_source": True,
|
||||
},
|
||||
},
|
||||
),
|
||||
"error": None,
|
||||
"experiments": None,
|
||||
}
|
||||
|
||||
|
||||
@@ -927,12 +793,7 @@ def test_metrics_renaming(tmp_dir, dvc, scm, capsys, copy_script):
|
||||
scm.gitpython.repo.rev_parse(rev).committed_date
|
||||
).isoformat()
|
||||
|
||||
assert (
|
||||
"master,{},baseline,{},,1,,1".format(
|
||||
scores_rev[:7], _get_rev_isotimestamp(scores_rev)
|
||||
)
|
||||
in cap.out
|
||||
)
|
||||
assert f",master,baseline,{_get_rev_isotimestamp(scores_rev)},,1,,1" in cap.out
|
||||
assert (
|
||||
",{},baseline,{},,,1,1".format(
|
||||
metrics_rev[:7], _get_rev_isotimestamp(metrics_rev)
|
||||
@@ -961,8 +822,6 @@ def test_show_sorted_deps(tmp_dir, dvc, scm, capsys):
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_queued_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
|
||||
dvc.experiments.run(
|
||||
exp_stage.addressing, params=["foo=2"], queue=True, name="test_name"
|
||||
)
|
||||
@@ -983,17 +842,16 @@ def test_show_queued_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
side_effect=mocker.MagicMock(side_effect=resolve_commit),
|
||||
)
|
||||
|
||||
results = dvc.experiments.show()[baseline_rev]
|
||||
results = dvc.experiments.show()[1].experiments
|
||||
assert len(results) == 2
|
||||
exp_2 = results[exp_rev_2]["data"]
|
||||
assert exp_2["status"] == "Queued"
|
||||
assert exp_2["params"]["params.yaml"] == {"data": {"foo": 2}}
|
||||
queued = results[0]
|
||||
assert queued.executor.state == "queued"
|
||||
errored = results[1]
|
||||
assert errored.revs[0].error
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_completed_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
|
||||
result_2 = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
exp_rev_2 = first(result_2)
|
||||
commit_2 = scm.resolve_commit(exp_rev_2)
|
||||
@@ -1010,49 +868,14 @@ def test_show_completed_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
"resolve_commit",
|
||||
side_effect=mocker.MagicMock(side_effect=resolve_commit),
|
||||
)
|
||||
experiments = dvc.experiments.show()[baseline_rev]
|
||||
assert len(experiments) == 2
|
||||
assert exp_rev_2 in experiments
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_checkpoint_error(tmp_dir, scm, dvc, checkpoint_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
results = dvc.experiments.run(checkpoint_stage.addressing, params=["foo=2"])
|
||||
exp_rev = first(results)
|
||||
exp_ref = str(first(exp_refs_by_rev(scm, exp_rev)))
|
||||
|
||||
results = dvc.experiments.show()[baseline_rev]
|
||||
# Assert 4 rows: baseline, 2 checkpoints, and final commit
|
||||
assert len(results) == checkpoint_stage.iterations + 2
|
||||
|
||||
checkpoints = {}
|
||||
for rev in results:
|
||||
if rev != "baseline":
|
||||
checkpoints[rev] = scm.resolve_commit(rev)
|
||||
checkpoints[exp_ref] = scm.resolve_commit(exp_ref)
|
||||
checkpoints[baseline_rev] = scm.resolve_commit(baseline_rev)
|
||||
|
||||
failed_rev = random.choice(list(checkpoints.keys()))
|
||||
|
||||
def resolve_commit(rev):
|
||||
if rev == failed_rev:
|
||||
raise SCMError
|
||||
return checkpoints[rev]
|
||||
|
||||
mocker.patch.object(
|
||||
scm,
|
||||
"resolve_commit",
|
||||
side_effect=mocker.MagicMock(side_effect=resolve_commit),
|
||||
)
|
||||
results = dvc.experiments.show(force=True)[baseline_rev]
|
||||
results = dvc.experiments.show()[1].experiments
|
||||
assert len(results) == 1
|
||||
assert not results[0].revs[0].error
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_baseline_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
baseline_rev = scm.get_rev()
|
||||
branch = scm.active_branch()
|
||||
|
||||
result_2 = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
exp_rev_2 = first(result_2)
|
||||
@@ -1068,7 +891,7 @@ def test_show_baseline_error(tmp_dir, scm, dvc, exp_stage, mocker):
|
||||
"resolve_commit",
|
||||
side_effect=mocker.MagicMock(side_effect=resolve_commit),
|
||||
)
|
||||
experiments = dvc.experiments.show()[baseline_rev]
|
||||
assert len(experiments) == 1
|
||||
assert experiments["baseline"]["data"] == {"name": branch}
|
||||
assert isinstance(experiments["baseline"]["error"], (SCMError, _CachedError))
|
||||
|
||||
results = dvc.experiments.show()
|
||||
assert results[1].error
|
||||
assert len(results[1].experiments) == 1
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import csv
|
||||
import pathlib
|
||||
import textwrap
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -18,7 +15,7 @@ from dvc.commands.experiments.push import CmdExperimentsPush
|
||||
from dvc.commands.experiments.remove import CmdExperimentsRemove
|
||||
from dvc.commands.experiments.run import CmdExperimentsRun
|
||||
from dvc.commands.experiments.save import CmdExperimentsSave
|
||||
from dvc.commands.experiments.show import CmdExperimentsShow, show_experiments
|
||||
from dvc.commands.experiments.show import CmdExperimentsShow
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
from dvc.repo import Repo
|
||||
from tests.utils import ANY
|
||||
@@ -422,279 +419,6 @@ def test_experiments_remove_invalid(dvc, scm, mocker, capsys, caplog):
|
||||
)
|
||||
|
||||
|
||||
def test_show_experiments_csv(capsys):
|
||||
all_experiments = {
|
||||
"workspace": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": None,
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"parent": 20170428,
|
||||
"train": {
|
||||
"n_est": 100,
|
||||
"min_split": 36,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {
|
||||
"scores.json": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"avg_prec": 0.5843640011189556,
|
||||
"roc_auc": 0.9544670443829399,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"b05eecc666734e899f79af228ff49a7ae5a18cc0": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 2, 16, 48, 14),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"parent": 20170428,
|
||||
"train": {
|
||||
"n_est": 100,
|
||||
"min_split": 2,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {
|
||||
"scores.json": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"avg_prec": 0.5325162867864254,
|
||||
"roc_auc": 0.9106964878520005,
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "master",
|
||||
}
|
||||
},
|
||||
"ae99936461d6c3092934160f8beafe66a294f98d": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"parent": 20170428,
|
||||
"train": {
|
||||
"n_est": 100,
|
||||
"min_split": 36,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Running",
|
||||
"executor": None,
|
||||
"metrics": {
|
||||
"scores.json": {
|
||||
"data": {
|
||||
"featurize": {
|
||||
"max_features": 3000,
|
||||
"ngrams": 1,
|
||||
},
|
||||
"avg_prec": 0.5843640011189556,
|
||||
"roc_auc": 0.9544670443829399,
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "exp-44136",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
show_experiments(all_experiments, precision=None, fill_value="", iso=True, csv=True)
|
||||
cap = capsys.readouterr()
|
||||
assert (
|
||||
"Experiment,rev,typ,Created,parent,State,scores.json:"
|
||||
"featurize.max_features,scores.json:featurize.ngrams,"
|
||||
"avg_prec,roc_auc,params.yaml:featurize.max_features,"
|
||||
"params.yaml:featurize.ngrams,params.yaml:parent,"
|
||||
"train.n_est,train.min_split" in cap.out
|
||||
)
|
||||
assert (
|
||||
",workspace,baseline,,,,3000,1,0.5843640011189556,0.9544670443829399,"
|
||||
"3000,1,20170428,100,36" in cap.out
|
||||
)
|
||||
assert (
|
||||
"master,b05eecc,baseline,2021-08-02T16:48:14,,,3000,1,"
|
||||
"0.5325162867864254,0.9106964878520005,3000,1,20170428,100,2" in cap.out
|
||||
)
|
||||
assert (
|
||||
"exp-44136,ae99936,branch_base,2021-08-31T14:56:55,,Running,"
|
||||
"3000,1,0.5843640011189556,0.9544670443829399,3000,1,20170428,100,36" in cap.out
|
||||
)
|
||||
|
||||
|
||||
def test_show_experiments_md(capsys):
|
||||
all_experiments = {
|
||||
"workspace": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": None,
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {"scores.json": {"data": {"bar": 0.9544670443829399}}},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
show_experiments(
|
||||
all_experiments, precision=None, fill_value="", iso=True, markdown=True
|
||||
)
|
||||
cap = capsys.readouterr()
|
||||
|
||||
assert cap.out == textwrap.dedent(
|
||||
"""\
|
||||
| Experiment | Created | bar | foo |
|
||||
|--------------|-----------|--------------------|-------|
|
||||
| workspace | | 0.9544670443829399 | 1 |\n
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sort_order", ["asc", "desc"])
|
||||
def test_show_experiments_sort_by(capsys, sort_order):
|
||||
sort_experiments = {
|
||||
"workspace": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": None,
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"foo": 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
"233b132676792d89e848e5c9c12e408d7efde78a": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 2, 16, 48, 14),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"foo": 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {},
|
||||
"name": "master",
|
||||
}
|
||||
},
|
||||
"fad0a94": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"foo": 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {},
|
||||
"name": "exp-89140",
|
||||
}
|
||||
},
|
||||
"60fcda8": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"foo": 2,
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {},
|
||||
"name": "exp-43537",
|
||||
}
|
||||
},
|
||||
"a7e9aaf": {
|
||||
"data": {
|
||||
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
|
||||
"params": {
|
||||
"params.yaml": {
|
||||
"data": {
|
||||
"foo": 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {},
|
||||
"name": "exp-4f89e",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
show_experiments(
|
||||
sort_experiments,
|
||||
precision=None,
|
||||
fill_value="",
|
||||
iso=True,
|
||||
csv=True,
|
||||
sort_by="foo",
|
||||
sort_order=sort_order,
|
||||
)
|
||||
|
||||
cap = capsys.readouterr()
|
||||
rows = list(csv.reader(cap.out.strip().split("\n")))
|
||||
# [3:] To skip header, workspace and baseline(master)
|
||||
# which are not affected by order
|
||||
params = tuple(int(row[-1]) for row in rows[3:])
|
||||
|
||||
if sort_order == "asc":
|
||||
assert params == (0, 1, 2)
|
||||
else:
|
||||
assert params == (2, 1, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("extra_args", [(), ("--run",)])
|
||||
def test_experiments_init(dvc, scm, mocker, capsys, extra_args):
|
||||
stage = mocker.Mock(outs=[], addressing="train")
|
||||
@@ -893,35 +617,6 @@ def test_experiments_init_displays_output_on_no_run(dvc, mocker, capsys, args):
|
||||
assert out.splitlines() == expected_lines
|
||||
|
||||
|
||||
def test_show_experiments_pcp(tmp_dir, mocker):
|
||||
all_experiments = {
|
||||
"workspace": {
|
||||
"baseline": {
|
||||
"data": {
|
||||
"timestamp": None,
|
||||
"params": {"params.yaml": {"data": {"foo": 1}}},
|
||||
"status": "Success",
|
||||
"executor": None,
|
||||
"metrics": {"scores.json": {"data": {"bar": 0.9544670443829399}}},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
experiments_table = mocker.patch("dvc.commands.experiments.show.experiments_table")
|
||||
td = experiments_table.return_value
|
||||
|
||||
show_experiments(all_experiments, pcp=True)
|
||||
|
||||
td.drop.assert_called_with("Created")
|
||||
td.dropna.assert_called_with("rows", how="all", subset=set())
|
||||
td.drop_duplicates.assert_called_with("rows", subset=set())
|
||||
|
||||
kwargs = td.to_parallel_coordinates.call_args[1]
|
||||
|
||||
assert kwargs["output_path"] == str(tmp_dir / "dvc_plots" / "index.html")
|
||||
assert kwargs["color_by"] == "Experiment"
|
||||
|
||||
|
||||
def test_experiments_save(dvc, scm, mocker):
|
||||
cli_args = parse_args(["exp", "save", "--name", "exp-name", "--force"])
|
||||
assert cli_args.func == CmdExperimentsSave
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
import pytest
|
||||
from funcy import first
|
||||
|
||||
from dvc.repo.experiments.show import (
|
||||
ExpStatus,
|
||||
get_branch_names,
|
||||
move_properties_to_head,
|
||||
update_names,
|
||||
)
|
||||
|
||||
|
||||
def test_get_show_branch(tmp_dir, scm, dvc, exp_stage):
|
||||
new_branch = "new"
|
||||
|
||||
baseline = scm.get_rev()
|
||||
base_branch = scm.active_branch()
|
||||
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
|
||||
exp_a = first(results)
|
||||
dvc.experiments.branch(exp_a, new_branch)
|
||||
|
||||
scm.checkout(new_branch, force=True)
|
||||
|
||||
result = {
|
||||
"workspace": {"baseline": {"data": {}}},
|
||||
exp_a: {"baseline": {"data": {}}},
|
||||
baseline: {"baseline": {"data": {}}, exp_a: {"data": {}}},
|
||||
}
|
||||
|
||||
branch_names = get_branch_names(scm, ["workspace", exp_a, baseline])
|
||||
assert branch_names == {exp_a: new_branch, baseline: base_branch}
|
||||
|
||||
update_names(dvc, branch_names, result)
|
||||
assert result[exp_a]["baseline"]["data"] == {"name": new_branch}
|
||||
assert result[baseline]["baseline"]["data"] == {"name": base_branch}
|
||||
assert result[baseline][exp_a]["data"] == {"name": new_branch}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"res_in,res_out",
|
||||
[
|
||||
(
|
||||
{
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"data": {
|
||||
"checkpoint_tip": "3",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"data": {
|
||||
"checkpoint_tip": "3",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "b",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"data": {
|
||||
"checkpoint_tip": "3",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "b",
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"data": {
|
||||
"checkpoint_tip": "3",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"0": {"error": {"msg": "something"}},
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"3": {"data": {"name": "b"}},
|
||||
},
|
||||
{
|
||||
"0": {"error": {"msg": "something"}},
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"3": {"data": {"name": "b"}},
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "b",
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"1": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": "local",
|
||||
"status": ExpStatus.Running.name,
|
||||
"name": "a",
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
"name": "b",
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"data": {
|
||||
"checkpoint_tip": "1",
|
||||
"executor": None,
|
||||
"status": ExpStatus.Success.name,
|
||||
}
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_move_properties_to_head(res_in, res_out):
|
||||
move_properties_to_head({"baseline": res_in})
|
||||
assert res_in == res_out
|
||||
Reference in New Issue
Block a user