Commit f070f1cb authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #21448: Improve performance of the email feedparser

parent 573b44c1
...@@ -26,6 +26,7 @@ import re ...@@ -26,6 +26,7 @@ import re
from email import errors from email import errors
from email import message from email import message
from email._policybase import compat32 from email._policybase import compat32
from collections import deque
NLCRE = re.compile('\r\n|\r|\n') NLCRE = re.compile('\r\n|\r|\n')
NLCRE_bol = re.compile('(\r\n|\r|\n)') NLCRE_bol = re.compile('(\r\n|\r|\n)')
...@@ -52,8 +53,8 @@ class BufferedSubFile(object): ...@@ -52,8 +53,8 @@ class BufferedSubFile(object):
def __init__(self): def __init__(self):
# Chunks of the last partial line pushed into this object. # Chunks of the last partial line pushed into this object.
self._partial = [] self._partial = []
# The list of full, pushed lines, in reverse order # A deque of full, pushed lines
self._lines = [] self._lines = deque()
# The stack of false-EOF checking predicates. # The stack of false-EOF checking predicates.
self._eofstack = [] self._eofstack = []
# A flag indicating whether the file has been closed or not. # A flag indicating whether the file has been closed or not.
...@@ -78,21 +79,21 @@ class BufferedSubFile(object): ...@@ -78,21 +79,21 @@ class BufferedSubFile(object):
return NeedMoreData return NeedMoreData
# Pop the line off the stack and see if it matches the current # Pop the line off the stack and see if it matches the current
# false-EOF predicate. # false-EOF predicate.
line = self._lines.pop() line = self._lines.popleft()
# RFC 2046, section 5.1.2 requires us to recognize outer level # RFC 2046, section 5.1.2 requires us to recognize outer level
# boundaries at any level of inner nesting. Do this, but be sure it's # boundaries at any level of inner nesting. Do this, but be sure it's
# in the order of most to least nested. # in the order of most to least nested.
for ateof in self._eofstack[::-1]: for ateof in reversed(self._eofstack):
if ateof(line): if ateof(line):
# We're at the false EOF. But push the last line back first. # We're at the false EOF. But push the last line back first.
self._lines.append(line) self._lines.appendleft(line)
return '' return ''
return line return line
def unreadline(self, line): def unreadline(self, line):
# Let the consumer push a line back into the buffer. # Let the consumer push a line back into the buffer.
assert line is not NeedMoreData assert line is not NeedMoreData
self._lines.append(line) self._lines.appendleft(line)
def push(self, data): def push(self, data):
"""Push some new data into this object.""" """Push some new data into this object."""
...@@ -119,8 +120,7 @@ class BufferedSubFile(object): ...@@ -119,8 +120,7 @@ class BufferedSubFile(object):
self.pushlines(parts) self.pushlines(parts)
def pushlines(self, lines): def pushlines(self, lines):
# Reverse and insert at the front of the lines. self._lines.extend(lines)
self._lines[:0] = lines[::-1]
def __iter__(self): def __iter__(self):
return self return self
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment