diff options
author | Steve Dower <steve.dower@microsoft.com> | 2017-02-04 15:39:38 -0800 |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2017-02-04 15:39:38 -0800 |
commit | 1a5780aabb550cae175ad8711e2f33ba644d0ddb (patch) | |
tree | 68e47eaafb4ccc17bbdb7668c6058984945b332d /Lib/test/test_email | |
parent | 956c7cfa7111ab5458e2f69868a05b7b84fc6843 (diff) | |
parent | d1d8706cdb77e2adbbb4110338dcda0e1811f892 (diff) | |
download | cpython-1a5780aabb550cae175ad8711e2f33ba644d0ddb.tar.gz |
Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0].
Diffstat (limited to 'Lib/test/test_email')
-rw-r--r-- | Lib/test/test_email/__init__.py | 1 | ||||
-rw-r--r-- | Lib/test/test_email/test__header_value_parser.py | 4 | ||||
-rw-r--r-- | Lib/test/test_email/test_asian_codecs.py | 1 | ||||
-rw-r--r-- | Lib/test/test_email/test_email.py | 44 | ||||
-rw-r--r-- | Lib/test/test_email/test_generator.py | 2 | ||||
-rw-r--r-- | Lib/test/test_email/test_headerregistry.py | 1 | ||||
-rw-r--r-- | Lib/test/test_email/test_message.py | 20 | ||||
-rw-r--r-- | Lib/test/test_email/test_parser.py | 91 | ||||
-rw-r--r-- | Lib/test/test_email/test_policy.py | 42 |
9 files changed, 152 insertions, 54 deletions
diff --git a/Lib/test/test_email/__init__.py b/Lib/test/test_email/__init__.py index d4a03ee071..888751e9e6 100644 --- a/Lib/test/test_email/__init__.py +++ b/Lib/test/test_email/__init__.py @@ -1,5 +1,4 @@ import os -import sys import unittest import collections import email diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f7ac0e3ded..26ece6911f 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -581,7 +581,7 @@ class TestParser(TestParserMixin, TestEmailBase): def test_get_comment_quoted_parens(self): self._test_get_x(parser.get_comment, - '(foo\) \(\)bar)', '(foo\) \(\)bar)', ' ', [], '', ['foo) ()bar']) + r'(foo\) \(\)bar)', r'(foo\) \(\)bar)', ' ', [], '', ['foo) ()bar']) def test_get_comment_non_printable(self): self._test_get_x(parser.get_comment, @@ -625,7 +625,7 @@ class TestParser(TestParserMixin, TestEmailBase): def test_get_comment_qs_in_nested_comment(self): comment = self._test_get_x(parser.get_comment, - '(foo (b\)))', '(foo (b\)))', ' ', [], '', ['foo (b\))']) + r'(foo (b\)))', r'(foo (b\)))', ' ', [], '', [r'foo (b\))']) self.assertEqual(comment[2].content, 'b)') # get_cfws diff --git a/Lib/test/test_email/test_asian_codecs.py b/Lib/test/test_email/test_asian_codecs.py index f9cd7d9b4e..1e0caeeaed 100644 --- a/Lib/test/test_email/test_asian_codecs.py +++ b/Lib/test/test_email/test_asian_codecs.py @@ -3,7 +3,6 @@ # email package unit tests for (optional) Asian codecs import unittest -from test.support import run_unittest from test.test_email import TestEmailBase from email.charset import Charset diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 9b86a2aee9..f97ccc6711 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -32,6 +32,7 @@ from email.mime.image import MIMEImage from email.mime.base import MIMEBase from email.mime.message import MIMEMessage from email.mime.multipart import MIMEMultipart +from email.mime.nonmultipart import MIMENonMultipart from email import utils from email import errors from email import encoders @@ -2078,7 +2079,13 @@ YXNkZg== --===============0012394164==--""") self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') + def test_mimebase_default_policy(self): + m = MIMEBase('multipart', 'mixed') + self.assertIs(m.policy, email.policy.compat32) + def test_mimebase_custom_policy(self): + m = MIMEBase('multipart', 'mixed', policy=email.policy.default) + self.assertIs(m.policy, email.policy.default) # Test some badly formatted messages class TestNonConformant(TestEmailBase): @@ -2680,6 +2687,19 @@ message 2 msg = MIMEMultipart() self.assertTrue(msg.is_multipart()) + def test_multipart_default_policy(self): + msg = MIMEMultipart() + msg['To'] = 'a@b.com' + msg['To'] = 'c@d.com' + self.assertEqual(msg.get_all('to'), ['a@b.com', 'c@d.com']) + + def test_multipart_custom_policy(self): + msg = MIMEMultipart(policy=email.policy.default) + msg['To'] = 'a@b.com' + with self.assertRaises(ValueError) as cm: + msg['To'] = 'c@d.com' + self.assertEqual(str(cm.exception), + 'There may be at most 1 To headers in a message') # A general test of parser->model->generator idempotency. IOW, read a message # in, parse it into a message object tree, then without touching the tree, @@ -3033,7 +3053,7 @@ class TestMiscellaneous(TestEmailBase): def test_escape_backslashes(self): self.assertEqual( - utils.formataddr(('Arthur \Backslash\ Foobar', 'person@dom.ain')), + utils.formataddr((r'Arthur \Backslash\ Foobar', 'person@dom.ain')), r'"Arthur \\Backslash\\ Foobar" <person@dom.ain>') a = r'Arthur \Backslash\ Foobar' b = 'person@dom.ain' @@ -3340,6 +3360,27 @@ multipart/report g.flatten(msg, linesep='\r\n') self.assertEqual(s.getvalue(), msgtxt) + def test_mime_classes_policy_argument(self): + with openfile('audiotest.au', 'rb') as fp: + audiodata = fp.read() + with openfile('PyBanner048.gif', 'rb') as fp: + bindata = fp.read() + classes = [ + (MIMEApplication, ('',)), + (MIMEAudio, (audiodata,)), + (MIMEImage, (bindata,)), + (MIMEMessage, (Message(),)), + (MIMENonMultipart, ('multipart', 'mixed')), + (MIMEText, ('',)), + ] + for cls, constructor in classes: + with self.subTest(cls=cls.__name__, policy='compat32'): + m = cls(*constructor) + self.assertIs(m.policy, email.policy.compat32) + with self.subTest(cls=cls.__name__, policy='default'): + m = cls(*constructor, policy=email.policy.default) + self.assertIs(m.policy, email.policy.default) + # Test the iterator/generators class TestIterators(TestEmailBase): @@ -3448,7 +3489,6 @@ Do you like this message? class TestFeedParsers(TestEmailBase): def parse(self, chunks): - from email.feedparser import FeedParser feedparser = FeedParser() for chunk in chunks: feedparser.feed(chunk) diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index b1cbce26d5..7c8877fdcb 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -143,7 +143,7 @@ class TestGeneratorBase: def test_set_mangle_from_via_policy(self): source = textwrap.dedent("""\ Subject: test that - from is mangeld in the body! + from is mangled in the body! From time to time I write a rhyme. """) diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 55ecdea9aa..af836dc972 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1,7 +1,6 @@ import datetime import textwrap import unittest -import types from email import errors from email import policy from email.message import Message diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index 434516226c..f3a57df9e9 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -764,6 +764,26 @@ class TestEmailMessage(TestEmailMessageBase, TestEmailBase): m.set_content(content_manager=cm) self.assertEqual(m['MIME-Version'], '1.0') + def test_as_string_uses_max_header_length_by_default(self): + m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n') + self.assertEqual(len(m.as_string().strip().splitlines()), 3) + + def test_as_string_allows_maxheaderlen(self): + m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n') + self.assertEqual(len(m.as_string(maxheaderlen=0).strip().splitlines()), + 1) + self.assertEqual(len(m.as_string(maxheaderlen=34).strip().splitlines()), + 6) + + def test_str_defaults_to_policy_max_line_length(self): + m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n') + self.assertEqual(len(str(m).strip().splitlines()), 3) + + def test_str_defaults_to_utf8(self): + m = EmailMessage() + m['Subject'] = 'unicöde' + self.assertEqual(str(m), 'Subject: unicöde\n\n') + class TestMIMEPart(TestEmailMessageBase, TestEmailBase): # Doing the full test run here may seem a bit redundant, since the two diff --git a/Lib/test/test_email/test_parser.py b/Lib/test/test_email/test_parser.py index 8ddc176389..06c86408ab 100644 --- a/Lib/test/test_email/test_parser.py +++ b/Lib/test/test_email/test_parser.py @@ -1,7 +1,7 @@ import io import email import unittest -from email.message import Message +from email.message import Message, EmailMessage from email.policy import default from test.test_email import TestEmailBase @@ -39,38 +39,71 @@ class TestParserBase: # The unicode line splitter splits on unicode linebreaks, which are # more numerous than allowed by the email RFCs; make sure we are only # splitting on those two. - msg = self.parser( - "Next-Line: not\x85broken\r\n" - "Null: not\x00broken\r\n" - "Vertical-Tab: not\vbroken\r\n" - "Form-Feed: not\fbroken\r\n" - "File-Separator: not\x1Cbroken\r\n" - "Group-Separator: not\x1Dbroken\r\n" - "Record-Separator: not\x1Ebroken\r\n" - "Line-Separator: not\u2028broken\r\n" - "Paragraph-Separator: not\u2029broken\r\n" - "\r\n", - policy=default, - ) - self.assertEqual(msg.items(), [ - ("Next-Line", "not\x85broken"), - ("Null", "not\x00broken"), - ("Vertical-Tab", "not\vbroken"), - ("Form-Feed", "not\fbroken"), - ("File-Separator", "not\x1Cbroken"), - ("Group-Separator", "not\x1Dbroken"), - ("Record-Separator", "not\x1Ebroken"), - ("Line-Separator", "not\u2028broken"), - ("Paragraph-Separator", "not\u2029broken"), - ]) - self.assertEqual(msg.get_payload(), "") + for parser in self.parsers: + with self.subTest(parser=parser.__name__): + msg = parser( + "Next-Line: not\x85broken\r\n" + "Null: not\x00broken\r\n" + "Vertical-Tab: not\vbroken\r\n" + "Form-Feed: not\fbroken\r\n" + "File-Separator: not\x1Cbroken\r\n" + "Group-Separator: not\x1Dbroken\r\n" + "Record-Separator: not\x1Ebroken\r\n" + "Line-Separator: not\u2028broken\r\n" + "Paragraph-Separator: not\u2029broken\r\n" + "\r\n", + policy=default, + ) + self.assertEqual(msg.items(), [ + ("Next-Line", "not\x85broken"), + ("Null", "not\x00broken"), + ("Vertical-Tab", "not\vbroken"), + ("Form-Feed", "not\fbroken"), + ("File-Separator", "not\x1Cbroken"), + ("Group-Separator", "not\x1Dbroken"), + ("Record-Separator", "not\x1Ebroken"), + ("Line-Separator", "not\u2028broken"), + ("Paragraph-Separator", "not\u2029broken"), + ]) + self.assertEqual(msg.get_payload(), "") + + class MyMessage(EmailMessage): + pass + + def test_custom_message_factory_on_policy(self): + for parser in self.parsers: + with self.subTest(parser=parser.__name__): + MyPolicy = default.clone(message_factory=self.MyMessage) + msg = parser("To: foo\n\ntest", policy=MyPolicy) + self.assertIsInstance(msg, self.MyMessage) + + def test_factory_arg_overrides_policy(self): + for parser in self.parsers: + with self.subTest(parser=parser.__name__): + MyPolicy = default.clone(message_factory=self.MyMessage) + msg = parser("To: foo\n\ntest", Message, policy=MyPolicy) + self.assertNotIsInstance(msg, self.MyMessage) + self.assertIsInstance(msg, Message) + +# Play some games to get nice output in subTest. This code could be clearer +# if staticmethod supported __name__. + +def message_from_file(s, *args, **kw): + f = io.StringIO(s) + return email.message_from_file(f, *args, **kw) class TestParser(TestParserBase, TestEmailBase): - parser = staticmethod(email.message_from_string) + parsers = (email.message_from_string, message_from_file) + +def message_from_bytes(s, *args, **kw): + return email.message_from_bytes(s.encode(), *args, **kw) + +def message_from_binary_file(s, *args, **kw): + f = io.BytesIO(s.encode()) + return email.message_from_binary_file(f, *args, **kw) class TestBytesParser(TestParserBase, TestEmailBase): - def parser(self, s, *args, **kw): - return email.message_from_bytes(s.encode(), *args, **kw) + parsers = (message_from_bytes, message_from_binary_file) if __name__ == '__main__': diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py index 70ac4db8b0..8fecb8a5fc 100644 --- a/Lib/test/test_email/test_policy.py +++ b/Lib/test/test_email/test_policy.py @@ -5,6 +5,7 @@ import unittest import email.policy import email.parser import email.generator +import email.message from email import headerregistry def make_defaults(base_defaults, differences): @@ -23,6 +24,7 @@ class PolicyAPITests(unittest.TestCase): 'cte_type': '8bit', 'raise_on_defect': False, 'mangle_from_': True, + 'message_factory': None, } # These default values are the ones set on email.policy.default. # If any of these defaults change, the docs must be updated. @@ -34,6 +36,7 @@ class PolicyAPITests(unittest.TestCase): 'refold_source': 'long', 'content_manager': email.policy.EmailPolicy.content_manager, 'mangle_from_': False, + 'message_factory': email.message.EmailMessage, }) # For each policy under test, we give here what we expect the defaults to @@ -62,20 +65,22 @@ class PolicyAPITests(unittest.TestCase): def test_defaults(self): for policy, expected in self.policies.items(): for attr, value in expected.items(): - self.assertEqual(getattr(policy, attr), value, - ("change {} docs/docstrings if defaults have " - "changed").format(policy)) + with self.subTest(policy=policy, attr=attr): + self.assertEqual(getattr(policy, attr), value, + ("change {} docs/docstrings if defaults have " + "changed").format(policy)) def test_all_attributes_covered(self): for policy, expected in self.policies.items(): for attr in dir(policy): - if (attr.startswith('_') or - isinstance(getattr(email.policy.EmailPolicy, attr), - types.FunctionType)): - continue - else: - self.assertIn(attr, expected, - "{} is not fully tested".format(attr)) + with self.subTest(policy=policy, attr=attr): + if (attr.startswith('_') or + isinstance(getattr(email.policy.EmailPolicy, attr), + types.FunctionType)): + continue + else: + self.assertIn(attr, expected, + "{} is not fully tested".format(attr)) def test_abc(self): with self.assertRaises(TypeError) as cm: @@ -237,6 +242,9 @@ class PolicyAPITests(unittest.TestCase): # wins), but that the order still works (right overrides left). +class TestException(Exception): + pass + class TestPolicyPropagation(unittest.TestCase): # The abstract methods are used by the parser but not by the wrapper @@ -244,40 +252,40 @@ class TestPolicyPropagation(unittest.TestCase): # policy was actually propagated all the way to feedparser. class MyPolicy(email.policy.Policy): def badmethod(self, *args, **kw): - raise Exception("test") + raise TestException("test") fold = fold_binary = header_fetch_parser = badmethod header_source_parse = header_store_parse = badmethod def test_message_from_string(self): - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): email.message_from_string("Subject: test\n\n", policy=self.MyPolicy) def test_message_from_bytes(self): - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): email.message_from_bytes(b"Subject: test\n\n", policy=self.MyPolicy) def test_message_from_file(self): f = io.StringIO('Subject: test\n\n') - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): email.message_from_file(f, policy=self.MyPolicy) def test_message_from_binary_file(self): f = io.BytesIO(b'Subject: test\n\n') - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): email.message_from_binary_file(f, policy=self.MyPolicy) # These are redundant, but we need them for black-box completeness. def test_parser(self): p = email.parser.Parser(policy=self.MyPolicy) - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): p.parsestr('Subject: test\n\n') def test_bytes_parser(self): p = email.parser.BytesParser(policy=self.MyPolicy) - with self.assertRaisesRegex(Exception, "^test$"): + with self.assertRaisesRegex(TestException, "^test$"): p.parsebytes(b'Subject: test\n\n') # Now that we've established that all the parse methods get the |