# Path: pre_commit_hooks/sort_simple_yaml.py
# def first_key(lines: list[str]) -> str:
#     """Returns a string representing the sort key of a block.
# 
#     The sort key is the first YAML key we encounter, ignoring comments, and
#     stripping leading quotes.
# 
#     >>> print(test)
#     # some comment
#     'foo': true
#     >>> first_key(test)
#     'foo'
#     """
#     for line in lines:
#         if line.startswith('#'):
#             continue
#         if any(line.startswith(quote) for quote in QUOTES):
#             return line[1:]
#         return line
#     else:
#         return ''  # not actually reached in reality
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def main(argv: Sequence[str] | None = None) -> int:
#     parser = argparse.ArgumentParser()
#     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
#     args = parser.parse_args(argv)
# 
#     retval = 0
# 
#     for filename in args.filenames:
#         with open(filename, 'r+') as f:
#             lines = [line.rstrip() for line in f.readlines()]
#             new_lines = sort(lines)
# 
#             if lines != new_lines:
#                 print(f'Fixing file `{filename}`')
#                 f.seek(0)
#                 f.write('\n'.join(new_lines) + '\n')
#                 f.truncate()
#                 retval = 1
# 
#     return retval
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def parse_block(lines: list[str], header: bool = False) -> list[str]:
#     """Parse and return a single block, popping off the start of `lines`.
# 
#     If parsing a header block, we stop after we reach a line that is not a
#     comment. Otherwise, we stop after reaching an empty line.
# 
#     :param lines: list of lines
#     :param header: whether we are parsing a header block
#     :return: list of lines that form the single block
#     """
#     block_lines = []
#     while lines and lines[0] and (not header or lines[0].startswith('#')):
#         block_lines.append(lines.pop(0))
#     return block_lines
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def parse_blocks(lines: list[str]) -> list[list[str]]:
#     """Parse and return all possible blocks, popping off the start of `lines`.
# 
#     :param lines: list of lines
#     :return: list of blocks, where each block is a list of lines
#     """
#     blocks = []
# 
#     while lines:
#         if lines[0] == '':
#             lines.pop(0)
#         else:
#             blocks.append(parse_block(lines))
# 
#     return blocks
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def sort(lines: list[str]) -> list[str]:
#     """Sort a YAML file in alphabetical order, keeping blocks together.
# 
#     :param lines: array of strings (without newlines)
#     :return: sorted array of strings
#     """
#     # make a copy of lines since we will clobber it
#     lines = list(lines)
#     new_lines = parse_block(lines, header=True)
# 
#     for block in sorted(parse_blocks(lines), key=first_key):
#         if new_lines:
#             new_lines.append('')
#         new_lines.extend(block)
# 
#     return new_lines


import os
import pytest
from pre_commit_hooks.sort_simple_yaml import first_key
from pre_commit_hooks.sort_simple_yaml import main
from pre_commit_hooks.sort_simple_yaml import parse_block
from pre_commit_hooks.sort_simple_yaml import parse_blocks
from pre_commit_hooks.sort_simple_yaml import sort

    (
        ['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
        ['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
        RETVAL_GOOD,
    ),

    (
        ['# i am', '# a header'],
        ['# i am', '# a header'],
        RETVAL_GOOD,
    ),
]


@pytest.mark.parametrize('bad_lines,good_lines,retval', TEST_SORTS)
def test_integration_good_bad_lines(tmpdir, bad_lines, good_lines, retval):
    file_path = os.path.join(str(tmpdir), 'foo.yaml')

    with open(file_path, 'w') as f:
        f.write('\n'.join(bad_lines) + '\n')

    assert main([file_path]) == retval

    with open(file_path) as f:
        assert [line.rstrip() for line in f.readlines()] == good_lines


def test_parse_header():
    lines = ['# some header', '# is here', '', 'this is not a header']

# Path: pre_commit_hooks/sort_simple_yaml.py
# def first_key(lines: list[str]) -> str:
#     """Returns a string representing the sort key of a block.
# 
#     The sort key is the first YAML key we encounter, ignoring comments, and
#     stripping leading quotes.
# 
#     >>> print(test)
#     # some comment
#     'foo': true
#     >>> first_key(test)
#     'foo'
#     """
#     for line in lines:
#         if line.startswith('#'):
#             continue
#         if any(line.startswith(quote) for quote in QUOTES):
#             return line[1:]
#         return line
#     else:
#         return ''  # not actually reached in reality
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def main(argv: Sequence[str] | None = None) -> int:
#     parser = argparse.ArgumentParser()
#     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
#     args = parser.parse_args(argv)
# 
#     retval = 0
# 
#     for filename in args.filenames:
#         with open(filename, 'r+') as f:
#             lines = [line.rstrip() for line in f.readlines()]
#             new_lines = sort(lines)
# 
#             if lines != new_lines:
#                 print(f'Fixing file `{filename}`')
#                 f.seek(0)
#                 f.write('\n'.join(new_lines) + '\n')
#                 f.truncate()
#                 retval = 1
# 
#     return retval
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def parse_block(lines: list[str], header: bool = False) -> list[str]:
#     """Parse and return a single block, popping off the start of `lines`.
# 
#     If parsing a header block, we stop after we reach a line that is not a
#     comment. Otherwise, we stop after reaching an empty line.
# 
#     :param lines: list of lines
#     :param header: whether we are parsing a header block
#     :return: list of lines that form the single block
#     """
#     block_lines = []
#     while lines and lines[0] and (not header or lines[0].startswith('#')):
#         block_lines.append(lines.pop(0))
#     return block_lines
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def parse_blocks(lines: list[str]) -> list[list[str]]:
#     """Parse and return all possible blocks, popping off the start of `lines`.
# 
#     :param lines: list of lines
#     :return: list of blocks, where each block is a list of lines
#     """
#     blocks = []
# 
#     while lines:
#         if lines[0] == '':
#             lines.pop(0)
#         else:
#             blocks.append(parse_block(lines))
# 
#     return blocks
# 
# Path: pre_commit_hooks/sort_simple_yaml.py
# def sort(lines: list[str]) -> list[str]:
#     """Sort a YAML file in alphabetical order, keeping blocks together.
# 
#     :param lines: array of strings (without newlines)
#     :return: sorted array of strings
#     """
#     # make a copy of lines since we will clobber it
#     lines = list(lines)
#     new_lines = parse_block(lines, header=True)
# 
#     for block in sorted(parse_blocks(lines), key=first_key):
#         if new_lines:
#             new_lines.append('')
#         new_lines.extend(block)
# 
#     return new_lines


# Path: tests/sort_simple_yaml_test.py
import os
import pytest
from pre_commit_hooks.sort_simple_yaml import first_key
from pre_commit_hooks.sort_simple_yaml import main
from pre_commit_hooks.sort_simple_yaml import parse_block
from pre_commit_hooks.sort_simple_yaml import parse_blocks
from pre_commit_hooks.sort_simple_yaml import sort


    (
        ['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
        ['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
        RETVAL_GOOD,
    ),

    (
        ['# i am', '# a header'],
        ['# i am', '# a header'],
        RETVAL_GOOD,
    ),
]


@pytest.mark.parametrize('bad_lines,good_lines,retval', TEST_SORTS)
def test_integration_good_bad_lines(tmpdir, bad_lines, good_lines, retval):
    file_path = os.path.join(str(tmpdir), 'foo.yaml')

    with open(file_path, 'w') as f:
        f.write('\n'.join(bad_lines) + '\n')

    assert main([file_path]) == retval

    with open(file_path) as f:
        assert [line.rstrip() for line in f.readlines()] == good_lines


def test_parse_header():
    lines = ['# some header', '# is here', '', 'this is not a header']

    assert parse_block(lines, header=True) == ['# some header', '# is here']