human
Complete this python program:
def make_line_iter(stream, limit=None, buffer_size=(10 * 1024), cap_at_buffer=False):
assistant
#Here is the Python code you requested.

    """Safely iterates line-based over an input stream.  If the input stream
    is not a :class:`LimitedStream` the `limit` parameter is mandatory.
    This uses the stream\s :meth:`~file.read` method internally as opposite
    to the :meth:`~file.readline` method that is unsafe and can only be used
    in violation of the WSGI specification.  The same problem applies to the
    `__iter__` function of the input stream which calls :meth:`~file.readline`
    without arguments.
    If you need line-by-line processing it\s strongly recommended to iterate
    over the input stream using this helper function.
    .. versionchanged:: 0.8
    This function now ensures that the limit was reached.
    .. versionadded:: 0.9
    added support for iterators as input stream.
    .. versionadded:: 0.11.10
    added support for the `cap_at_buffer` parameter.
    :param stream: the stream or iterate to iterate over.
    :param limit: the limit in bytes for the stream.  (Usually
    content length.  Not necessary if the `stream`
    is a :class:`LimitedStream`.
    :param buffer_size: The optional buffer size.
    :param cap_at_buffer: if this is set chunks are split if they are longer
    than the buffer size.  Internally this is implemented
    that the buffer size might be exhausted by a factor
    of two however.
    """
    _iter = _make_chunk_iter(stream, limit, buffer_size)
    first_item = next(_iter, '')
    if (not first_item):
        return
    s = make_literal_wrapper(first_item)
    empty = s('')
    cr = s('\r')
    lf = s('\n')
    crlf = s('\r\n')
    _iter = chain((first_item,), _iter)
    def _iter_basic_lines():
        _join = empty.join
        buffer = []
        while 1:
            new_data = next(_iter, '')
            if (not new_data):
                break
            new_buf = []
            buf_size = 0
            for item in chain(buffer, new_data.splitlines(True)):
                new_buf.append(item)
                buf_size += len(item)
                if (item and (item[(-1):] in crlf)):
                    (yield _join(new_buf))
                    new_buf = []
                elif (cap_at_buffer and (buf_size >= buffer_size)):
                    rv = _join(new_buf)
                    while (len(rv) >= buffer_size):
                        (yield rv[:buffer_size])
                        rv = rv[buffer_size:]
                    new_buf = [rv]
            buffer = new_buf
        if buffer:
            (yield _join(buffer))
    previous = empty
    for item in _iter_basic_lines():
        if ((item == lf) and (previous[(-1):] == cr)):
            previous += item
            item = empty
        if previous:
            (yield previous)
        previous = item
    if previous:
        (yield previous)