diff --git a/.travis.yml b/.travis.yml index 6a0aaa0..a6a39d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: python env: # These should match the tox env list - - TOXENV=py26 - TOXENV=py27 - TOXENV=py33 - TOXENV=py34 - TOXENV=pypy - TOXENV=pypy3 -install: pip install coveralls tox +install: + - pip install coveralls tox script: tox # Special snowflake. Our tests depend on making real commits. before_install: diff --git a/README.md b/README.md index 773fb81..091a8a4 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ Add this to your `.pre-commit-config.yaml` - Use `args: ['--django']` to match `test*.py` instead. - `pyflakes` - Run pyflakes on your python files. - `pretty-format-json` - Checks that all your JSON files are pretty + - Use `args: ['--autofix']` to automatically fixing the encountered not-pretty-formatted files and + `args: ['--no-sort-keys']` to disable the sort on the keys. - `requirements-txt-fixer` - Sorts entries in requirements.txt - `trailing-whitespace` - Trims trailing whitespace. - Markdown linebreak trailing spaces preserved for `.md` and`.markdown`; diff --git a/pre_commit_hooks/pretty_format_json.py b/pre_commit_hooks/pretty_format_json.py index d22dada..6bcc9b0 100644 --- a/pre_commit_hooks/pretty_format_json.py +++ b/pre_commit_hooks/pretty_format_json.py @@ -2,14 +2,16 @@ from __future__ import print_function import argparse import sys +from collections import OrderedDict import simplejson -def _get_pretty_format(contents, indent): +def _get_pretty_format(contents, indent, sort_keys=True): return simplejson.dumps( - simplejson.loads(contents), - sort_keys=True, + simplejson.loads(contents, + object_pairs_hook=None if sort_keys else OrderedDict), + sort_keys=sort_keys, indent=indent ) + "\n" # dumps don't end with a newline @@ -34,6 +36,13 @@ def pretty_format_json(argv=None): default=2, help='Number of indent spaces used to pretty-format files' ) + parser.add_argument( + '--no-sort-keys', + action='store_true', + dest='no_sort_keys', + default=False, + help='Keep JSON nodes in the same order' + ) parser.add_argument('filenames', nargs='*', help='Filenames to fix') args = parser.parse_args(argv) @@ -46,7 +55,7 @@ def pretty_format_json(argv=None): contents = f.read() f.close() - pretty_contents = _get_pretty_format(contents, args.indent) + pretty_contents = _get_pretty_format(contents, args.indent, (not args.no_sort_keys)) if contents != pretty_contents: print("File {0} is not pretty-formatted".format(json_file)) diff --git a/testing/resources/not_pretty_formatted_json.json b/testing/resources/not_pretty_formatted_json.json index 6376d59..58b1d02 100644 --- a/testing/resources/not_pretty_formatted_json.json +++ b/testing/resources/not_pretty_formatted_json.json @@ -1,5 +1,6 @@ { - "foo": "bar", - "alist": [2, 34, 234], - "blah": null + "foo": + "bar", + "alist": [2, 34, 234], + "blah": null } diff --git a/testing/resources/unsorted_pretty_formatted_json.json b/testing/resources/unsorted_pretty_formatted_json.json new file mode 100644 index 0000000..fe8bf5e --- /dev/null +++ b/testing/resources/unsorted_pretty_formatted_json.json @@ -0,0 +1,9 @@ +{ + "foo": "bar", + "alist": [ + 34, + 2, + 234 + ], + "blah": null +} diff --git a/tests/pretty_format_json_test.py b/tests/pretty_format_json_test.py index 6165a13..443c20f 100644 --- a/tests/pretty_format_json_test.py +++ b/tests/pretty_format_json_test.py @@ -8,6 +8,7 @@ from testing.util import get_resource_path @pytest.mark.parametrize(('filename', 'expected_retval'), ( ('not_pretty_formatted_json.json', 1), + ('unsorted_pretty_formatted_json.json', 1), ('pretty_formatted_json.json', 0), )) def test_pretty_format_json(filename, expected_retval): @@ -15,6 +16,16 @@ def test_pretty_format_json(filename, expected_retval): assert ret == expected_retval +@pytest.mark.parametrize(('filename', 'expected_retval'), ( + ('not_pretty_formatted_json.json', 1), + ('unsorted_pretty_formatted_json.json', 0), + ('pretty_formatted_json.json', 0), +)) +def test_unsorted_pretty_format_json(filename, expected_retval): + ret = pretty_format_json(['--no-sort-keys', get_resource_path(filename)]) + assert ret == expected_retval + + def test_autofix_pretty_format_json(tmpdir): srcfile = tmpdir.join('to_be_json_formatted.json') with io.open(get_resource_path('not_pretty_formatted_json.json')) as f: