diff --git a/.travis.yml b/.travis.yml index 39d83d3..720eec7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ env: # These should match the tox env list - TOXENV=py33 - TOXENV=py34 - TOXENV=pypy + - TOXENV=pypy3 install: pip install coveralls tox --use-mirrors script: tox # Special snowflake. Our tests depend on making real commits. diff --git a/README.md b/README.md index 82e48fd..7b9604b 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Add this to your `.pre-commit-config.yaml` - `check-case-conflict` - Check for files that would conflict in case-insensitive filesystems. - `check-docstring-first` - Checks a common error of defining a docstring after code. - `check-json` - Attempts to load all json files to verify syntax. +- `check-xml` - Attempts to load all xml files to verify syntax. - `check-yaml` - Attempts to load all yaml files to verify syntax. - `debug-statements` - Check for pdb / ipdb / pudb statements in code. - `end-of-file-fixer` - Makes sure files end in a newline and only a newline. diff --git a/hooks.yaml b/hooks.yaml index 4e31f98..d575170 100644 --- a/hooks.yaml +++ b/hooks.yaml @@ -31,6 +31,12 @@ entry: check-json language: python files: \.json$ +- id: check-xml + name: Check Xml + description: This hook checks xml files for parseable syntax. + entry: check-xml + language: python + files: \.xml$ - id: check-yaml name: Check Yaml description: This hook checks yaml files for parseable syntax. diff --git a/pre_commit_hooks/check_xml.py b/pre_commit_hooks/check_xml.py new file mode 100644 index 0000000..926f6e9 --- /dev/null +++ b/pre_commit_hooks/check_xml.py @@ -0,0 +1,28 @@ +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import io +import sys +import xml.sax + + +def check_xml(argv=None): + parser = argparse.ArgumentParser() + parser.add_argument('filenames', nargs='*', help='XML filenames to check.') + args = parser.parse_args(argv) + + retval = 0 + for filename in args.filenames: + try: + with io.open(filename, 'rb') as xml_file: + xml.sax.parse(xml_file, xml.sax.ContentHandler()) + except xml.sax.SAXException as exc: + print('{0}: Failed to xml parse ({1})'.format(filename, exc)) + retval = 1 + return retval + + +if __name__ == '__main__': + sys.exit(check_xml()) diff --git a/requirements-dev.txt b/requirements-dev.txt index b3a7721..97343d5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,6 @@ -e . +astroid<1.3.3 coverage flake8 mock diff --git a/setup.py b/setup.py index 3addc42..4ed93f8 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,7 @@ setup( 'check-case-conflict = pre_commit_hooks.check_case_conflict:main', 'check-docstring-first = pre_commit_hooks.check_docstring_first:main', 'check-json = pre_commit_hooks.check_json:check_json', + 'check-xml = pre_commit_hooks.check_xml:check_xml', 'check-yaml = pre_commit_hooks.check_yaml:check_yaml', 'debug-statement-hook = pre_commit_hooks.debug_statement_hook:debug_statement_hook', 'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer', diff --git a/testing/resources/bad_xml.notxml b/testing/resources/bad_xml.notxml new file mode 100644 index 0000000..e6edcc7 --- /dev/null +++ b/testing/resources/bad_xml.notxml @@ -0,0 +1 @@ + diff --git a/testing/resources/ok_xml.xml b/testing/resources/ok_xml.xml new file mode 100644 index 0000000..134f37c --- /dev/null +++ b/testing/resources/ok_xml.xml @@ -0,0 +1,4 @@ + + Hi + Earth + diff --git a/tests/check_xml_test.py b/tests/check_xml_test.py new file mode 100644 index 0000000..99b0902 --- /dev/null +++ b/tests/check_xml_test.py @@ -0,0 +1,13 @@ +import pytest + +from pre_commit_hooks.check_xml import check_xml +from testing.util import get_resource_path + + +@pytest.mark.parametrize(('filename', 'expected_retval'), ( + ('bad_xml.notxml', 1), + ('ok_xml.xml', 0), +)) +def test_check_xml(filename, expected_retval): + ret = check_xml([get_resource_path(filename)]) + assert ret == expected_retval diff --git a/tox.ini b/tox.ini index 4b043ba..b37a773 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] project = pre_commit_hooks # These should match the travis env list -envlist = py26,py27,py33,py34,pypy +envlist = py26,py27,py33,py34,pypy,pypy3 [testenv] install_command = pip install --use-wheel {opts} {packages}