Skip to content

Commit 1eab66d

Browse files
committed
feed dvc-render updates into API output
1 parent 51e5e50 commit 1eab66d

File tree

5 files changed

+68
-103
lines changed

5 files changed

+68
-103
lines changed

dvc/render/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
FILENAME_FIELD = "filename"
44
FIELD_FIELD = "field"
55
REVISIONS_KEY = "revisions"
6-
ANCHORS_Y_DEFN = "anchors_y_defn"
6+
ANCHOR_DEFINITIONS = "anchor_definitions"
77
TYPE_KEY = "type"
88
SRC_FIELD = "src"

dvc/render/convert.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
from typing import Dict, List, Union
22

3-
from dvc.render import (
4-
ANCHORS_Y_DEFN,
5-
REVISION_FIELD,
6-
REVISIONS_KEY,
7-
SRC_FIELD,
8-
TYPE_KEY,
9-
)
3+
from dvc.render import REVISION_FIELD, REVISIONS_KEY, SRC_FIELD, TYPE_KEY
104
from dvc.render.converter.image import ImageConverter
115
from dvc.render.converter.vega import VegaConverter
126

@@ -28,20 +22,19 @@ def to_json(renderer, split: bool = False) -> List[Dict]:
2822
if renderer.TYPE == "vega":
2923
if not renderer.datapoints:
3024
return []
25+
revs = renderer.get_revs()
3126
if split:
32-
content = renderer.get_filled_template(
33-
skip_anchors=["data"], as_string=False
34-
)
27+
content, split_content = renderer.get_partial_filled_template()
3528
else:
3629
content = renderer.get_filled_template(as_string=False)
30+
split_content = {}
3731

3832
return [
3933
{
40-
ANCHORS_Y_DEFN: renderer.properties.get("anchors_y_defn", {}),
4134
TYPE_KEY: renderer.TYPE,
42-
REVISIONS_KEY: renderer.properties.get("anchor_revs", []),
35+
REVISIONS_KEY: revs,
4336
"content": content,
44-
"datapoints": renderer.datapoints,
37+
**split_content,
4538
}
4639
]
4740
if renderer.TYPE == "image":

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ classifiers = [
2929
"Programming Language :: Python :: 3.11",
3030
]
3131
dynamic = ["version"]
32+
3233
dependencies = [
3334
"colorama>=0.3.9",
3435
"configobj>=5.0.6",
3536
"distro>=1.3",
3637
"dpath<3,>=2.1.0",
3738
"dvc-data>=2.16.3,<2.17.0",
3839
"dvc-http>=2.29.0",
39-
"dvc-render>=0.3.1,<1",
40+
"dvc-render@git+https://github.com/iterative/dvc-render@refs/pull/142/head",
4041
"dvc-studio-client>=0.9.2,<1",
4142
"dvc-task>=0.3.0,<1",
4243
"flatten_dict<1,>=0.4.1",

tests/integration/plots/test_plots.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,22 +111,26 @@ def verify_vega(
111111
assert j[0]["type"] == "vega"
112112
assert set(j[0]["revisions"]) == set(versions)
113113

114-
assert json_result[0]["datapoints"] == split_json_result[0]["datapoints"]
114+
assert (
115+
json_result[0]["content"]["data"]["values"]
116+
== split_json_result[0]["anchor_definitions"]["<DVC_METRIC_DATA>"]
117+
)
115118
assert set(versions) == set(json_result[0]["revisions"])
116119

117120
assert json_result[0]["content"]["data"]["values"]
118121
assert html_result["data"]["values"]
119-
assert split_json_result[0]["content"]["data"]["values"] == "<DVC_METRIC_DATA>"
122+
assert "<DVC_METRIC_DATA>" in split_json_result[0]["content"]
120123

121124
def _assert_templates_equal(html_template, filled_template, split_template):
122-
# besides data, json and split json should be equal
123-
path = ["data", "values"]
125+
# besides split anchors, json and split json should be equal
126+
paths = [["data", "values"], ["encoding", "color"]]
124127
tmp1 = deepcopy(html_template)
125128
tmp2 = deepcopy(filled_template)
126-
tmp3 = deepcopy(split_template)
127-
dpath.set(tmp1, path, {})
128-
dpath.set(tmp2, path, {})
129-
dpath.set(tmp3, path, {})
129+
tmp3 = deepcopy(json.loads(split_template))
130+
for path in paths:
131+
dpath.set(tmp1, path, {})
132+
dpath.set(tmp2, path, {})
133+
dpath.set(tmp3, path, {})
130134

131135
assert tmp1 == tmp2 == tmp3
132136

@@ -194,16 +198,12 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
194198
linear_v1,
195199
{
196200
"rev": "workspace",
197-
"filename": "linear.json",
198-
"field": "y",
199201
},
200202
)
201203
assert html_result["linear.json"]["data"]["values"] == _update_datapoints(
202204
linear_v1,
203205
{
204206
REVISION_FIELD: "workspace",
205-
"filename": "linear.json",
206-
"field": "y",
207207
},
208208
)
209209
assert json_data["confusion.json"][0]["content"]["data"][
@@ -278,30 +278,22 @@ def test_repo_with_plots(tmp_dir, scm, dvc, capsys, run_copy_metrics, repo_with_
278278
linear_v2,
279279
{
280280
"rev": "workspace",
281-
"filename": "../linear.json",
282-
"field": "y",
283281
},
284282
) + _update_datapoints(
285283
linear_v1,
286284
{
287285
"rev": "HEAD",
288-
"filename": "../linear.json",
289-
"field": "y",
290286
},
291287
)
292288
assert html_result["../linear.json"]["data"]["values"] == _update_datapoints(
293289
linear_v2,
294290
{
295291
REVISION_FIELD: "workspace",
296-
"filename": "../linear.json",
297-
"field": "y",
298292
},
299293
) + _update_datapoints(
300294
linear_v1,
301295
{
302296
REVISION_FIELD: "HEAD",
303-
"filename": "../linear.json",
304-
"field": "y",
305297
},
306298
)
307299
assert json_data["../confusion.json"][0]["content"]["data"][
@@ -434,7 +426,7 @@ def test_repo_with_config_plots(tmp_dir, capsys, repo_with_config_plots):
434426
repo_state = repo_with_config_plots()
435427
plots = next(repo_state)
436428

437-
html_path, json_result, __ = call(capsys)
429+
html_path, _, split_json_result = call(capsys)
438430

439431
assert os.path.exists(html_path)
440432
html_result = extract_vega_specs(
@@ -450,19 +442,22 @@ def test_repo_with_config_plots(tmp_dir, capsys, repo_with_config_plots):
450442
{
451443
"rev": "workspace",
452444
"filename": "linear_train.json",
453-
"field": "y",
454445
},
455446
) + _update_datapoints(
456447
plots["data"]["linear_test.json"],
457448
{
458449
"rev": "workspace",
459450
"filename": "linear_test.json",
460-
"field": "y",
461451
},
462452
)
463453

464454
assert html_result["linear_train_vs_test"]["data"]["values"] == ble
465-
# TODO check json results once vscode is able to handle flexible plots
455+
assert (
456+
split_json_result["data"]["linear_train_vs_test"][0]["anchor_definitions"][
457+
"<DVC_METRIC_DATA>"
458+
]
459+
== ble
460+
)
466461

467462

468463
@pytest.mark.vscode

tests/unit/render/test_convert.py

Lines changed: 40 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import json
2+
3+
import pytest
4+
15
from dvc.render import (
2-
ANCHORS_Y_DEFN,
6+
ANCHOR_DEFINITIONS,
37
REVISION_FIELD,
48
REVISIONS_KEY,
59
SRC_FIELD,
@@ -11,95 +15,67 @@
1115
def test_to_json_vega(mocker):
1216
vega_renderer = mocker.MagicMock()
1317
vega_renderer.TYPE = "vega"
14-
vega_renderer.properties = {
15-
ANCHORS_Y_DEFN: [{"filename": "foo.json", "field": "y"}],
16-
"anchor_revs": ["bar", "foo"],
17-
}
18+
vega_renderer.get_revs.return_value = ["bar", "foo"]
1819
vega_renderer.get_filled_template.return_value = {"this": "is vega"}
19-
vega_renderer.datapoints = [
20-
{
21-
"x": 1,
22-
"y": 2,
23-
"rev": "foo",
24-
"filename": "foo.json",
25-
},
26-
{
27-
"x": 2,
28-
"y": 1,
29-
"rev": "bar",
30-
"filename": "foo.json",
31-
},
32-
]
3320
result = to_json(vega_renderer)
3421
assert result[0] == {
35-
ANCHORS_Y_DEFN: [{"filename": "foo.json", "field": "y"}],
3622
TYPE_KEY: vega_renderer.TYPE,
3723
REVISIONS_KEY: ["bar", "foo"],
3824
"content": {"this": "is vega"},
39-
"datapoints": [
40-
{
41-
"x": 1,
42-
"y": 2,
43-
"filename": "foo.json",
44-
"rev": "foo",
45-
},
46-
{
47-
"x": 2,
48-
"y": 1,
49-
"filename": "foo.json",
50-
"rev": "bar",
51-
},
52-
],
5325
}
5426
vega_renderer.get_filled_template.assert_called()
5527

5628

29+
@pytest.mark.vscode
5730
def test_to_json_vega_split(mocker):
58-
vega_renderer = mocker.MagicMock()
59-
vega_renderer.TYPE = "vega"
60-
vega_renderer.get_filled_template.return_value = {"this": "is split vega"}
61-
vega_renderer.properties = {
62-
ANCHORS_Y_DEFN: [{"filename": "foo.json", "field": "y"}],
63-
"anchor_revs": ["bar", "foo"],
64-
}
65-
vega_renderer.datapoints = [
66-
{
67-
"x": 1,
68-
"y": 2,
69-
"rev": "foo",
70-
"filename": "foo.json",
71-
},
31+
revs = ["bar", "foo"]
32+
content = json.dumps(
7233
{
73-
"x": 2,
74-
"y": 1,
75-
"rev": "bar",
76-
"filename": "foo.json",
34+
"this": "is split vega",
35+
"encoding": {"color": "<DVC_METRIC_COLOR>"},
36+
"data": {"values": "<DVC_METRIC_DATA>"},
37+
}
38+
)
39+
anchor_definitions = {
40+
"<DVC_METRIC_COLOR>": {
41+
"field": "rev",
42+
"scale": {
43+
"domain": revs,
44+
"range": ["#ff0000", "#00ff00"],
45+
},
7746
},
78-
]
79-
result = to_json(vega_renderer, split=True)
80-
assert result[0] == {
81-
ANCHORS_Y_DEFN: [{"filename": "foo.json", "field": "y"}],
82-
TYPE_KEY: vega_renderer.TYPE,
83-
REVISIONS_KEY: ["bar", "foo"],
84-
"content": {"this": "is split vega"},
85-
"datapoints": [
47+
"<DVC_METRIC_DATA>": [
8648
{
8749
"x": 1,
8850
"y": 2,
89-
"filename": "foo.json",
9051
"rev": "foo",
52+
"filename": "foo.json",
9153
},
9254
{
9355
"x": 2,
9456
"y": 1,
95-
"filename": "foo.json",
9657
"rev": "bar",
58+
"filename": "foo.json",
9759
},
9860
],
9961
}
100-
vega_renderer.get_filled_template.assert_called_with(
101-
as_string=False, skip_anchors=["data"]
62+
63+
vega_renderer = mocker.MagicMock()
64+
vega_renderer.TYPE = "vega"
65+
vega_renderer.get_partial_filled_template.return_value = (
66+
content,
67+
{ANCHOR_DEFINITIONS: anchor_definitions},
10268
)
69+
vega_renderer.get_revs.return_value = ["bar", "foo"]
70+
71+
result = to_json(vega_renderer, split=True)
72+
assert result[0] == {
73+
ANCHOR_DEFINITIONS: anchor_definitions,
74+
TYPE_KEY: vega_renderer.TYPE,
75+
REVISIONS_KEY: revs,
76+
"content": content,
77+
}
78+
vega_renderer.get_partial_filled_template.assert_called_once()
10379

10480

10581
def test_to_json_image(mocker):

0 commit comments

Comments
 (0)