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
=== modified file 'bzrlib/email_message.py'
--- bzrlib/email_message.py 2011-12-19 13:23:58 +0000
+++ bzrlib/email_message.py 2014-04-09 08:25:34 +0000
@@ -149,7 +149,7 @@
149149
150 @staticmethod150 @staticmethod
151 def send(config, from_address, to_address, subject, body, attachment=None,151 def send(config, from_address, to_address, subject, body, attachment=None,
152 attachment_filename=None, attachment_mime_subtype='plain'):152 attachment_filename=None, attachment_mime_subtype='plain'):
153 """Create an email message and send it with SMTPConnection.153 """Create an email message and send it with SMTPConnection.
154154
155 :param config: config object to pass to SMTPConnection constructor.155 :param config: config object to pass to SMTPConnection constructor.
156156
=== modified file 'bzrlib/tests/test_email_message.py'
--- bzrlib/tests/test_email_message.py 2011-12-16 19:18:39 +0000
+++ bzrlib/tests/test_email_message.py 2014-04-09 08:25:34 +0000
@@ -14,13 +14,14 @@
14# along with this program; if not, write to the Free Software14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1616
17import sys
17from email.Header import decode_header18from email.Header import decode_header
1819
19from bzrlib import __version__ as _bzrlib_version20from bzrlib import __version__ as _bzrlib_version
20from bzrlib.email_message import EmailMessage21from bzrlib.email_message import EmailMessage
21from bzrlib.errors import BzrBadParameterNotUnicode22from bzrlib.errors import BzrBadParameterNotUnicode
22from bzrlib.smtp_connection import SMTPConnection23from bzrlib.smtp_connection import SMTPConnection
23from bzrlib.tests import TestCase24from bzrlib import tests
2425
25EMPTY_MESSAGE = '''\26EMPTY_MESSAGE = '''\
26From: from@from.com27From: from@from.com
@@ -65,9 +66,22 @@
65body66body
66''' % { 'version': _bzrlib_version, 'boundary': BOUNDARY }67''' % { 'version': _bzrlib_version, 'boundary': BOUNDARY }
6768
68SIMPLE_MULTIPART_MESSAGE = _MULTIPART_HEAD + '--%s--' % BOUNDARY69
6970def final_newline_or_not(msg):
70COMPLEX_MULTIPART_MESSAGE = _MULTIPART_HEAD + '''\71 if sys.version_info >= (2, 7, 6):
72 # Some internals of python's email module changed in an (minor)
73 # incompatible way: a final newline is appended in 2.7.6...
74 msg += '\n'
75 return msg
76
77
78def simple_multipart_message():
79 msg = _MULTIPART_HEAD + '--%s--' % BOUNDARY
80 return final_newline_or_not(msg)
81
82
83def complex_multipart_message(typ):
84 msg = _MULTIPART_HEAD + '''\
71--%(boundary)s85--%(boundary)s
72MIME-Version: 1.086MIME-Version: 1.0
73Content-Type: text/%%s; charset="us-ascii"; name="lines.txt"87Content-Type: text/%%s; charset="us-ascii"; name="lines.txt"
@@ -81,9 +95,11 @@
81e95e
8296
83--%(boundary)s--''' % { 'boundary': BOUNDARY }97--%(boundary)s--''' % { 'boundary': BOUNDARY }
8498 msg = final_newline_or_not(msg)
8599 return msg % (typ,)
86class TestEmailMessage(TestCase):100
101
102class TestEmailMessage(tests.TestCase):
87103
88 def test_empty_message(self):104 def test_empty_message(self):
89 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')105 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
@@ -100,15 +116,18 @@
100 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', body)116 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', body)
101 self.assertEqualDiff(expected, msg.as_string())117 self.assertEqualDiff(expected, msg.as_string())
102118
103 def test_multipart_message(self):119 def test_multipart_message_simple(self):
104 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')120 msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
105 msg.add_inline_attachment('body')121 msg.add_inline_attachment('body')
106 self.assertEqualDiff(SIMPLE_MULTIPART_MESSAGE, msg.as_string(BOUNDARY))122 self.assertEqualDiff(simple_multipart_message(),
107123 msg.as_string(BOUNDARY))
124
125
126 def test_multipart_message_complex(self):
108 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', 'body')127 msg = EmailMessage('from@from.com', 'to@to.com', 'subject', 'body')
109 msg.add_inline_attachment(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-subtype')128 msg.add_inline_attachment(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-subtype')
110 self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'x-subtype',129 self.assertEqualDiff(complex_multipart_message('x-subtype'),
111 msg.as_string(BOUNDARY))130 msg.as_string(BOUNDARY))
112131
113 def test_headers_accept_unicode_and_utf8(self):132 def test_headers_accept_unicode_and_utf8(self):
114 for user in [ u'Pepe P\xe9rez <pperez@ejemplo.com>',133 for user in [ u'Pepe P\xe9rez <pperez@ejemplo.com>',
@@ -148,40 +167,6 @@
148 self.assertEqual('to2@to.com', msg['To'])167 self.assertEqual('to2@to.com', msg['To'])
149 self.assertEqual('cc@cc.com', msg['Cc'])168 self.assertEqual('cc@cc.com', msg['Cc'])
150169
151 def test_send(self):
152 class FakeConfig:
153 def get(self, option):
154 return None
155
156 messages = []
157
158 def send_as_append(_self, msg):
159 messages.append(msg.as_string(BOUNDARY))
160
161 old_send_email = SMTPConnection.send_email
162 try:
163 SMTPConnection.send_email = send_as_append
164
165 EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
166 'subject', 'body', u'a\nb\nc\nd\ne\n', 'lines.txt')
167 self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'plain',
168 messages[0])
169 messages[:] = []
170
171 EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
172 'subject', 'body', u'a\nb\nc\nd\ne\n', 'lines.txt',
173 'x-patch')
174 self.assertEqualDiff(COMPLEX_MULTIPART_MESSAGE % 'x-patch',
175 messages[0])
176 messages[:] = []
177
178 EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
179 'subject', 'body')
180 self.assertEqualDiff(SIMPLE_MESSAGE_ASCII , messages[0])
181 messages[:] = []
182 finally:
183 SMTPConnection.send_email = old_send_email
184
185 def test_address_to_encoded_header(self):170 def test_address_to_encoded_header(self):
186 def decode(s):171 def decode(s):
187 """Convert a RFC2047-encoded string to a unicode string."""172 """Convert a RFC2047-encoded string to a unicode string."""
@@ -224,3 +209,46 @@
224 }209 }
225 for string_, pair in pairs.items():210 for string_, pair in pairs.items():
226 self.assertEqual(pair, EmailMessage.string_with_encoding(string_))211 self.assertEqual(pair, EmailMessage.string_with_encoding(string_))
212
213
214class TestSend(tests.TestCase):
215
216 def setUp(self):
217 super(TestSend, self).setUp()
218 self.messages = []
219
220 def send_as_append(_self, msg):
221 self.messages.append(msg.as_string(BOUNDARY))
222
223 self.overrideAttr(SMTPConnection, 'send_email', send_as_append)
224
225
226
227 def send_email(self, attachment=None, attachment_filename=None,
228 attachment_mime_subtype='plain'):
229 class FakeConfig:
230 def get(self, option):
231 return None
232
233 EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
234 'subject', 'body',
235 attachment=attachment,
236 attachment_filename=attachment_filename,
237 attachment_mime_subtype=attachment_mime_subtype)
238
239 def assertMessage(self, expected):
240 self.assertLength(1, self.messages)
241 self.assertEqualDiff(expected, self.messages[0])
242
243 def test_send_plain(self):
244 self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt')
245 self.assertMessage(complex_multipart_message('plain'))
246
247 def test_send_patch(self):
248 self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-patch')
249 self.assertMessage(complex_multipart_message('x-patch'))
250
251 def test_send_simple(self):
252 self.send_email()
253 self.assertMessage(SIMPLE_MESSAGE_ASCII)
254
227255
=== modified file 'bzrlib/tests/test_osutils.py'
--- bzrlib/tests/test_osutils.py 2013-06-24 12:03:12 +0000
+++ bzrlib/tests/test_osutils.py 2014-04-09 08:25:34 +0000
@@ -943,9 +943,15 @@
943 osutils._win32_pathjoin('path/to', 'C:/foo'))943 osutils._win32_pathjoin('path/to', 'C:/foo'))
944 self.assertEqual('path/to/foo',944 self.assertEqual('path/to/foo',
945 osutils._win32_pathjoin('path/to/', 'foo'))945 osutils._win32_pathjoin('path/to/', 'foo'))
946 self.assertEqual('/foo',946
947 def test_pathjoin_late_bugfix(self):
948 if sys.version_info < (2, 7, 6):
949 expected = '/foo'
950 else:
951 expected = 'C:/foo'
952 self.assertEqual(expected,
947 osutils._win32_pathjoin('C:/path/to/', '/foo'))953 osutils._win32_pathjoin('C:/path/to/', '/foo'))
948 self.assertEqual('/foo',954 self.assertEqual(expected,
949 osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))955 osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
950956
951 def test_normpath(self):957 def test_normpath(self):
952958
=== modified file 'doc/en/release-notes/bzr-2.7.txt'
--- doc/en/release-notes/bzr-2.7.txt 2014-04-02 16:15:32 +0000
+++ doc/en/release-notes/bzr-2.7.txt 2014-04-09 08:25:34 +0000
@@ -63,6 +63,12 @@
63 suite. This can include new facilities for writing tests, fixes to 63 suite. This can include new facilities for writing tests, fixes to
64 spurious test failures and changes to the way things should be tested.64 spurious test failures and changes to the way things should be tested.
6565
66* Handle (minor) incompatible change in python 2.7.6 leading to test
67 failures. Only tests are affected. (Vincent Ladeuil, #1303879)
68
69* Take python 2.7.6 late (better than never) bugfix in ntpath.py into
70 account. Only tests are affected (Vincent Ladeuil, #1303879).
71
66* Remove wrong assumption about how TCP server and client interact when run72* Remove wrong assumption about how TCP server and client interact when run
67 inside the same process. (Vincent Ladeuil, #1269886).73 inside the same process. (Vincent Ladeuil, #1269886).
6874