def split_lines(data, newline, keep_ends=False):
    """Split data along newline boundaries.

    This differs from :py:meth:`str.splitlines` in that it will split across
    a specific newline boundary, rather than against any sequence of newline
    characters.

    Args:
        data (bytes):
            The data to split.

        newline (bytes):
            The newline character(s) used to split the data into lines.

        keep_ends (bool, optional):
            Whether to keep the line endings in the resulting lines.

    Returns:
        list of bytes:
        The split list of lines.
    """
    assert data
    assert newline

    lines = data.split(newline)

    if keep_ends:
        lines = [
            b'%s%s' % (_line, newline)
            for _line in lines
        ]

    # If the very last line of the original text had a newline, then we're
    # going to end up with too many lines at the end. This is because
    # the split() above would have added a final blank entry. Get rid of
    # it.
    if data.endswith(newline):
        lines.pop()
    elif keep_ends:
        lines[-1] = lines[-1][:-len(newline)]

    return lines