# Buggy code
def _ReadLine(
    self, parser_mediator, file_entry, text_file_object, max_len=0, quiet=False, depth=0
):
    """Read a single line from a text file and return it back.

    Args:
      parser_mediator: A parser mediator object (instance of ParserMediator).
      file_entry: A file entry object (instance of dfvfs.FileEntry).
      text_file_object: A text file object (instance of dfvfs.TextFile).
      max_len: If defined determines the maximum number of bytes a single line
               can take.
      quiet: If True then a decode warning is not displayed.
      depth: A threshold of how many newlines we can encounter before bailing
             out.

    Returns:
      A single line read from the file-like object, or the maximum number of
      characters (if max_len defined and line longer than the defined size).
    """
    if max_len:
        line = text_file_object.readline(max_len)
    else:
        line = text_file_object.readline()

    if not line:
        return

    # If line is empty, skip it and go on.
    if line == "\n" or line == "\r\n":
        # Max 40 new lines in a row before we bail out.
        if depth == 40:
            return ""

        return self._ReadLine(
            parser_mediator,
            file_entry,
            text_file_object,
            max_len=max_len,
            depth=depth + 1,
        )

    if not self.encoding:
        return line.strip()

    try:
        decoded_line = line.decode(self.encoding)
        return decoded_line.strip()
    except UnicodeDecodeError:
        if not quiet:
            logging.warning(
                (
                    "Unable to decode line [{0:s}...] with encoding: {1:s} in "
                    "file: {2:s}"
                ).format(
                    repr(line[1:30]),
                    self.encoding,
                    parser_mediator.GetDisplayName(file_entry),
                )
            )
        return line.strip()


# Traceback (UnicodeDecodeError)
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/plaso/engine/worker.py", line 169, in _ParseFileEntryWithParser
parser_object.UpdateChainAndParse(self._parser_mediator)
File "/usr/lib/python2.7/dist-packages/plaso/parsers/interface.py", line 72, in UpdateChainAndParse
self.Parse(parser_mediator, **kwargs)
File "/usr/lib/python2.7/dist-packages/plaso/parsers/interface.py", line 256, in Parse
self.ParseFileObject(parser_mediator, file_object, **kwargs)
File "/usr/lib/python2.7/dist-packages/plaso/parsers/text_parser.py", line 160, in ParseFileObject
_ = self.NextToken()
File "/usr/lib/python2.7/dist-packages/plaso/lib/lexer.py", line 191, in NextToken
return Lexer.NextToken(self)
File "/usr/lib/python2.7/dist-packages/plaso/lib/lexer.py", line 99, in NextToken
possible_next_state = callback(string=m.group(0), match=m)
File "/usr/lib/python2.7/dist-packages/plaso/parsers/text_parser.py", line 119, in ParseIncomplete
self.attributes['body'] += match.group(0)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

# Fixed code
def _ReadLine(
    self, parser_mediator, file_entry, text_file_object, max_len=0, quiet=False, depth=0
):
    """Read a single line from a text file and return it back.

    Args:
      parser_mediator: a parser mediator object (instance of ParserMediator).
      file_entry: a file entry object (instance of dfvfs.FileEntry).
      text_file_object: a text file object (instance of dfvfs.TextFile).
      max_len: if defined determines the maximum number of bytes a single line
               can take.
      quiet: if True then a decode warning is not displayed.
      depth: a threshold of how many newlines we can encounter before bailing
             out.

    Returns:
      A single line read from the file-like object, or the maximum number of
      characters (if max_len defined and line longer than the defined size).
    """
    if max_len:
        line = text_file_object.readline(max_len)
    else:
        line = text_file_object.readline()

    if not line:
        return

    # If line is empty, skip it and go on.
    if line == "\n" or line == "\r\n":
        # Max 40 new lines in a row before we bail out.
        if depth == 40:
            return ""

        return self._ReadLine(
            parser_mediator,
            file_entry,
            text_file_object,
            max_len=max_len,
            depth=depth + 1,
        )

    if not self.encoding:
        return line.strip()

    try:
        decoded_line = line.decode(self.encoding)
        return decoded_line.strip()
    except UnicodeDecodeError:
        if not quiet:
            logging.warning(
                (
                    "Unable to decode line [{0:s}...] with encoding: {1:s} in "
                    "file: {2:s}"
                ).format(
                    repr(line[1:30]),
                    self.encoding,
                    parser_mediator.GetDisplayName(file_entry),
                )
            )
        return line.strip()