Merge lp:~vila/bzr/1303879-py27-issues into lp:bzr

Proposed by Vincent Ladeuil on 2014-04-09
Status: Merged
Approved by: Vincent Ladeuil on 2014-04-09
Approved revision: 6594
Merged at revision: 6593
Proposed branch: lp:~vila/bzr/1303879-py27-issues
Merge into: lp:bzr
Diff against target: 223 lines (+89/-49)
4 files modified
bzrlib/email_message.py (+1/-1)
bzrlib/tests/test_email_message.py (+74/-46)
bzrlib/tests/test_osutils.py (+8/-2)
doc/en/release-notes/bzr-2.7.txt (+6/-0)
To merge this branch: bzr merge lp:~vila/bzr/1303879-py27-issues
Reviewer Review Type Date Requested Status
Andrew Starr-Bochicchio 2014-04-09 Approve on 2014-04-09
bzr-core 2014-04-09 Pending
Review via email: mp+214896@code.launchpad.net

Commit message

Fix python-2.7.6 test failures.

Description of the change

python 2.7.6 introduced a minor incompatible change in the email module. Some tests were relying on as_string() to get a representation of the email message. A final new line is now appended there...

A bug has also been fixed in python 2.7.6 ntpath.py module and some of our tests runs on all platforms and needed to be fixed.

None of those changes affect bzr itself, only its tests.

This has been tested on trusty and saucy to make sure the tests pass for all python versions.

To post a comment you must log in.

Thanks for running this down. It looks good to me. I ran the test suite on Debian sid for good measure as it had been failing there as well. All tests were successful.

review: Approve
Vincent Ladeuil (vila) wrote :

> Thanks for running this down. It looks good to me.

> I ran the test suite on
> Debian sid for good measure

Thanks !

> as it had been failing there as well.

2.7.6 there too according to rmadison, so expected.

> All tests
> were successful.

Great.

Vincent Ladeuil (vila) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/email_message.py'
2--- bzrlib/email_message.py 2011-12-19 13:23:58 +0000
3+++ bzrlib/email_message.py 2014-04-09 08:25:34 +0000
4@@ -149,7 +149,7 @@
5
6 @staticmethod
7 def send(config, from_address, to_address, subject, body, attachment=None,
8- attachment_filename=None, attachment_mime_subtype='plain'):
9+ attachment_filename=None, attachment_mime_subtype='plain'):
10 """Create an email message and send it with SMTPConnection.
11
12 :param config: config object to pass to SMTPConnection constructor.
13
14=== modified file 'bzrlib/tests/test_email_message.py'
15--- bzrlib/tests/test_email_message.py 2011-12-16 19:18:39 +0000
16+++ bzrlib/tests/test_email_message.py 2014-04-09 08:25:34 +0000
17@@ -14,13 +14,14 @@
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21+import sys
22 from email.Header import decode_header
23
24 from bzrlib import __version__ as _bzrlib_version
25 from bzrlib.email_message import EmailMessage
26 from bzrlib.errors import BzrBadParameterNotUnicode
27 from bzrlib.smtp_connection import SMTPConnection
28-from bzrlib.tests import TestCase
29+from bzrlib import tests
30
31 EMPTY_MESSAGE = '''\
32 From: from@from.com
33@@ -65,9 +66,22 @@
34 body
35 ''' % { 'version': _bzrlib_version, 'boundary': BOUNDARY }
36
37-SIMPLE_MULTIPART_MESSAGE = _MULTIPART_HEAD + '--%s--' % BOUNDARY
38-
39-COMPLEX_MULTIPART_MESSAGE = _MULTIPART_HEAD + '''\
40+
41+def final_newline_or_not(msg):
42+ if sys.version_info >= (2, 7, 6):
43+ # Some internals of python's email module changed in an (minor)
44+ # incompatible way: a final newline is appended in 2.7.6...
45+ msg += '\n'
46+ return msg
47+
48+
49+def simple_multipart_message():
50+ msg = _MULTIPART_HEAD + '--%s--' % BOUNDARY
51+ return final_newline_or_not(msg)
52+
53+
54+def complex_multipart_message(typ):
55+ msg = _MULTIPART_HEAD + '''\
56 --%(boundary)s
57 MIME-Version: 1.0
58 Content-Type: text/%%s; charset="us-ascii"; name="lines.txt"
59@@ -81,9 +95,11 @@
60 e
61
62 --%(boundary)s--''' % { 'boundary': BOUNDARY }
63-
64-
65-class TestEmailMessage(TestCase):
66+ msg = final_newline_or_not(msg)
67+ return msg % (typ,)
68+
69+
70+class TestEmailMessage(tests.TestCase):
71
72 def test_empty_message(self):
73 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
74@@ -100,15 +116,18 @@
75 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', body)
76 self.assertEqualDiff(expected, msg.as_string())
77
78- def test_multipart_message(self):
79+ def test_multipart_message_simple(self):
80 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
81 msg.add_inline_attachment('body')
82- self.assertEqualDiff(SIMPLE_MULTIPART_MESSAGE, msg.as_string(BOUNDARY))
83-
84+ self.assertEqualDiff(simple_multipart_message(),
85+ msg.as_string(BOUNDARY))
86+
87+
88+ def test_multipart_message_complex(self):
89 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', 'body')
90 msg.add_inline_attachment(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-subtype')
91- self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'x-subtype',
92- msg.as_string(BOUNDARY))
93+ self.assertEqualDiff(complex_multipart_message('x-subtype'),
94+ msg.as_string(BOUNDARY))
95
96 def test_headers_accept_unicode_and_utf8(self):
97 for user in [ u'Pepe P\xe9rez <pperez@ejemplo.com>',
98@@ -148,40 +167,6 @@
99 self.assertEqual('to2@to.com', msg['To'])
100 self.assertEqual('cc@cc.com', msg['Cc'])
101
102- def test_send(self):
103- class FakeConfig:
104- def get(self, option):
105- return None
106-
107- messages = []
108-
109- def send_as_append(_self, msg):
110- messages.append(msg.as_string(BOUNDARY))
111-
112- old_send_email = SMTPConnection.send_email
113- try:
114- SMTPConnection.send_email = send_as_append
115-
116- EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
117- 'subject', 'body', u'a\nb\nc\nd\ne\n', 'lines.txt')
118- self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'plain',
119- messages[0])
120- messages[:] = []
121-
122- EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
123- 'subject', 'body', u'a\nb\nc\nd\ne\n', 'lines.txt',
124- 'x-patch')
125- self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'x-patch',
126- messages[0])
127- messages[:] = []
128-
129- EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
130- 'subject', 'body')
131- self.assertEqualDiff(SIMPLE_MESSAGE_ASCII , messages[0])
132- messages[:] = []
133- finally:
134- SMTPConnection.send_email = old_send_email
135-
136 def test_address_to_encoded_header(self):
137 def decode(s):
138 """Convert a RFC2047-encoded string to a unicode string."""
139@@ -224,3 +209,46 @@
140 }
141 for string_, pair in pairs.items():
142 self.assertEqual(pair, EmailMessage.string_with_encoding(string_))
143+
144+
145+class TestSend(tests.TestCase):
146+
147+ def setUp(self):
148+ super(TestSend, self).setUp()
149+ self.messages = []
150+
151+ def send_as_append(_self, msg):
152+ self.messages.append(msg.as_string(BOUNDARY))
153+
154+ self.overrideAttr(SMTPConnection, 'send_email', send_as_append)
155+
156+
157+
158+ def send_email(self, attachment=None, attachment_filename=None,
159+ attachment_mime_subtype='plain'):
160+ class FakeConfig:
161+ def get(self, option):
162+ return None
163+
164+ EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
165+ 'subject', 'body',
166+ attachment=attachment,
167+ attachment_filename=attachment_filename,
168+ attachment_mime_subtype=attachment_mime_subtype)
169+
170+ def assertMessage(self, expected):
171+ self.assertLength(1, self.messages)
172+ self.assertEqualDiff(expected, self.messages[0])
173+
174+ def test_send_plain(self):
175+ self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt')
176+ self.assertMessage(complex_multipart_message('plain'))
177+
178+ def test_send_patch(self):
179+ self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-patch')
180+ self.assertMessage(complex_multipart_message('x-patch'))
181+
182+ def test_send_simple(self):
183+ self.send_email()
184+ self.assertMessage(SIMPLE_MESSAGE_ASCII)
185+
186
187=== modified file 'bzrlib/tests/test_osutils.py'
188--- bzrlib/tests/test_osutils.py 2013-06-24 12:03:12 +0000
189+++ bzrlib/tests/test_osutils.py 2014-04-09 08:25:34 +0000
190@@ -943,9 +943,15 @@
191 osutils._win32_pathjoin('path/to', 'C:/foo'))
192 self.assertEqual('path/to/foo',
193 osutils._win32_pathjoin('path/to/', 'foo'))
194- self.assertEqual('/foo',
195+
196+ def test_pathjoin_late_bugfix(self):
197+ if sys.version_info < (2, 7, 6):
198+ expected = '/foo'
199+ else:
200+ expected = 'C:/foo'
201+ self.assertEqual(expected,
202 osutils._win32_pathjoin('C:/path/to/', '/foo'))
203- self.assertEqual('/foo',
204+ self.assertEqual(expected,
205 osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
206
207 def test_normpath(self):
208
209=== modified file 'doc/en/release-notes/bzr-2.7.txt'
210--- doc/en/release-notes/bzr-2.7.txt 2014-04-02 16:15:32 +0000
211+++ doc/en/release-notes/bzr-2.7.txt 2014-04-09 08:25:34 +0000
212@@ -63,6 +63,12 @@
213 suite. This can include new facilities for writing tests, fixes to
214 spurious test failures and changes to the way things should be tested.
215
216+* Handle (minor) incompatible change in python 2.7.6 leading to test
217+ failures. Only tests are affected. (Vincent Ladeuil, #1303879)
218+
219+* Take python 2.7.6 late (better than never) bugfix in ntpath.py into
220+ account. Only tests are affected (Vincent Ladeuil, #1303879).
221+
222 * Remove wrong assumption about how TCP server and client interact when run
223 inside the same process. (Vincent Ladeuil, #1269886).
224