# Buggy code
def reverse_readlines(filename, buf_size=2097152, encoding=default_encoding):
    """A generator that returns the lines of a file in reverse order.

    Thanks to Andomar: http://stackoverflow.com/a/23646049

    :param filename:
    :type filename: str
    :param encoding:
    :type encoding: str
    :param buf_size:
    :return:
    :rtype: collections.Iterable of str
    """
    new_line = "\n"
    with io.open(filename, "rb") as fh:
        segment = None
        offset = 0
        fh.seek(0, os.SEEK_END)
        file_size = remaining_size = fh.tell()
        while remaining_size > 0:
            offset = min(file_size, offset + buf_size)
            fh.seek(file_size - offset)
            buf = fh.read(min(remaining_size, buf_size))
            buf = text_type(
                buf.decode(sys.getfilesystemencoding()) if os.name == "nt" else buf,
                errors="replace",
            )
            remaining_size -= buf_size
            lines = buf.split(new_line)
            # the first line of the buffer is probably not a complete line so
            # we'll save it and append it to the last line of the next buffer
            # we read
            if segment is not None:
                # if the previous chunk starts right from the beginning of line
                # do not concact the segment to the last line of new chunk
                # instead, yield the segment first
                if buf[-1] is not new_line:
                    lines[-1] += segment
                else:
                    yield segment
            segment = lines[0]
            for index in range(len(lines) - 1, 0, -1):
                if len(lines[index]):
                    yield lines[index]
        # Don't yield None if the file was empty
        if segment is not None:
            yield segment


# Traceback (TypeError)
2016-10-19 21:48:16 ERROR    Thread-24 :: [6eca5cd] Failed doing web ui callback: Traceback (most recent call last):
File "H:\usr\local\medusa\medusa\server\web\core\base.py", line 271, in async_call
result = function(**kwargs)
File "H:\usr\local\medusa\medusa\server\web\core\error_logs.py", line 133, in viewlog
predicate=lambda l: filter_logline(l, min_level=min_level,
File "H:\usr\local\medusa\medusa\logger.py", line 137, in read_loglines
for line in reverse_readlines(f):
File "H:\usr\local\medusa\medusa\logger.py", line 196, in reverse_readlines
buf = text_type(buf.decode(sys.getfilesystemencoding()) if os.name == 'nt' else buf, errors='replace')
TypeError: decoding Unicode is not supported
Traceback (most recent call last):
File "H:\usr\local\medusa\medusa\server\web\core\base.py", line 271, in async_call
result = function(**kwargs)
File "H:\usr\local\medusa\medusa\server\web\core\error_logs.py", line 133, in viewlog
predicate=lambda l: filter_logline(l, min_level=min_level,
File "H:\usr\local\medusa\medusa\logger.py", line 137, in read_loglines
for line in reverse_readlines(f):
File "H:\usr\local\medusa\medusa\logger.py", line 196, in reverse_readlines
buf = text_type(buf.decode(sys.getfilesystemencoding()) if os.name == 'nt' else buf, errors='replace')
TypeError: decoding Unicode is not supported

# Fixed code
def reverse_readlines(filename, buf_size=2097152, encoding=default_encoding):
    """A generator that returns the lines of a file in reverse order.

    Thanks to Andomar: http://stackoverflow.com/a/23646049

    :param filename:
    :type filename: str
    :param encoding:
    :type encoding: str
    :param buf_size:
    :return:
    :rtype: collections.Iterable of str
    """
    new_line = "\n"
    with io.open(filename, "rb") as fh:
        segment = None
        offset = 0
        fh.seek(0, os.SEEK_END)
        file_size = remaining_size = fh.tell()
        while remaining_size > 0:
            offset = min(file_size, offset + buf_size)
            fh.seek(file_size - offset)
            buf = fh.read(min(remaining_size, buf_size))
            if os.name == "nt":
                buf = buf.decode(sys.getfilesystemencoding())
            if not isinstance(buf, text_type):
                buf = text_type(buf, errors="replace")
            remaining_size -= buf_size
            lines = buf.split(new_line)
            # the first line of the buffer is probably not a complete line so
            # we'll save it and append it to the last line of the next buffer
            # we read
            if segment is not None:
                # if the previous chunk starts right from the beginning of line
                # do not concact the segment to the last line of new chunk
                # instead, yield the segment first
                if buf[-1] is not new_line:
                    lines[-1] += segment
                else:
                    yield segment
            segment = lines[0]
            for index in range(len(lines) - 1, 0, -1):
                if len(lines[index]):
                    yield lines[index]
        # Don't yield None if the file was empty
        if segment is not None:
            yield segment