run: raise error when command is not specified (#3850)

* run: raise error when command is not specified

* tests: adjust tests/func/plots/test_plots.py

* tests: adjust tests/func/plots/test_diff.py

* tests: add command to metrics/plots/params

* tests: fix test_remote.py

* tests: fix test_ls.py

* tests: fix test_repro* and test_run*

* tests: fix script in test_ls, was failing on Win
This commit is contained in:
Saugat Pachhai
2020-05-27 12:13:26 +03:00
committed by GitHub
parent 10f2bb93fa
commit e8f6cd7f5b
15 changed files with 374 additions and 182 deletions
+3
View File
@@ -45,6 +45,9 @@ def run(self, fname=None, no_exec=False, single_stage=False, **kwargs):
from dvc.stage import PipelineStage, Stage, create_stage
from dvc.dvcfile import Dvcfile, PIPELINE_FILE
if not kwargs.get("cmd"):
raise InvalidArgumentError("command is not specified")
stage_cls = PipelineStage
path = PIPELINE_FILE
stage_name = kwargs.get("name")
+1
View File
@@ -0,0 +1 @@
from tests.func.plots import run_copy_metrics # noqa: F401
+45 -37
View File
@@ -3,11 +3,10 @@ import json
import yaml
def test_metrics_diff_simple(tmp_dir, scm, dvc):
def test_metrics_diff_simple(tmp_dir, scm, dvc, run_copy_metrics):
def _gen(val):
tmp_dir.gen({"m.yaml": str(val)})
dvc.run(cmd="", metrics=["m.yaml"], single_stage=True)
dvc.scm.add(["m.yaml.dvc"])
tmp_dir.gen({"m_temp.yaml": str(val)})
run_copy_metrics("m_temp.yaml", "m.yaml", metrics=["m.yaml"])
dvc.scm.commit(str(val))
_gen(1)
@@ -19,13 +18,13 @@ def test_metrics_diff_simple(tmp_dir, scm, dvc):
assert dvc.metrics.diff(a_rev="HEAD~2") == expected
def test_metrics_diff_yaml(tmp_dir, scm, dvc):
def test_metrics_diff_yaml(tmp_dir, scm, dvc, run_copy_metrics):
def _gen(val):
metrics = {"a": {"b": {"c": val, "d": 1, "e": str(val)}}}
tmp_dir.gen({"m.yaml": yaml.dump(metrics)})
dvc.run(cmd="", metrics=["m.yaml"], single_stage=True)
dvc.scm.add(["m.yaml.dvc"])
dvc.scm.commit(str(val))
tmp_dir.gen({"m_temp.yaml": yaml.dump(metrics)})
run_copy_metrics(
"m_temp.yaml", "m.yaml", metrics=["m.yaml"], commit=str(val)
)
_gen(1)
_gen(2)
@@ -36,13 +35,13 @@ def test_metrics_diff_yaml(tmp_dir, scm, dvc):
assert dvc.metrics.diff(a_rev="HEAD~2") == expected
def test_metrics_diff_json(tmp_dir, scm, dvc):
def test_metrics_diff_json(tmp_dir, scm, dvc, run_copy_metrics):
def _gen(val):
metrics = {"a": {"b": {"c": val, "d": 1, "e": str(val)}}}
tmp_dir.gen({"m.json": json.dumps(metrics)})
dvc.run(cmd="", metrics=["m.json"], single_stage=True)
dvc.scm.add(["m.json.dvc"])
dvc.scm.commit(str(val))
tmp_dir.gen({"m_temp.json": json.dumps(metrics)})
run_copy_metrics(
"m_temp.json", "m.json", metrics=["m.json"], commit=str(val)
)
_gen(1)
_gen(2)
@@ -52,13 +51,13 @@ def test_metrics_diff_json(tmp_dir, scm, dvc):
assert dvc.metrics.diff(a_rev="HEAD~2") == expected
def test_metrics_diff_json_unchanged(tmp_dir, scm, dvc):
def test_metrics_diff_json_unchanged(tmp_dir, scm, dvc, run_copy_metrics):
def _gen(val):
metrics = {"a": {"b": {"c": val, "d": 1, "e": str(val)}}}
tmp_dir.gen({"m.json": json.dumps(metrics)})
dvc.run(cmd="", metrics=["m.json"], single_stage=True)
dvc.scm.add(["m.json.dvc"])
dvc.scm.commit(str(val))
tmp_dir.gen({"m_temp.json": json.dumps(metrics)})
run_copy_metrics(
"m_temp.json", "m.json", metrics=["m.json"], commit=str(val)
)
_gen(1)
_gen(2)
@@ -67,12 +66,15 @@ def test_metrics_diff_json_unchanged(tmp_dir, scm, dvc):
assert dvc.metrics.diff(a_rev="HEAD~2") == {}
def test_metrics_diff_broken_json(tmp_dir, scm, dvc):
def test_metrics_diff_broken_json(tmp_dir, scm, dvc, run_copy_metrics):
metrics = {"a": {"b": {"c": 1, "d": 1, "e": "3"}}}
tmp_dir.gen({"m.json": json.dumps(metrics)})
dvc.run(cmd="", metrics_no_cache=["m.json"], single_stage=True)
dvc.scm.add(["m.json.dvc", "m.json"])
dvc.scm.commit("add metrics")
tmp_dir.gen({"m_temp.json": json.dumps(metrics)})
run_copy_metrics(
"m_temp.json",
"m.json",
metrics_no_cache=["m.json"],
commit="add metrics",
)
(tmp_dir / "m.json").write_text(json.dumps(metrics) + "ma\nlformed\n")
@@ -89,10 +91,10 @@ def test_metrics_diff_no_metrics(tmp_dir, scm, dvc):
assert dvc.metrics.diff(a_rev="HEAD~1") == {}
def test_metrics_diff_new_metric(tmp_dir, scm, dvc):
def test_metrics_diff_new_metric(tmp_dir, scm, dvc, run_copy_metrics):
metrics = {"a": {"b": {"c": 1, "d": 1, "e": "3"}}}
tmp_dir.gen({"m.json": json.dumps(metrics)})
dvc.run(cmd="", metrics_no_cache=["m.json"], single_stage=True)
tmp_dir.gen({"m_temp.json": json.dumps(metrics)})
run_copy_metrics("m_temp.json", "m.json", metrics_no_cache=["m.json"])
assert dvc.metrics.diff() == {
"m.json": {
@@ -102,12 +104,15 @@ def test_metrics_diff_new_metric(tmp_dir, scm, dvc):
}
def test_metrics_diff_deleted_metric(tmp_dir, scm, dvc):
def test_metrics_diff_deleted_metric(tmp_dir, scm, dvc, run_copy_metrics):
metrics = {"a": {"b": {"c": 1, "d": 1, "e": "3"}}}
tmp_dir.gen({"m.json": json.dumps(metrics)})
dvc.run(cmd="", metrics_no_cache=["m.json"], single_stage=True)
dvc.scm.add(["m.json.dvc", "m.json"])
dvc.scm.commit("add metrics")
tmp_dir.gen({"m_temp.json": json.dumps(metrics)})
run_copy_metrics(
"m_temp.json",
"m.json",
metrics_no_cache=["m.json"],
commit="add metrics",
)
(tmp_dir / "m.json").unlink()
@@ -119,11 +124,14 @@ def test_metrics_diff_deleted_metric(tmp_dir, scm, dvc):
}
def test_metrics_diff_with_unchanged(tmp_dir, scm, dvc):
tmp_dir.gen("metrics.yaml", "foo: 1\nxyz: 10")
dvc.run(metrics_no_cache=["metrics.yaml"], single_stage=True)
scm.add(["metrics.yaml", "metrics.yaml.dvc"])
scm.commit("1")
def test_metrics_diff_with_unchanged(tmp_dir, scm, dvc, run_copy_metrics):
tmp_dir.gen("metrics_temp.yaml", "foo: 1\nxyz: 10")
run_copy_metrics(
"metrics_temp.yaml",
"metrics.yaml",
metrics_no_cache=["metrics.yaml"],
commit="1",
)
tmp_dir.scm_gen("metrics.yaml", "foo: 2\nxyz: 10", commit="2")
tmp_dir.scm_gen("metrics.yaml", "foo: 3\nxyz: 10", commit="3")
+25 -17
View File
@@ -8,36 +8,44 @@ def test_show_empty(dvc):
dvc.metrics.show()
def test_show_simple(tmp_dir, dvc):
tmp_dir.gen("metrics.yaml", "1.1")
dvc.run(metrics=["metrics.yaml"], single_stage=True)
def test_show_simple(tmp_dir, dvc, run_copy_metrics):
tmp_dir.gen("metrics_t.yaml", "1.1")
run_copy_metrics(
"metrics_t.yaml", "metrics.yaml", metrics=["metrics.yaml"],
)
assert dvc.metrics.show() == {"": {"metrics.yaml": 1.1}}
def test_show(tmp_dir, dvc):
tmp_dir.gen("metrics.yaml", "foo: 1.1")
dvc.run(metrics=["metrics.yaml"], single_stage=True)
def test_show(tmp_dir, dvc, run_copy_metrics):
tmp_dir.gen("metrics_t.yaml", "foo: 1.1")
run_copy_metrics(
"metrics_t.yaml", "metrics.yaml", metrics=["metrics.yaml"],
)
assert dvc.metrics.show() == {"": {"metrics.yaml": {"foo": 1.1}}}
def test_show_multiple(tmp_dir, dvc):
tmp_dir.gen("foo", "foo: 1\n")
tmp_dir.gen("baz", "baz: 2\n")
dvc.run(fname="foo.dvc", metrics=["foo"], single_stage=True)
dvc.run(fname="baz.dvc", metrics=["baz"], single_stage=True)
def test_show_multiple(tmp_dir, dvc, run_copy_metrics):
tmp_dir.gen("foo_temp", "foo: 1\n")
tmp_dir.gen("baz_temp", "baz: 2\n")
run_copy_metrics("foo_temp", "foo", fname="foo.dvc", metrics=["foo"])
run_copy_metrics("baz_temp", "baz", fname="baz.dvc", metrics=["baz"])
assert dvc.metrics.show() == {"": {"foo": {"foo": 1}, "baz": {"baz": 2}}}
def test_show_invalid_metric(tmp_dir, dvc):
tmp_dir.gen("metrics.yaml", "foo:\n- bar\n- baz\nxyz: string")
dvc.run(metrics=["metrics.yaml"], single_stage=True)
def test_show_invalid_metric(tmp_dir, dvc, run_copy_metrics):
tmp_dir.gen("metrics_temp.yaml", "foo:\n- bar\n- baz\nxyz: string")
run_copy_metrics(
"metrics_temp.yaml", "metrics.yaml", metrics=["metrics.yaml"]
)
with pytest.raises(NoMetricsError):
dvc.metrics.show()
def test_show_branch(tmp_dir, scm, dvc):
tmp_dir.gen("metrics.yaml", "foo: 1")
dvc.run(metrics_no_cache=["metrics.yaml"], single_stage=True)
def test_show_branch(tmp_dir, scm, dvc, run_copy_metrics):
tmp_dir.gen("metrics_temp.yaml", "foo: 1")
run_copy_metrics(
"metrics_temp.yaml", "metrics.yaml", metrics_no_cache=["metrics.yaml"]
)
scm.add(["metrics.yaml", "metrics.yaml.dvc"])
scm.commit("init")
+8 -8
View File
@@ -4,7 +4,7 @@ def test_diff_no_params(tmp_dir, scm, dvc):
def test_diff_no_changes(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("bar")
assert dvc.params.diff() == {}
@@ -12,7 +12,7 @@ def test_diff_no_changes(tmp_dir, scm, dvc):
def test_diff(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("bar")
@@ -26,7 +26,7 @@ def test_diff(tmp_dir, scm, dvc):
def test_diff_new(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
assert dvc.params.diff() == {
"params.yaml": {"foo": {"old": None, "new": "bar"}}
@@ -35,7 +35,7 @@ def test_diff_new(tmp_dir, scm, dvc):
def test_diff_deleted(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("bar")
@@ -48,7 +48,7 @@ def test_diff_deleted(tmp_dir, scm, dvc):
def test_diff_deleted_config(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("bar")
@@ -61,7 +61,7 @@ def test_diff_deleted_config(tmp_dir, scm, dvc):
def test_diff_list(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo:\n- bar\n- baz")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("foo")
@@ -76,7 +76,7 @@ def test_diff_list(tmp_dir, scm, dvc):
def test_diff_dict(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo:\n bar: baz")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("foo")
@@ -89,7 +89,7 @@ def test_diff_dict(tmp_dir, scm, dvc):
def test_diff_with_unchanged(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar\nxyz: val")
dvc.run(params=["foo,xyz"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo,xyz"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("bar")
+15 -5
View File
@@ -10,14 +10,24 @@ def test_show_empty(dvc):
def test_show(tmp_dir, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
assert dvc.params.show() == {"": {"params.yaml": {"foo": "bar"}}}
def test_show_multiple(tmp_dir, dvc):
tmp_dir.gen("params.yaml", "foo: bar\nbaz: qux\n")
dvc.run(fname="foo.dvc", params=["foo"], single_stage=True)
dvc.run(fname="baz.dvc", params=["baz"], single_stage=True)
dvc.run(
cmd="echo params.yaml",
fname="foo.dvc",
params=["foo"],
single_stage=True,
)
dvc.run(
cmd="echo params.yaml",
fname="baz.dvc",
params=["baz"],
single_stage=True,
)
assert dvc.params.show() == {
"": {"params.yaml": {"foo": "bar", "baz": "qux"}}
}
@@ -25,13 +35,13 @@ def test_show_multiple(tmp_dir, dvc):
def test_show_list(tmp_dir, dvc):
tmp_dir.gen("params.yaml", "foo:\n- bar\n- baz\n")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
assert dvc.params.show() == {"": {"params.yaml": {"foo": ["bar", "baz"]}}}
def test_show_branch(tmp_dir, scm, dvc):
tmp_dir.gen("params.yaml", "foo: bar")
dvc.run(params=["foo"], single_stage=True)
dvc.run(cmd="echo params.yaml", params=["foo"], single_stage=True)
scm.add(["params.yaml", "Dvcfile"])
scm.commit("init")
+30
View File
@@ -0,0 +1,30 @@
import os
import pytest
@pytest.fixture
def run_copy_metrics(tmp_dir, run_copy):
def run(file1, file2, commit=None, tag=None, **kwargs):
stage = tmp_dir.dvc.run(
cmd=f"python copy.py {file1} {file2}",
deps=[file1],
single_stage=True,
**kwargs,
)
if hasattr(tmp_dir.dvc, "scm"):
files = [stage.path]
files += [
os.fspath(out.path_info)
for out in stage.outs
if not out.use_cache
]
tmp_dir.dvc.scm.add(files)
if commit:
tmp_dir.dvc.scm.commit(commit)
if tag:
tmp_dir.dvc.scm.tag(tag)
return stage
return run
+1
View File
@@ -0,0 +1 @@
from . import run_copy_metrics # noqa: F401
+20 -8
View File
@@ -1,20 +1,32 @@
import json
from .test_plots import PlotData, _run_with, _write_json
from .test_plots import PlotData, _write_json
def test_diff_dirty(tmp_dir, scm, dvc):
def test_diff_dirty(tmp_dir, scm, dvc, run_copy_metrics):
metric_1 = [{"y": 2}, {"y": 3}]
_write_json(tmp_dir, metric_1, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init")
_write_json(tmp_dir, metric_1, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
)
metric_2 = [{"y": 3}, {"y": 5}]
_write_json(tmp_dir, metric_2, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="second")
_write_json(tmp_dir, metric_2, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="second",
)
metric_3 = [{"y": 5}, {"y": 6}]
_write_json(tmp_dir, metric_3, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"])
_write_json(tmp_dir, metric_3, "metric_t.json")
run_copy_metrics(
"metric_t.json", "metric.json", plots_no_cache=["metric.json"]
)
plot_string = dvc.plots.diff(fields={"y"})["metric.json"]
+150 -76
View File
@@ -26,20 +26,6 @@ def _remove_whitespace(value):
return value.replace(" ", "").replace("\n", "")
def _run_with(tmp_dir, commit=None, tag=None, **kwargs):
stage = tmp_dir.dvc.run(single_stage=True, **kwargs)
if hasattr(tmp_dir.dvc, "scm"):
files = [stage.path]
files += [
os.fspath(out.path_info) for out in stage.outs if not out.use_cache
]
tmp_dir.dvc.scm.add(files)
if commit:
tmp_dir.dvc.scm.commit(commit)
if tag:
tmp_dir.dvc.scm.tag(tag)
def _write_csv(metric, filename, header=True):
with open(filename, "w", newline="") as csvobj:
if header:
@@ -59,11 +45,13 @@ def _write_json(tmp_dir, metric, filename):
tmp_dir.gen(filename, json.dumps(metric, sort_keys=True))
def test_plot_csv_one_column(tmp_dir, scm, dvc):
def test_plot_csv_one_column(tmp_dir, scm, dvc, run_copy_metrics):
# no header
metric = [{"val": 2}, {"val": 3}]
_write_csv(metric, "metric.csv", header=False)
_run_with(tmp_dir, plots_no_cache=["metric.csv"])
_write_csv(metric, "metric_t.csv", header=False)
run_copy_metrics(
"metric_t.csv", "metric.csv", plots_no_cache=["metric.csv"]
)
plot_string = dvc.plots.show(
csv_header=False,
@@ -84,13 +72,15 @@ def test_plot_csv_one_column(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["title"] == "y_title"
def test_plot_csv_multiple_columns(tmp_dir, scm, dvc):
def test_plot_csv_multiple_columns(tmp_dir, scm, dvc, run_copy_metrics):
metric = [
OrderedDict([("first_val", 100), ("second_val", 100), ("val", 2)]),
OrderedDict([("first_val", 200), ("second_val", 300), ("val", 3)]),
]
_write_csv(metric, "metric.csv")
_run_with(tmp_dir, plots_no_cache=["metric.csv"])
_write_csv(metric, "metric_t.csv")
run_copy_metrics(
"metric_t.csv", "metric.csv", plots_no_cache=["metric.csv"]
)
plot_string = dvc.plots.show()["metric.csv"]
@@ -115,13 +105,15 @@ def test_plot_csv_multiple_columns(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "val"
def test_plot_csv_choose_axes(tmp_dir, scm, dvc):
def test_plot_csv_choose_axes(tmp_dir, scm, dvc, run_copy_metrics):
metric = [
OrderedDict([("first_val", 100), ("second_val", 100), ("val", 2)]),
OrderedDict([("first_val", 200), ("second_val", 300), ("val", 3)]),
]
_write_csv(metric, "metric.csv")
_run_with(tmp_dir, plots_no_cache=["metric.csv"])
_write_csv(metric, "metric_t.csv")
run_copy_metrics(
"metric_t.csv", "metric.csv", plots_no_cache=["metric.csv"]
)
plot_string = dvc.plots.show(x_field="first_val", y_field="second_val")[
"metric.csv"
@@ -146,10 +138,15 @@ def test_plot_csv_choose_axes(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "second_val"
def test_plot_json_single_val(tmp_dir, scm, dvc):
def test_plot_json_single_val(tmp_dir, scm, dvc, run_copy_metrics):
metric = [{"val": 2}, {"val": 3}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="first run")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="first run",
)
plot_string = dvc.plots.show()["metric.json"]
@@ -162,13 +159,18 @@ def test_plot_json_single_val(tmp_dir, scm, dvc):
assert plot_json["encoding"]["y"]["field"] == "val"
def test_plot_json_multiple_val(tmp_dir, scm, dvc):
def test_plot_json_multiple_val(tmp_dir, scm, dvc, run_copy_metrics):
metric = [
{"first_val": 100, "val": 2},
{"first_val": 200, "val": 3},
]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="first run")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="first run",
)
plot_string = dvc.plots.show()["metric.json"]
@@ -191,13 +193,18 @@ def test_plot_json_multiple_val(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "val"
def test_plot_confusion(tmp_dir, dvc):
def test_plot_confusion(tmp_dir, dvc, run_copy_metrics):
confusion_matrix = [
{"predicted": "B", "actual": "A"},
{"predicted": "A", "actual": "A"},
]
_write_json(tmp_dir, confusion_matrix, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="first run")
_write_json(tmp_dir, confusion_matrix, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="first run",
)
plot_string = dvc.plots.show(
template="confusion", x_field="predicted", y_field="actual",
@@ -212,21 +219,35 @@ def test_plot_confusion(tmp_dir, dvc):
assert plot_content["encoding"]["y"]["field"] == "actual"
def test_plot_multiple_revs_default(tmp_dir, scm, dvc):
def test_plot_multiple_revs_default(tmp_dir, scm, dvc, run_copy_metrics):
metric_1 = [{"y": 2}, {"y": 3}]
_write_json(tmp_dir, metric_1, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric_1, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
tag="v1",
)
metric_2 = [{"y": 3}, {"y": 5}]
_write_json(tmp_dir, metric_2, "metric.json")
_run_with(
tmp_dir, plots_no_cache=["metric.json"], commit="second", tag="v2"
_write_json(tmp_dir, metric_2, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="second",
tag="v2",
)
metric_3 = [{"y": 5}, {"y": 6}]
_write_json(tmp_dir, metric_3, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="third")
_write_json(tmp_dir, metric_3, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="third",
)
plot_string = dvc.plots.show(fields={"y"}, revs=["HEAD", "v2", "v1"],)[
"metric.json"
]
@@ -244,22 +265,31 @@ def test_plot_multiple_revs_default(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "y"
def test_plot_multiple_revs(tmp_dir, scm, dvc):
def test_plot_multiple_revs(tmp_dir, scm, dvc, run_copy_metrics):
shutil.copy(tmp_dir / ".dvc" / "plots" / "default.json", "template.json")
metric_1 = [{"y": 2}, {"y": 3}]
_write_json(tmp_dir, metric_1, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init", tag="v1")
metric_2 = [{"y": 3}, {"y": 5}]
_write_json(tmp_dir, metric_2, "metric.json")
_run_with(
tmp_dir, plots_no_cache=["metric.json"], commit="second", tag="v2"
_write_json(tmp_dir, metric_1, "metric_t.json")
stage = run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
tag="v1",
)
metric_2 = [{"y": 3}, {"y": 5}]
_write_json(tmp_dir, metric_2, "metric_t.json")
assert dvc.reproduce(stage.addressing) == [stage]
scm.add(["metric.json", stage.path])
scm.commit("second")
scm.tag("v2")
metric_3 = [{"y": 5}, {"y": 6}]
_write_json(tmp_dir, metric_3, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="third")
_write_json(tmp_dir, metric_3, "metric_t.json")
assert dvc.reproduce(stage.addressing) == [stage]
scm.add(["metric.json", stage.path])
scm.commit("third")
plot_string = dvc.plots.show(
template="template.json", revs=["HEAD", "v2", "v1"],
@@ -278,14 +308,17 @@ def test_plot_multiple_revs(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "y"
def test_plot_even_if_metric_missing(tmp_dir, scm, dvc, caplog):
def test_plot_even_if_metric_missing(
tmp_dir, scm, dvc, caplog, run_copy_metrics
):
tmp_dir.scm_gen("some_file", "content", commit="there is no metric")
scm.tag("v1")
metric = [{"y": 2}, {"y": 3}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(
tmp_dir,
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="there is metric",
tag="v2",
@@ -335,10 +368,16 @@ def custom_template(tmp_dir, dvc):
return custom_template
def test_custom_template(tmp_dir, scm, dvc, custom_template):
def test_custom_template(tmp_dir, scm, dvc, custom_template, run_copy_metrics):
metric = [{"a": 1, "b": 2}, {"a": 2, "b": 3}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
tag="v1",
)
plot_string = dvc.plots.show(
template=os.fspath(custom_template), x_field="a", y_field="b"
@@ -358,15 +397,21 @@ def _replace(path, src, dst):
def test_custom_template_with_specified_data(
tmp_dir, scm, dvc, custom_template
tmp_dir, scm, dvc, custom_template, run_copy_metrics
):
_replace(
custom_template, "DVC_METRIC_DATA", "DVC_METRIC_DATA,metric.json",
)
metric = [{"a": 1, "b": 2}, {"a": 2, "b": 3}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, outs_no_cache=["metric.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
outs_no_cache=["metric.json"],
commit="init",
tag="v1",
)
plot_string = dvc.plots.show(
template=os.fspath(custom_template), x_field="a", y_field="b",
@@ -381,7 +426,9 @@ def test_custom_template_with_specified_data(
assert plot_content["encoding"]["y"]["field"] == "b"
def test_plot_override_specified_data_source(tmp_dir, scm, dvc):
def test_plot_override_specified_data_source(
tmp_dir, scm, dvc, run_copy_metrics
):
shutil.copy(
tmp_dir / ".dvc" / "plots" / "default.json",
tmp_dir / "newtemplate.json",
@@ -393,8 +440,14 @@ def test_plot_override_specified_data_source(tmp_dir, scm, dvc):
)
metric = [{"a": 1, "b": 2}, {"a": 2, "b": 3}]
_write_json(tmp_dir, metric, "metric2.json")
_run_with(tmp_dir, outs_no_cache=["metric2.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric, "metric1.json")
run_copy_metrics(
"metric1.json",
"metric2.json",
outs_no_cache=["metric2.json"],
commit="init",
tag="v1",
)
plot_string = dvc.plots.show(
targets=["metric2.json"], template="newtemplate.json", x_field="a"
@@ -430,10 +483,18 @@ def test_plot_wrong_metric_type(tmp_dir, scm, dvc):
dvc.plots.show(targets=["metric.txt"])
def test_plot_choose_columns(tmp_dir, scm, dvc, custom_template):
def test_plot_choose_columns(
tmp_dir, scm, dvc, custom_template, run_copy_metrics
):
metric = [{"a": 1, "b": 2, "c": 3}, {"a": 2, "b": 3, "c": 4}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
tag="v1",
)
plot_string = dvc.plots.show(
template=os.fspath(custom_template),
@@ -451,10 +512,16 @@ def test_plot_choose_columns(tmp_dir, scm, dvc, custom_template):
assert plot_content["encoding"]["y"]["field"] == "c"
def test_plot_default_choose_column(tmp_dir, scm, dvc):
def test_plot_default_choose_column(tmp_dir, scm, dvc, run_copy_metrics):
metric = [{"a": 1, "b": 2, "c": 3}, {"a": 2, "b": 3, "c": 4}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="init", tag="v1")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="init",
tag="v1",
)
plot_string = dvc.plots.show(fields={"b"})["metric.json"]
@@ -467,12 +534,14 @@ def test_plot_default_choose_column(tmp_dir, scm, dvc):
assert plot_content["encoding"]["y"]["field"] == "b"
def test_plot_yaml(tmp_dir, scm, dvc):
def test_plot_yaml(tmp_dir, scm, dvc, run_copy_metrics):
metric = [{"val": 2}, {"val": 3}]
with open("metric.yaml", "w") as fobj:
with open("metric_t.yaml", "w") as fobj:
yaml.dump(metric, fobj)
_run_with(tmp_dir, plots_no_cache=["metric.yaml"])
run_copy_metrics(
"metric_t.yaml", "metric.yaml", plots_no_cache=["metric.yaml"]
)
plot_string = dvc.plots.show()["metric.yaml"]
@@ -483,10 +552,15 @@ def test_plot_yaml(tmp_dir, scm, dvc):
]
def test_raise_on_wrong_field(tmp_dir, scm, dvc):
def test_raise_on_wrong_field(tmp_dir, scm, dvc, run_copy_metrics):
metric = [{"val": 2}, {"val": 3}]
_write_json(tmp_dir, metric, "metric.json")
_run_with(tmp_dir, plots_no_cache=["metric.json"], commit="first run")
_write_json(tmp_dir, metric, "metric_t.json")
run_copy_metrics(
"metric_t.json",
"metric.json",
plots_no_cache=["metric.json"],
commit="first run",
)
with pytest.raises(NoFieldInDataError):
dvc.plots.show("metric.json", x_field="no_val")
+9 -6
View File
@@ -1,5 +1,6 @@
import os
import shutil
import textwrap
import pytest
@@ -29,17 +30,19 @@ def match_files(files, expected_files):
def create_dvc_pipeline(tmp_dir, dvc):
script = os.linesep.join(
[
"from pathlib import Path",
"Path({}).touch()".format(os.path.join("out", "file")),
]
script = textwrap.dedent(
"""\
import os, sys
f = sys.argv[1]
os.makedirs(os.path.dirname(f))
open(f, "w+").close()
"""
)
tmp_dir.scm_gen({"script.py": script}, commit="init")
tmp_dir.dvc_gen({"dep": "content"}, commit="init dvc")
dvc.run(
**{
"command": "python script.py",
"cmd": "python script.py {}".format(os.path.join("out", "file")),
"outs": [os.path.join("out", "file")],
"deps": ["dep"],
"fname": "out.dvc",
+5 -1
View File
@@ -239,7 +239,11 @@ def test_external_dir_resource_on_no_cache(tmp_dir, dvc, tmp_path_factory):
dvc.cache.local = None
with pytest.raises(RemoteCacheRequiredError):
dvc.run(deps=[os.fspath(external_dir)], single_stage=True)
dvc.run(
cmd="echo hello world",
deps=[os.fspath(external_dir)],
single_stage=True,
)
def test_push_order(tmp_dir, dvc, tmp_path_factory, mocker, setup_remote):
+17 -3
View File
@@ -264,9 +264,11 @@ class TestReproDepDirWithOutputsUnderIt(SingleStageRun, TestDvc):
self.assertEqual(len(stages), 1)
self.assertTrue(stages[0] is not None)
deps = [self.DATA, self.DATA_SUB]
stage = self.dvc.run(
cmd="ls {}".format(" ".join(deps)),
fname="dvcfile2.dvc",
deps=[self.DATA, self.DATA_SUB],
deps=deps,
single_stage=True,
)
self.assertTrue(stage is not None)
@@ -405,7 +407,17 @@ class TestReproDryNoExec(TestDvc):
self.assertEqual(ret, 0)
ret = main(
["run", "--no-exec", "--single-stage", "-f", DVC_FILE] + deps
[
"run",
"--no-exec",
"--single-stage",
"-f",
DVC_FILE,
*deps,
"ls {}".format(
" ".join(dep for i, dep in enumerate(deps) if i % 2)
),
]
)
self.assertEqual(ret, 0)
@@ -1465,9 +1477,11 @@ def repro_dir(tmp_dir, dvc, run_copy):
stages["dir_file_copy"] = stage
last_stage = tmp_dir / "dir" / DVC_FILE
deps = [os.fspath(origin_copy_2), os.fspath(dir_file_copy)]
stage = dvc.run(
cmd="echo {}".format(" ".join(deps)),
fname=os.fspath(last_stage),
deps=[os.fspath(origin_copy_2), os.fspath(dir_file_copy)],
deps=deps,
single_stage=True,
)
assert stage is not None
+15
View File
@@ -3,6 +3,8 @@ import os
import pytest
import yaml
from dvc.exceptions import InvalidArgumentError
from dvc.repo import Repo
from dvc.stage.exceptions import DuplicateStageName, InvalidStageName
@@ -299,3 +301,16 @@ def test_run_params_no_exec(tmp_dir, dvc):
assert data["stages"]["read_params"]["params"] == [
{"params2.yaml": ["lists"]}
]
@pytest.mark.parametrize(
"kwargs",
[
{"outs": ["foo"], "deps": ["bar"]},
{"outs": ["foo"], "deps": ["bar"], "name": "copy-foo-bar"},
],
)
def test_run_without_cmd(kwargs):
with pytest.raises(InvalidArgumentError) as exc:
Repo().run(**kwargs)
assert "command is not specified" == str(exc.value)
+30 -21
View File
@@ -76,7 +76,7 @@ class TestRun(TestDvc):
class TestRunEmpty(TestDvc):
def test(self):
self.dvc.run(
cmd="",
cmd="echo hello world",
deps=[],
outs=[],
outs_no_cache=[],
@@ -91,7 +91,7 @@ class TestRunMissingDep(TestDvc):
with self.assertRaises(DependencyDoesNotExistError):
self.dvc.run(
cmd="",
cmd="command",
deps=["non-existing-dep"],
outs=[],
outs_no_cache=[],
@@ -118,7 +118,7 @@ class TestRunCircularDependency(TestDvc):
def test(self):
with self.assertRaises(CircularDependencyError):
self.dvc.run(
cmd="",
cmd="command",
deps=[self.FOO],
outs=[self.FOO],
fname="circular-dependency.dvc",
@@ -128,7 +128,7 @@ class TestRunCircularDependency(TestDvc):
def test_outs_no_cache(self):
with self.assertRaises(CircularDependencyError):
self.dvc.run(
cmd="",
cmd="command",
deps=[self.FOO],
outs_no_cache=[self.FOO],
fname="circular-dependency.dvc",
@@ -138,7 +138,7 @@ class TestRunCircularDependency(TestDvc):
def test_non_normalized_paths(self):
with self.assertRaises(CircularDependencyError):
self.dvc.run(
cmd="",
cmd="command",
deps=["./foo"],
outs=["foo"],
fname="circular-dependency.dvc",
@@ -173,7 +173,7 @@ class TestRunDuplicatedArguments(TestDvc):
def test(self):
with self.assertRaises(ArgumentDuplicationError):
self.dvc.run(
cmd="",
cmd="command",
deps=[],
outs=[self.FOO, self.FOO],
fname="circular-dependency.dvc",
@@ -183,7 +183,7 @@ class TestRunDuplicatedArguments(TestDvc):
def test_outs_no_cache(self):
with self.assertRaises(ArgumentDuplicationError):
self.dvc.run(
cmd="",
cmd="command",
outs=[self.FOO],
outs_no_cache=[self.FOO],
fname="circular-dependency.dvc",
@@ -193,7 +193,7 @@ class TestRunDuplicatedArguments(TestDvc):
def test_non_normalized_paths(self):
with self.assertRaises(ArgumentDuplicationError):
self.dvc.run(
cmd="",
cmd="command",
deps=[],
outs=["foo", "./foo"],
fname="circular-dependency.dvc",
@@ -204,22 +204,30 @@ class TestRunDuplicatedArguments(TestDvc):
class TestRunStageInsideOutput(TestDvc):
def test_cwd(self):
self.dvc.run(
cmd="", deps=[], outs=[self.DATA_DIR], single_stage=True,
cmd=f"mkdir {self.DATA_DIR}",
deps=[],
outs=[self.DATA_DIR],
single_stage=True,
)
with self.assertRaises(StagePathAsOutputError):
self.dvc.run(
cmd="",
cmd="command",
fname=os.path.join(self.DATA_DIR, "inside-cwd.dvc"),
single_stage=True,
)
def test_file_name(self):
self.dvc.run(cmd="", deps=[], outs=[self.DATA_DIR], single_stage=True)
self.dvc.run(
cmd=f"mkdir {self.DATA_DIR}",
deps=[],
outs=[self.DATA_DIR],
single_stage=True,
)
with self.assertRaises(StagePathAsOutputError):
self.dvc.run(
cmd="",
cmd="command",
outs=[self.FOO],
fname=os.path.join(self.DATA_DIR, "inside-cwd.dvc"),
single_stage=True,
@@ -229,30 +237,30 @@ class TestRunStageInsideOutput(TestDvc):
class TestRunBadCwd(TestDvc):
def test(self):
with self.assertRaises(StagePathOutsideError):
self.dvc.run(cmd="", wdir=self.mkdtemp(), single_stage=True)
self.dvc.run(cmd="command", wdir=self.mkdtemp(), single_stage=True)
def test_same_prefix(self):
with self.assertRaises(StagePathOutsideError):
path = f"{self._root_dir}-{uuid.uuid4()}"
os.mkdir(path)
self.dvc.run(cmd="", wdir=path, single_stage=True)
self.dvc.run(cmd="command", wdir=path, single_stage=True)
class TestRunBadWdir(TestDvc):
def test(self):
with self.assertRaises(StagePathOutsideError):
self.dvc.run(cmd="", wdir=self.mkdtemp(), single_stage=True)
self.dvc.run(cmd="command", wdir=self.mkdtemp(), single_stage=True)
def test_same_prefix(self):
with self.assertRaises(StagePathOutsideError):
path = f"{self._root_dir}-{uuid.uuid4()}"
os.mkdir(path)
self.dvc.run(cmd="", wdir=path, single_stage=True)
self.dvc.run(cmd="command", wdir=path, single_stage=True)
def test_not_found(self):
with self.assertRaises(StagePathNotFoundError):
path = os.path.join(self._root_dir, str(uuid.uuid4()))
self.dvc.run(cmd="", wdir=path, single_stage=True)
self.dvc.run(cmd="command", wdir=path, single_stage=True)
def test_not_dir(self):
with self.assertRaises(StagePathNotDirectoryError):
@@ -261,7 +269,7 @@ class TestRunBadWdir(TestDvc):
path = os.path.join(path, str(uuid.uuid4()))
open(path, "a").close()
self.dvc.run(
cmd="", wdir=path, single_stage=True,
cmd="command", wdir=path, single_stage=True,
)
@@ -269,7 +277,7 @@ class TestRunBadName(TestDvc):
def test(self):
with self.assertRaises(StagePathOutsideError):
self.dvc.run(
cmd="",
cmd="command",
fname=os.path.join(self.mkdtemp(), self.FOO + DVC_FILE_SUFFIX),
single_stage=True,
)
@@ -279,7 +287,7 @@ class TestRunBadName(TestDvc):
path = f"{self._root_dir}-{uuid.uuid4()}"
os.mkdir(path)
self.dvc.run(
cmd="",
cmd="command",
fname=os.path.join(path, self.FOO + DVC_FILE_SUFFIX),
single_stage=True,
)
@@ -288,7 +296,7 @@ class TestRunBadName(TestDvc):
with self.assertRaises(StagePathNotFoundError):
path = os.path.join(self._root_dir, str(uuid.uuid4()))
self.dvc.run(
cmd="",
cmd="command",
fname=os.path.join(path, self.FOO + DVC_FILE_SUFFIX),
single_stage=True,
)
@@ -574,6 +582,7 @@ class TestCmdRunOverwrite(TestDvc):
"out.dvc",
"-d",
self.BAR,
f"cat {self.BAR}",
]
)
self.assertEqual(ret, 0)