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_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], commit="init", tag="v1", ) props = { "template": os.fspath(custom_template), "fields": {"b", "c"}, "x": "b", "y": "c", } plot_string = dvc.plots.show(props=props)["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { "b": 2, "c": 3, "rev": "workspace" }, { "b": 3, "c": 4, "rev": "workspace" }, ] assert plot_content["encoding"]["x"]["field"] == "b" assert plot_content["encoding"]["y"]["field"] == "c"
def test_show_non_plot_and_plot_with_params(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_copy_metrics("metric.json", "metric2.json", plots_no_cache=["metric2.json"]) dvc.plots.modify("metric2.json", props={"title": "TITLE"}) result = dvc.plots.show(targets=["metric.json", "metric2.json"]) plot_content = json.loads(result["metric.json"]) plot2_content = json.loads(result["metric2.json"]) assert plot2_content["title"] == "TITLE" assert plot_content != plot2_content plot_content.pop("title") plot2_content.pop("title") assert plot_content == plot2_content
def test_plot_json_single_val(tmp_dir, scm, dvc, run_copy_metrics): metric = [{"val": 2}, {"val": 3}] _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"] plot_json = json.loads(plot_string) assert plot_json["data"]["values"] == [ { "val": 2, PlotData.INDEX_FIELD: 0, "rev": "workspace" }, { "val": 3, PlotData.INDEX_FIELD: 1, "rev": "workspace" }, ] assert plot_json["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_json["encoding"]["y"]["field"] == "val"
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_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], commit="there is metric", tag="v2", ) caplog.clear() with caplog.at_level(logging.WARNING, "dvc"): plots = dvc.plots.show(revs=["v1", "v2"], targets=["metric.json"]) assert "'metric.json' was not found at: 'v1'." in caplog.text plot_content = json.loads(plots["metric.json"]) assert plot_content["data"]["values"] == [ { "y": 2, PlotData.INDEX_FIELD: 0, "rev": "v2" }, { "y": 3, PlotData.INDEX_FIELD: 1, "rev": "v2" }, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "y"
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_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], commit="init", tag="v1", ) plot_string = dvc.plots.show(props={"fields": {"b"}})["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { PlotData.INDEX_FIELD: 0, "b": 2, "rev": "workspace" }, { PlotData.INDEX_FIELD: 1, "b": 3, "rev": "workspace" }, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "b"
def test_diff_no_file_on_target_rev(tmp_dir, scm, dvc, caplog, diff_fun, metric_value): with tmp_dir.branch("new_branch", new=True): _write_json(tmp_dir, metric_value, "metric.json") with caplog.at_level(logging.WARNING, "dvc"): diff_fun(dvc, "metric.json", "master") assert "'metric.json' was not found at: 'master'." in caplog.text
def test_diff_no_file_on_target_rev(tmp_dir, scm, dvc, caplog, command, metric_value): with tmp_dir.branch("new_branch", new=True): _write_json(tmp_dir, metric_value, "metric.json") with caplog.at_level(logging.WARNING, "dvc"): assert (main( [command, "diff", "master", "--targets", "metric.json"]) == 0) assert "'metric.json' was not found at: 'master'." in caplog.text
def test_should_raise_on_no_template(tmp_dir, dvc, run_copy_metrics): metric = [{"val": 2}, {"val": 3}] _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(TemplateNotFoundError): props = {"template": "non_existing_template.json"} dvc.plots.show("metric.json", props=props)
def test_plots_modify_existing_template(tmp_dir, dvc, run_copy_metrics, custom_template): metric = [{"a": 1, "b": 2}, {"a": 2, "b": 3}] _write_json(tmp_dir, metric, "metric_t.json") stage = run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], name="copy-metrics", single_stage=False, ) dvc.plots.modify("metric.json", props={"template": relpath(custom_template)}) stage = stage.reload() assert stage.outs[0].plot == {"template": relpath(custom_template)}
def test_raise_on_wrong_field(tmp_dir, scm, dvc, run_copy_metrics): metric = [{"val": 2}, {"val": 3}] _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", props={"x": "no_val"}) with pytest.raises(NoFieldInDataError): dvc.plots.show("metric.json", props={"y": "no_val"})
def test_bad_template(tmp_dir, dvc, run_copy_metrics): metric = [{"val": 2}, {"val": 3}] _write_json(tmp_dir, metric, "metric_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], commit="first run", ) tmp_dir.gen("template.json", json.dumps({"a": "b", "c": "d"})) with pytest.raises(BadTemplateError): props = {"template": "template.json"} dvc.plots.show("metric.json", props=props)
def test_unset_nonexistent(tmp_dir, dvc, run_copy_metrics, custom_template): metric = [{"a": 1, "b": 2}, {"a": 2, "b": 3}] _write_json(tmp_dir, metric, "metric_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], name="copy-metrics", single_stage=False, ) with pytest.raises(PropsNotFoundError): dvc.plots.modify( "metric.json", unset=["nonexistent"], )
def test_plots_modify_should_not_change_lockfile(tmp_dir, dvc, run_copy_metrics, custom_template): _write_json(tmp_dir, [{"a": 1, "b": 2}], "metric_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], name="copy-metrics", single_stage=False, ) (tmp_dir / PIPELINE_LOCK).unlink() dvc.plots.modify("metric.json", props={"template": relpath(custom_template)}) assert not (tmp_dir / PIPELINE_LOCK).exists()
def test_show_no_repo(tmp_dir): metric = [ { "first_val": 100, "val": 2 }, { "first_val": 200, "val": 3 }, ] _write_json(tmp_dir, metric, "metric.json") dvc = Repo(uninitialized=True) dvc.plots.show(["metric.json"])
def test_plot_confusion_normalized(tmp_dir, dvc, run_copy_metrics): confusion_matrix = [ { "predicted": "B", "actual": "A" }, { "predicted": "A", "actual": "A" }, ] _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", ) props = { "template": "confusion_normalized", "x": "predicted", "y": "actual", } plot_string = dvc.plots.show(props=props)["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { "predicted": "B", "actual": "A", "rev": "workspace" }, { "predicted": "A", "actual": "A", "rev": "workspace" }, ] assert plot_content["spec"]["transform"][0]["groupby"] == [ "actual", "predicted", ] assert plot_content["spec"]["transform"][1]["groupby"] == ["rev", "actual"] assert plot_content["spec"]["encoding"]["x"]["field"] == "predicted" assert plot_content["spec"]["encoding"]["y"]["field"] == "actual"
def test_multiple_plots(tmp_dir, scm, dvc, run_copy_metrics): metric1 = [ OrderedDict([("first_val", 100), ("second_val", 100), ("val", 2)]), OrderedDict([("first_val", 200), ("second_val", 300), ("val", 3)]), ] metric2 = [ OrderedDict([("first_val", 100), ("second_val", 100), ("val", 2)]), OrderedDict([("first_val", 200), ("second_val", 300), ("val", 3)]), ] _write_csv(metric1, "metric_t1.csv") _write_json(tmp_dir, metric2, "metric_t2.json") run_copy_metrics("metric_t1.csv", "metric1.csv", plots_no_cache=["metric1.csv"]) run_copy_metrics("metric_t2.json", "metric2.json", plots_no_cache=["metric2.json"]) assert len(dvc.plots.show().keys()) == 2
def test_show_from_subdir(tmp_dir, dvc, caplog): subdir = tmp_dir / "subdir" subdir.mkdir() metric = [ { "first_val": 100, "val": 2 }, { "first_val": 200, "val": 3 }, ] _write_json(subdir, metric, "metric.json") with subdir.chdir(), caplog.at_level(logging.INFO, "dvc"): assert main(["plots", "show", "metric.json"]) == 0 assert f"file://{str(subdir)}" in caplog.text assert (subdir / "plots.html").exists()
def test_diff_dirty(tmp_dir, scm, dvc, run_copy_metrics): metric_1 = [{"y": 2}, {"y": 3}] _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_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_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"] ) plot_string = dvc.plots.diff(props={"fields": {"y"}})["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ {"y": 3, PlotData.INDEX_FIELD: 0, "rev": "HEAD"}, {"y": 5, PlotData.INDEX_FIELD: 1, "rev": "HEAD"}, {"y": 5, PlotData.INDEX_FIELD: 0, "rev": "workspace"}, {"y": 6, PlotData.INDEX_FIELD: 1, "rev": "workspace"}, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "y" _write_json(tmp_dir, [{"y": 7}, {"y": 8}], "metric.json") plot_string = dvc.plots.diff(props={"fields": {"y"}})["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ {"y": 3, PlotData.INDEX_FIELD: 0, "rev": "HEAD"}, {"y": 5, PlotData.INDEX_FIELD: 1, "rev": "HEAD"}, {"y": 7, PlotData.INDEX_FIELD: 0, "rev": "workspace"}, {"y": 8, PlotData.INDEX_FIELD: 1, "rev": "workspace"}, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "y"
def test_show_non_plot(tmp_dir, scm, use_dvc): metric = [ { "first_val": 100, "val": 2 }, { "first_val": 200, "val": 3 }, ] _write_json(tmp_dir, metric, "metric.json") if use_dvc: dvc = Repo.init() else: dvc = Repo(uninitialized=True) plot_string = dvc.plots.show(targets=["metric.json"])["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { "val": 2, PlotData.INDEX_FIELD: 0, "first_val": 100, "rev": "workspace", }, { "val": 3, PlotData.INDEX_FIELD: 1, "first_val": 200, "rev": "workspace", }, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "val" if not use_dvc: assert not (tmp_dir / ".dvc").exists()
def test_plot_cache_missing(tmp_dir, scm, dvc, caplog, run_copy_metrics): metric = [{"y": 2}, {"y": 3}] _write_json(tmp_dir, metric, "metric_t.json") stage = run_copy_metrics( "metric_t.json", "metric.json", plots=["metric.json"], commit="there is metric", ) scm.tag("v1") # Make a different plot and then remove its datafile metric = [{"y": 3}, {"y": 4}] _write_json(tmp_dir, metric, "metric_t.json") stage = run_copy_metrics( "metric_t.json", "metric.json", plots=["metric.json"], commit="there is an another metric", ) scm.tag("v2") remove(stage.outs[0].fspath) remove(stage.outs[0].cache_path) plots = dvc.plots.show(revs=["v1", "v2"], targets=["metric.json"]) plot_content = json.loads(plots["metric.json"]) assert plot_content["data"]["values"] == [ { "y": 2, PlotData.INDEX_FIELD: 0, "rev": "v1" }, { "y": 3, PlotData.INDEX_FIELD: 1, "rev": "v1" }, ]
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_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_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_t.json") run_copy_metrics( "metric_t.json", "metric.json", plots_no_cache=["metric.json"], commit="third", ) plot_string = dvc.plots.show(revs=["HEAD", "v2", "v1"], props={"fields": {"y"}})["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { "y": 5, PlotData.INDEX_FIELD: 0, "rev": "HEAD" }, { "y": 6, PlotData.INDEX_FIELD: 1, "rev": "HEAD" }, { "y": 3, PlotData.INDEX_FIELD: 0, "rev": "v2" }, { "y": 5, PlotData.INDEX_FIELD: 1, "rev": "v2" }, { "y": 2, PlotData.INDEX_FIELD: 0, "rev": "v1" }, { "y": 3, PlotData.INDEX_FIELD: 1, "rev": "v1" }, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "y"
def test_plot_multiple_revs(tmp_dir, scm, dvc, run_copy_metrics): templates_dir = dvc.plots.templates.templates_dir shutil.copy( os.path.join(templates_dir, "default.json"), os.path.join(templates_dir, "template.json"), ) metric_1 = [{"y": 2}, {"y": 3}] _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_t.json") assert dvc.reproduce(stage.addressing) == [stage] scm.add(["metric.json", stage.path]) scm.commit("third") props = {"template": "template.json"} plot_string = dvc.plots.show(revs=["HEAD", "v2", "v1"], props=props)["metric.json"] plot_content = json.loads(plot_string) assert plot_content["data"]["values"] == [ { "y": 5, PlotData.INDEX_FIELD: 0, "rev": "HEAD" }, { "y": 6, PlotData.INDEX_FIELD: 1, "rev": "HEAD" }, { "y": 3, PlotData.INDEX_FIELD: 0, "rev": "v2" }, { "y": 5, PlotData.INDEX_FIELD: 1, "rev": "v2" }, { "y": 2, PlotData.INDEX_FIELD: 0, "rev": "v1" }, { "y": 3, PlotData.INDEX_FIELD: 1, "rev": "v1" }, ] assert plot_content["encoding"]["x"]["field"] == PlotData.INDEX_FIELD assert plot_content["encoding"]["y"]["field"] == "y"