From 6883485395b7717c0ae8ba1e8923d64f4f5b30f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20P=C3=A9rez?= Date: Sun, 6 Oct 2024 00:57:18 -0400 Subject: [PATCH] Disallow --unique alongside --ignore-cases in file-contents-sorter Closes #794: using these flags at the same time results in undefined behavior - the final ordering is not guaranteed as --unique breaks sorting due to passing the contents through a set. NOTE: I added a newline before and after the mutex group to be consistent with other usages of mutex groups (e.g., check_builtin_literals.py) in this repo. --- pre_commit_hooks/file_contents_sorter.py | 7 ++++-- tests/file_contents_sorter_test.py | 27 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/pre_commit_hooks/file_contents_sorter.py b/pre_commit_hooks/file_contents_sorter.py index bfbeb257..4435d6a6 100644 --- a/pre_commit_hooks/file_contents_sorter.py +++ b/pre_commit_hooks/file_contents_sorter.py @@ -54,18 +54,21 @@ def sort_file_contents( def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser() parser.add_argument('filenames', nargs='+', help='Files to sort') - parser.add_argument( + + mutex = parser.add_mutually_exclusive_group(required=False) + mutex.add_argument( '--ignore-case', action='store_const', const=bytes.lower, default=None, help='fold lower case to upper case characters', ) - parser.add_argument( + mutex.add_argument( '--unique', action='store_true', help='ensure each line is unique', ) + args = parser.parse_args(argv) retv = PASS diff --git a/tests/file_contents_sorter_test.py b/tests/file_contents_sorter_test.py index 49b3b793..f178ae6e 100644 --- a/tests/file_contents_sorter_test.py +++ b/tests/file_contents_sorter_test.py @@ -67,25 +67,34 @@ FAIL, b'Fie\nFoe\nfee\nfum\n', ), + ), +) +def test_integration(input_s, argv, expected_retval, output, tmpdir): + path = tmpdir.join('file.txt') + path.write_binary(input_s) + + output_retval = main([str(path)] + argv) + + assert path.read_binary() == output + assert output_retval == expected_retval + + +@pytest.mark.parametrize( + ('input_s', 'argv'), + ( ( b'fee\nFie\nFoe\nfum\n', ['--unique', '--ignore-case'], - PASS, - b'fee\nFie\nFoe\nfum\n', ), ( b'fee\nfee\nFie\nFoe\nfum\n', ['--unique', '--ignore-case'], - FAIL, - b'fee\nFie\nFoe\nfum\n', ), ), ) -def test_integration(input_s, argv, expected_retval, output, tmpdir): +def test_integration_invalid_args(input_s, argv, tmpdir): path = tmpdir.join('file.txt') path.write_binary(input_s) - output_retval = main([str(path)] + argv) - - assert path.read_binary() == output - assert output_retval == expected_retval + with pytest.raises(SystemExit): + main([str(path)] + argv)