mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
#15160: Extend the new email parser to handle MIME headers.
This code passes all the same tests that the existing RFC mime header parser passes, plus a bunch of additional ones. There are a couple of commented out tests where there are issues with the folding. The folding doesn't normally get invoked for headers parsed from source, and the cases are marginal anyway (headers with invalid binary data) so I'm not worried about them, but will fix them after the beta. There are things that can be done to make this API even more convenient, but I think this is a solid foundation worth having. And the parser is a full RFC parser, so it handles cases that the current parser doesn't. (There are also probably cases where it fails when the current parser doesn't, but I haven't found them yet ;) Oh, yeah, and there are some really ugly bits in the parser for handling some 'postel' cases that are unfortunately common. I hope/plan to to eventually refactor a lot of the code in the parser which should reduce the line count...but there is no escaping the fact that the error recovery is welter of special cases.
This commit is contained in:
parent
49c15d4a5f
commit
97f43c019f
6 changed files with 1918 additions and 34 deletions
|
@ -3,7 +3,7 @@ import unittest
|
|||
from email import _header_value_parser as parser
|
||||
from email import errors
|
||||
from email import policy
|
||||
from test.test_email import TestEmailBase
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
|
||||
class TestTokens(TestEmailBase):
|
||||
|
||||
|
@ -28,7 +28,32 @@ class TestTokens(TestEmailBase):
|
|||
self.assertDefectsEqual(parts[2].all_defects, [errors.UndecodableBytesDefect])
|
||||
|
||||
|
||||
class TestParser(TestEmailBase):
|
||||
class TestParserMixin:
|
||||
|
||||
def _assert_results(self, tl, rest, string, value, defects, remainder,
|
||||
comments=None):
|
||||
self.assertEqual(str(tl), string)
|
||||
self.assertEqual(tl.value, value)
|
||||
self.assertDefectsEqual(tl.all_defects, defects)
|
||||
self.assertEqual(rest, remainder)
|
||||
if comments is not None:
|
||||
self.assertEqual(tl.comments, comments)
|
||||
|
||||
def _test_get_x(self, method, source, string, value, defects,
|
||||
remainder, comments=None):
|
||||
tl, rest = method(source)
|
||||
self._assert_results(tl, rest, string, value, defects, remainder,
|
||||
comments=None)
|
||||
return tl
|
||||
|
||||
def _test_parse_x(self, method, input, string, value, defects,
|
||||
comments=None):
|
||||
tl = method(input)
|
||||
self._assert_results(tl, '', string, value, defects, '', comments)
|
||||
return tl
|
||||
|
||||
|
||||
class TestParser(TestParserMixin, TestEmailBase):
|
||||
|
||||
# _wsp_splitter
|
||||
|
||||
|
@ -49,19 +74,6 @@ class TestParser(TestEmailBase):
|
|||
['foo', ' \t ', 'def jik'])
|
||||
|
||||
|
||||
# test harness
|
||||
|
||||
def _test_get_x(self, method, input, string, value, defects,
|
||||
remainder, comments=None):
|
||||
token, rest = method(input)
|
||||
self.assertEqual(str(token), string)
|
||||
self.assertEqual(token.value, value)
|
||||
self.assertDefectsEqual(token.all_defects, defects)
|
||||
self.assertEqual(rest, remainder)
|
||||
if comments is not None:
|
||||
self.assertEqual(token.comments, comments)
|
||||
return token
|
||||
|
||||
# get_fws
|
||||
|
||||
def test_get_fws_only(self):
|
||||
|
@ -2390,6 +2402,67 @@ class TestParser(TestEmailBase):
|
|||
str(address_list.mailboxes[2]))
|
||||
|
||||
|
||||
@parameterize
|
||||
class Test_parse_mime_version(TestParserMixin, TestEmailBase):
|
||||
|
||||
def mime_version_as_value(self,
|
||||
value,
|
||||
tl_str,
|
||||
tl_value,
|
||||
major,
|
||||
minor,
|
||||
defects):
|
||||
mime_version = self._test_parse_x(parser.parse_mime_version,
|
||||
value, tl_str, tl_value, defects)
|
||||
self.assertEqual(mime_version.major, major)
|
||||
self.assertEqual(mime_version.minor, minor)
|
||||
|
||||
mime_version_params = {
|
||||
|
||||
'rfc_2045_1': (
|
||||
'1.0',
|
||||
'1.0',
|
||||
'1.0',
|
||||
1,
|
||||
0,
|
||||
[]),
|
||||
|
||||
'RFC_2045_2': (
|
||||
'1.0 (produced by MetaSend Vx.x)',
|
||||
'1.0 (produced by MetaSend Vx.x)',
|
||||
'1.0 ',
|
||||
1,
|
||||
0,
|
||||
[]),
|
||||
|
||||
'RFC_2045_3': (
|
||||
'(produced by MetaSend Vx.x) 1.0',
|
||||
'(produced by MetaSend Vx.x) 1.0',
|
||||
' 1.0',
|
||||
1,
|
||||
0,
|
||||
[]),
|
||||
|
||||
'RFC_2045_4': (
|
||||
'1.(produced by MetaSend Vx.x)0',
|
||||
'1.(produced by MetaSend Vx.x)0',
|
||||
'1. 0',
|
||||
1,
|
||||
0,
|
||||
[]),
|
||||
|
||||
'empty': (
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
None,
|
||||
None,
|
||||
[errors.HeaderMissingRequiredValue]),
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class TestFolding(TestEmailBase):
|
||||
|
||||
policy = policy.default
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue