diff --git a/pungi/wrappers/variants.py b/pungi/wrappers/variants.py index a57daaf3..36bc6182 100755 --- a/pungi/wrappers/variants.py +++ b/pungi/wrappers/variants.py @@ -39,6 +39,21 @@ def get_variants_dtd(logger=None): return variants_dtd +class VariantsValidationError(ValueError): + pass + + +NO_WHITESPACE_ELEMENTS = [ + "arch", + "environment", + "group", + "kojitag", + "module", + "name", + "package", +] + + class VariantsXmlParser(object): def __init__(self, file_obj, tree_arches=None, tree_variants=None, logger=None): self.tree = lxml.etree.parse(file_obj) @@ -61,7 +76,24 @@ class VariantsXmlParser(object): def validate(self): if not self.dtd.validate(self.tree): errors = [str(i) for i in self.dtd.error_log.filter_from_errors()] - raise ValueError("Variants XML doesn't validate:\n%s" % "\n".join(errors)) + raise VariantsValidationError( + "Variants XML doesn't validate:\n%s" % "\n".join(errors) + ) + + errors = [] + for text in self.tree.xpath("//text()"): + if text != text.strip() and not text.is_tail: + e = text.getparent() + if e.tag in NO_WHITESPACE_ELEMENTS: + errors.append( + "Tag %s on line %s contains leading or trailing whitespace" + % (e.tag, e.sourceline) + ) + + if errors: + raise VariantsValidationError( + "Variants XML doesn't validate:\n%s" % "\n".join(errors) + ) def parse_variant_node(self, variant_node, parent=None): variant_dict = { diff --git a/tests/test_variant_wrapper.py b/tests/test_variant_wrapper.py new file mode 100644 index 00000000..34cf31ac --- /dev/null +++ b/tests/test_variant_wrapper.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +try: + import unittest2 as unittest +except ImportError: + import unittest +import os +import sys +from six.moves import cStringIO + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) + +from pungi.wrappers.variants import VariantsXmlParser + +VARIANTS_WITH_WHITESPACE = """ + + + x86_64 + core + foo + + +""" + + +class TestVariantsXmlParser(unittest.TestCase): + def test_whitespace_in_file(self): + input = cStringIO(VARIANTS_WITH_WHITESPACE) + + with self.assertRaises(ValueError) as ctx: + VariantsXmlParser(input) + + self.assertIn("Tag arch on line 4", str(ctx.exception)) + self.assertIn("Tag group on line 5", str(ctx.exception)) + self.assertIn("Tag environment on line 6", str(ctx.exception))