| """Build step class for validating XML files.""" |
| |
| from __future__ import absolute_import |
| import collections |
| import os |
| import re |
| import xml.etree |
| |
| from helpers import git_utils |
| from slave import base_step |
| |
| _XML_PARSE_ERROR_MSG = 'This XML file failed to parse: {}' |
| _XML_ERROR_POSITION_PATTERN = r'line (?P<linenum>\d+), column \d+' |
| |
| |
| class XmlCheckStep(base_step.BaseStep): |
| """Build step class for validating XML files.""" |
| |
| def __init__(self, **kwargs): |
| """Creates a XmlCheckStep instance. |
| |
| Args: |
| **kwargs: Any additional args to pass to BaseStep. |
| """ |
| base_step.BaseStep.__init__(self, name='xml check', **kwargs) |
| |
| def _parse_error_to_comment(self, err): |
| comment = {'message': _XML_PARSE_ERROR_MSG.format(str(err))} |
| match = re.search(_XML_ERROR_POSITION_PATTERN, str(err)) |
| if match: |
| comment['line'] = match.group('linenum') |
| return comment |
| |
| def run(self): |
| """Attempts to parse all .xml files in the current commit. |
| |
| Sets a build property "review" with the output if there are any errors. |
| |
| Returns: |
| True iff there were no parsing errors. |
| """ |
| comments = collections.defaultdict(list) |
| for xml_filename in self.changed_files(file_extensions=['.xml']): |
| with open(os.path.join(self.directory, xml_filename)) as xml_file: |
| try: |
| xml.etree.ElementTree.parse(xml_file) |
| except xml.etree.ElementTree.ParseError as err: |
| comments[xml_filename].append(self._parse_error_to_comment(err)) |
| |
| if comments: |
| self.add_review({'comments': comments}) |
| return False |
| |
| # No Errors |
| return True |