From 573111703e545aa2f749f21dff435f65aa672a22 Mon Sep 17 00:00:00 2001 From: David de la Iglesia Castro Date: Tue, 6 Sep 2022 10:25:32 +0200 Subject: [PATCH] vega: Escape special characters in `field` and `title`. Closes #80 --- src/dvc_render/vega.py | 2 ++ src/dvc_render/vega_templates.py | 7 +++++++ tests/test_templates.py | 6 ++++++ tests/test_vega.py | 17 +++++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/src/dvc_render/vega.py b/src/dvc_render/vega.py index ff17441..cdcae14 100644 --- a/src/dvc_render/vega.py +++ b/src/dvc_render/vega.py @@ -81,6 +81,8 @@ def get_filled_template( f"Template '{self.template.name}' " f"is not using '{anchor}' anchor" ) + else: + value = self.template.escape_special_characters(value) content = self.template.fill_anchor(content, name, value) return content diff --git a/src/dvc_render/vega_templates.py b/src/dvc_render/vega_templates.py index 8ade77e..a63b74c 100644 --- a/src/dvc_render/vega_templates.py +++ b/src/dvc_render/vega_templates.py @@ -72,6 +72,13 @@ def fill_anchor(cls, content, name, value) -> str: ) return content.replace(cls.anchor_str(name), value_str) + @classmethod + def escape_special_characters(cls, value: str) -> str: + "Escape special characters in `value`" + for character in (".", "[", "]"): + value = value.replace(character, "\\" + character) + return value + @classmethod def anchor_str(cls, name) -> str: "Get string wrapping ANCHOR formatted with name." diff --git a/tests/test_templates.py b/tests/test_templates.py index c197394..5d64f15 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -6,6 +6,7 @@ TEMPLATES, LinearTemplate, ScatterTemplate, + Template, TemplateContentDoesNotMatch, TemplateNotFoundError, dump_templates, @@ -76,3 +77,8 @@ def test_raise_on_init_modified(tmp_dir): with pytest.raises(TemplateContentDoesNotMatch): dump_templates(output=".", targets=["linear"]) + + +def test_escape_special_characters(): + value = "foo.bar[2]" + assert Template.escape_special_characters(value) == "foo\\.bar\\[2\\]" diff --git a/tests/test_vega.py b/tests/test_vega.py index e946ca7..b9218aa 100644 --- a/tests/test_vega.py +++ b/tests/test_vega.py @@ -159,3 +159,20 @@ def test_invalid_generate_markdown(): match="`generate_markdown` can only be used with `LinearTemplate`", ): renderer.generate_markdown("output") + + +def test_escape_special_characters(): + datapoints = [ + {"foo.bar[0]": 0, "foo.bar[1]": 3}, + {"foo.bar[0]": 1, "foo.bar[1]": 4}, + ] + props = {"template": "simple", "x": "foo.bar[0]", "y": "foo.bar[1]"} + renderer = VegaRenderer(datapoints, "foo", **props) + filled = json.loads(renderer.get_filled_template()) + # data is not escaped + assert filled["data"]["values"][0] == datapoints[0] + # field and title yes + assert filled["encoding"]["x"]["field"] == "foo\\.bar\\[0\\]" + assert filled["encoding"]["x"]["title"] == "foo\\.bar\\[0\\]" + assert filled["encoding"]["y"]["field"] == "foo\\.bar\\[1\\]" + assert filled["encoding"]["y"]["title"] == "foo\\.bar\\[1\\]"