Add a hook to verify python ast.
diff --git a/README.md b/README.md index 93b6360..65e8617 100644 --- a/README.md +++ b/README.md
@@ -28,6 +28,7 @@ see `.pre-commit-config.yaml` in this repository for an example. - `check-added-large-files` - Prevent giant files from being committed. - Specify what is "too large" with `args: ['--maxkb=123']` (default=500kB). +- `check-ast` - Simply check whether files parse as valid python. - `check-case-conflict` - Check for files with names that would conflict on a case-insensitive filesystem like MacOS HFS+ or Windows FAT. - `check-docstring-first` - Checks for a common error of placing code before
diff --git a/hooks.yaml b/hooks.yaml index 9282867..8fcbe78 100644 --- a/hooks.yaml +++ b/hooks.yaml
@@ -12,6 +12,12 @@ language: python # Match all files files: '' +- id: check-ast + name: Check python ast + description: Simply check whether the files parse as valid python. + entry: check-ast + language: python + files: '\.py$' - id: check-case-conflict name: Check for case conflicts description: Check for files that would conflict in case-insensitive filesystems
diff --git a/pre_commit_hooks/check_ast.py b/pre_commit_hooks/check_ast.py new file mode 100644 index 0000000..c993e6a --- /dev/null +++ b/pre_commit_hooks/check_ast.py
@@ -0,0 +1,36 @@ +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import ast +import os.path +import sys +import traceback + + +def check_ast(argv=None): + parser = argparse.ArgumentParser() + parser.add_argument('filenames', nargs='*') + args = parser.parse_args(argv) + + _, interpreter = os.path.split(sys.executable) + + retval = 0 + for filename in args.filenames: + + try: + ast.parse(open(filename, 'rb').read(), filename=filename) + except SyntaxError: + print('{0}: failed parsing with {1}:'.format( + filename, interpreter, + )) + print('\n{0}'.format( + ' ' + traceback.format_exc().replace('\n', '\n ') + )) + retval = 1 + return retval + + +if __name__ == '__main__': + exit(check_ast())
diff --git a/setup.py b/setup.py index 7a66dcf..4fefeaa 100644 --- a/setup.py +++ b/setup.py
@@ -38,6 +38,7 @@ 'console_scripts': [ 'autopep8-wrapper = pre_commit_hooks.autopep8_wrapper:main', 'check-added-large-files = pre_commit_hooks.check_added_large_files:main', + 'check-ast = pre_commit_hooks.check_ast:check_ast', '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',
diff --git a/tests/check_ast_test.py b/tests/check_ast_test.py new file mode 100644 index 0000000..64916ba --- /dev/null +++ b/tests/check_ast_test.py
@@ -0,0 +1,15 @@ +from __future__ import absolute_import +from __future__ import unicode_literals + +from pre_commit_hooks.check_ast import check_ast +from testing.util import get_resource_path + + +def test_failing_file(): + ret = check_ast([get_resource_path('cannot_parse_ast.notpy')]) + assert ret == 1 + + +def test_passing_file(): + ret = check_ast([__file__]) + assert ret == 0