mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
#14731: refactor email policy framework.
This patch primarily does two things: (1) it adds some internal-interface methods to Policy that allow for Policy to control the parsing and folding of headers in such a way that we can construct a backward compatibility policy that is 100% compatible with the 3.2 API, while allowing a new policy to implement the email6 API. (2) it adds that backward compatibility policy and refactors the test suite so that the only differences between the 3.2 test_email.py file and the 3.3 test_email.py file is some small changes in test framework and the addition of tests for bugs fixed that apply to the 3.2 API. There are some additional teaks, such as moving just the code needed for the compatibility policy into _policybase, so that the library code can import only _policybase. That way the new code that will be added for email6 will only get imported when a non-compatibility policy is imported.
This commit is contained in:
parent
9242c1378f
commit
c27e52265b
15 changed files with 1391 additions and 519 deletions
|
@ -25,7 +25,7 @@ import re
|
|||
|
||||
from email import errors
|
||||
from email import message
|
||||
from email import policy
|
||||
from email._policybase import compat32
|
||||
|
||||
NLCRE = re.compile('\r\n|\r|\n')
|
||||
NLCRE_bol = re.compile('(\r\n|\r|\n)')
|
||||
|
@ -135,7 +135,7 @@ class BufferedSubFile(object):
|
|||
class FeedParser:
|
||||
"""A feed-style parser of email."""
|
||||
|
||||
def __init__(self, _factory=message.Message, *, policy=policy.default):
|
||||
def __init__(self, _factory=message.Message, *, policy=compat32):
|
||||
"""_factory is called with no arguments to create a new message obj
|
||||
|
||||
The policy keyword specifies a policy object that controls a number of
|
||||
|
@ -145,6 +145,12 @@ class FeedParser:
|
|||
"""
|
||||
self._factory = _factory
|
||||
self.policy = policy
|
||||
try:
|
||||
_factory(policy=self.policy)
|
||||
self._factory_kwds = lambda: {'policy': self.policy}
|
||||
except TypeError:
|
||||
# Assume this is an old-style factory
|
||||
self._factory_kwds = lambda: {}
|
||||
self._input = BufferedSubFile()
|
||||
self._msgstack = []
|
||||
self._parse = self._parsegen().__next__
|
||||
|
@ -181,7 +187,7 @@ class FeedParser:
|
|||
return root
|
||||
|
||||
def _new_message(self):
|
||||
msg = self._factory()
|
||||
msg = self._factory(**self._factory_kwds())
|
||||
if self._cur and self._cur.get_content_type() == 'multipart/digest':
|
||||
msg.set_default_type('message/rfc822')
|
||||
if self._msgstack:
|
||||
|
@ -458,9 +464,7 @@ class FeedParser:
|
|||
lastvalue.append(line)
|
||||
continue
|
||||
if lastheader:
|
||||
# XXX reconsider the joining of folded lines
|
||||
lhdr = EMPTYSTRING.join(lastvalue)[:-1].rstrip('\r\n')
|
||||
self._cur[lastheader] = lhdr
|
||||
self._cur.set_raw(*self.policy.header_source_parse(lastvalue))
|
||||
lastheader, lastvalue = '', []
|
||||
# Check for envelope header, i.e. unix-from
|
||||
if line.startswith('From '):
|
||||
|
@ -487,16 +491,16 @@ class FeedParser:
|
|||
i = line.find(':')
|
||||
if i < 0:
|
||||
defect = errors.MalformedHeaderDefect(line)
|
||||
# XXX: fixme (defect not going through policy)
|
||||
self._cur.defects.append(defect)
|
||||
continue
|
||||
lastheader = line[:i]
|
||||
lastvalue = [line[i+1:].lstrip()]
|
||||
lastvalue = [line]
|
||||
# Done with all the lines, so handle the last header.
|
||||
if lastheader:
|
||||
# XXX reconsider the joining of folded lines
|
||||
self._cur[lastheader] = EMPTYSTRING.join(lastvalue).rstrip('\r\n')
|
||||
self._cur.set_raw(*self.policy.header_source_parse(lastvalue))
|
||||
|
||||
|
||||
|
||||
class BytesFeedParser(FeedParser):
|
||||
"""Like FeedParser, but feed accepts bytes."""
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue