plots: return errors in json format (#9146)

* plots: return errors in json format

* plots --json: move plots data into data key

* rename  revision key to rev

* move imports to top-level

* add tests
This commit is contained in:
skshetry
2023-03-27 12:53:43 +05:45
committed by GitHub
parent d41512c85c
commit 43195a806d
7 changed files with 167 additions and 49 deletions
+5 -2
View File
@@ -418,5 +418,8 @@ def test_show_plots_defined_with_native_os_path(tmp_dir, dvc, scm, capsys):
assert main(["plots", "show", "--json"]) == 0
out, _ = capsys.readouterr()
json_out = json.loads(out)
assert json_out[f"dvc.yaml::{top_level_plot}"]
assert json_out[stage_plot]
assert "errors" not in json_out
json_data = json_out["data"]
assert json_data[f"dvc.yaml::{top_level_plot}"]
assert json_data[stage_plot]
+59 -24
View File
@@ -182,7 +182,13 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
html_path, json_result, split_json_result = call(capsys)
html_result = extract_vega_specs(html_path, ["linear.json", "confusion.json"])
assert json_result["linear.json"][0]["content"]["data"][
assert "errors" not in json_result
assert "errors" not in split_json_result
json_data = json_result["data"]
split_json_data = split_json_result["data"]
assert json_data["linear.json"][0]["content"]["data"][
"values"
] == _update_datapoints(
linear_v1,
@@ -200,7 +206,7 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
REVISION_FIELD: "workspace",
},
)
assert json_result["confusion.json"][0]["content"]["data"][
assert json_data["confusion.json"][0]["content"]["data"][
"values"
] == _update_datapoints(
confusion_v1,
@@ -218,34 +224,40 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
REVISION_FIELD: "workspace",
},
)
verify_image(tmp_dir, "workspace", "image.png", image_v1, html_path, json_result)
verify_image(tmp_dir, "workspace", "image.png", image_v1, html_path, json_data)
for plot in ["linear.json", "confusion.json"]:
verify_vega(
"workspace",
html_result[plot],
json_result[plot],
split_json_result[plot],
json_data[plot],
split_json_data[plot],
)
verify_vega_props("confusion.json", json_result, **confusion_props)
verify_vega_props("confusion.json", json_data, **confusion_props)
image_v2, linear_v2, confusion_v2, confusion_props = next(repo_state)
html_path, json_result, split_json_result = call(capsys, subcommand="diff")
html_result = extract_vega_specs(html_path, ["linear.json", "confusion.json"])
verify_image(tmp_dir, "workspace", "image.png", image_v2, html_path, json_result)
verify_image(tmp_dir, "HEAD", "image.png", image_v1, html_path, json_result)
assert "errors" not in json_result
assert "errors" not in split_json_result
json_data = json_result["data"]
split_json_data = split_json_result["data"]
verify_image(tmp_dir, "workspace", "image.png", image_v2, html_path, json_data)
verify_image(tmp_dir, "HEAD", "image.png", image_v1, html_path, json_data)
for plot in ["linear.json", "confusion.json"]:
verify_vega(
["HEAD", "workspace"],
html_result[plot],
json_result[plot],
split_json_result[plot],
json_data[plot],
split_json_data[plot],
)
verify_vega_props("confusion.json", json_result, **confusion_props)
verify_vega_props("confusion.json", json_data, **confusion_props)
path = tmp_dir / "subdir"
path.mkdir()
with path.chdir():
@@ -254,7 +266,13 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
html_path,
["../linear.json", "../confusion.json"],
)
assert json_result["../linear.json"][0]["content"]["data"][
assert "errors" not in json_result
assert "errors" not in split_json_result
json_data = json_result["data"]
split_json_data = split_json_result["data"]
assert json_data["../linear.json"][0]["content"]["data"][
"values"
] == _update_datapoints(
linear_v2,
@@ -286,7 +304,7 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
REVISION_FIELD: "HEAD",
},
)
assert json_result["../confusion.json"][0]["content"]["data"][
assert json_data["../confusion.json"][0]["content"]["data"][
"values"
] == _update_datapoints(
confusion_v2,
@@ -326,8 +344,8 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
verify_vega(
["HEAD", "workspace"],
html_result[plot],
json_result[plot],
split_json_result[plot],
json_data[plot],
split_json_data[plot],
)
verify_image(
path,
@@ -335,7 +353,7 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
"../image.png",
image_v2,
html_path,
json_result,
json_data,
)
verify_image(
path,
@@ -343,7 +361,7 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
"../image.png",
image_v1,
html_path,
json_result,
json_data,
)
@@ -361,13 +379,30 @@ def test_repo_with_removed_plots(tmp_dir, capsys, repo_with_plots):
for s in {"show", "diff"}:
_, json_result, split_json_result = call(capsys, subcommand=s)
for p in {
"linear.json",
"confusion.json",
"image.png",
}:
assert json_result[p] == []
assert split_json_result[p] == []
errors = [
{
"name": p,
"source": p,
"rev": "workspace",
"type": "FileNotFoundError",
"msg": "",
}
for p in [
"linear.json",
"confusion.json",
"image.png",
]
]
expected_result = {
"errors": errors,
"data": {
"image.png": [],
"confusion.json": [],
"linear.json": [],
},
}
assert json_result == expected_result
assert split_json_result == expected_result
def test_config_output_dir(tmp_dir, dvc, capsys):
+9 -4
View File
@@ -7,6 +7,7 @@ import pytest
from dvc.cli import parse_args
from dvc.commands.plots import CmdPlotsDiff, CmdPlotsShow, CmdPlotsTemplates
from dvc.render.match import RendererWithErrors
@pytest.fixture
@@ -268,8 +269,11 @@ def test_should_call_render(tmp_dir, mocker, capsys, plots_data, output):
output = output or "dvc_plots"
index_path = tmp_dir / output / "index.html"
renderers = mocker.MagicMock()
mocker.patch("dvc.render.match.match_defs_renderers", return_value=renderers)
renderer = mocker.MagicMock()
mocker.patch(
"dvc.render.match.match_defs_renderers",
return_value=[RendererWithErrors(renderer, {}, {})],
)
render_mock = mocker.patch("dvc_render.render_html", return_value=index_path)
assert cmd.run() == 0
@@ -278,7 +282,7 @@ def test_should_call_render(tmp_dir, mocker, capsys, plots_data, output):
assert index_path.as_uri() in out
render_mock.assert_called_once_with(
renderers=renderers,
renderers=[renderer],
output_file=Path(tmp_dir / output / "index.html"),
html_template=None,
)
@@ -354,12 +358,13 @@ def test_show_json(split, mocker, capsys):
import dvc.commands.plots
renderer = mocker.MagicMock()
renderer_obj = RendererWithErrors(renderer, {}, {})
renderer.name = "rname"
to_json_mock = mocker.patch(
"dvc.render.convert.to_json", return_value={"renderer": "json"}
)
dvc.commands.plots._show_json([renderer], split)
dvc.commands.plots._show_json([renderer_obj], split)
to_json_mock.assert_called_once_with(renderer, split)
+26 -5
View File
@@ -1,4 +1,7 @@
from funcy import set_in
from dvc.render import VERSION_FIELD
from dvc.render.converter.vega import VegaConverter
from dvc.render.match import PlotsData, _squash_plots_properties, match_defs_renderers
@@ -35,7 +38,7 @@ def test_group_definitions():
}
def test_match_renderers(mocker):
def test_match_renderers(M):
data = {
"v1": {
"definitions": {
@@ -77,9 +80,9 @@ def test_match_renderers(mocker):
},
}
renderers = match_defs_renderers(data)
assert len(renderers) == 1
assert renderers[0].datapoints == [
(renderer_with_errors,) = match_defs_renderers(data)
renderer = renderer_with_errors[0]
assert renderer.datapoints == [
{
VERSION_FIELD: {
"revision": "v1",
@@ -99,13 +102,31 @@ def test_match_renderers(mocker):
"y": 2,
},
]
assert renderers[0].properties == {
assert renderer.properties == {
"title": "config_file_1::plot_id_1",
"x": "x",
"y": "y",
"x_label": "x",
"y_label": "y",
}
assert renderer_with_errors.source_errors == {
"revision_with_no_data": {"file.json": M.instance_of(FileNotFoundError)}
}
assert not renderer_with_errors.definition_errors
def test_flat_datapoints_errors_are_caught(M, mocker):
d = {}
d = set_in(
d,
["v1", "definitions", "data", "dvc.yaml", "data", "plot_id_1"],
{"x": "x", "y": {"file.json": "y"}},
)
d = set_in(d, ["v1", "sources", "data", "file.json", "data"], [{"x": 1, "y": 1}])
mocker.patch.object(VegaConverter, "flat_datapoints", side_effect=ValueError)
(renderer_with_errors,) = match_defs_renderers(d)
assert not renderer_with_errors.source_errors
assert renderer_with_errors.definition_errors == {"v1": M.instance_of(ValueError)}
def test_squash_plots_properties():