diff -r 4c1d543135ef Lib/email/feedparser.py --- a/Lib/email/feedparser.py Thu Jul 31 23:58:27 2014 -0500 +++ b/Lib/email/feedparser.py Sat Aug 02 16:24:36 2014 +0300 @@ -50,8 +50,8 @@ simple abstraction -- it parses until EOF closes the current message. """ def __init__(self): - # The last partial line pushed into this object. - self._partial = '' + # Chunks of the last partial line pushed into this object. + self._partial = [] # The list of full, pushed lines, in reverse order self._lines = [] # The stack of false-EOF checking predicates. @@ -67,8 +67,8 @@ def close(self): # Don't forget any trailing partial line. - self._lines.append(self._partial) - self._partial = '' + self._lines.append(''.join(self._partial)) + self._partial = [] self._closed = True def readline(self): @@ -96,16 +96,27 @@ def push(self, data): """Push some new data into this object.""" - # Handle any previous leftovers - data, self._partial = self._partial + data, '' + if not data: + return # Crack into lines, but preserve the linesep characters on the end of each parts = data.splitlines(True) + if self._partial and self._partial[-1].endswith('\r'): + if parts[0] != '\n': + parts.insert(0, '') + else: + # If there is no '\n' in data + if len(parts) == 1 and not parts[-1].endswith('\n'): + self._partial.append(data) + return + # Handle any previous leftovers + parts[0] = ''.join(self._partial) + parts[0] + self._partial = [] # If the last element of the list does not end in a newline, then treat # it as a partial line. We only check for '\n' here because a line # ending with '\r' might be a line that was split in the middle of a # '\r\n' sequence (see bugs 1555570 and 1721862). - if parts and not parts[-1].endswith('\n'): - self._partial = parts.pop() + if not parts[-1].endswith('\n'): + self._partial = [parts.pop()] self.pushlines(parts) def pushlines(self, lines):