Merge ~cjwatson/launchpad:py3only-version-detection into launchpad:master
- Git
- lp:~cjwatson/launchpad
- py3only-version-detection
- Merge into master
Proposed by
Colin Watson
Status: | Merged |
---|---|
Approved by: | Colin Watson |
Approved revision: | f20f13a3d5fa1ee1104b1ae141f33747b302f3f2 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~cjwatson/launchpad:py3only-version-detection |
Merge into: | launchpad:master |
Diff against target: |
983 lines (+83/-258) 36 files modified
lib/lp/app/security.py (+0/-4) lib/lp/bugs/externalbugtracker/bugzilla.py (+1/-3) lib/lp/bugs/mail/handler.py (+0/-7) lib/lp/bugs/scripts/bugexport.py (+2/-8) lib/lp/bugs/scripts/tests/test_bugsummaryrebuild.py (+1/-5) lib/lp/code/browser/tests/test_branchmergeproposal.py (+14/-21) lib/lp/registry/browser/person.py (+0/-3) lib/lp/registry/interfaces/sourcepackagename.py (+0/-5) lib/lp/registry/model/productrelease.py (+1/-5) lib/lp/registry/tests/test_nickname.py (+3/-14) lib/lp/registry/tests/test_ssh.py (+1/-7) lib/lp/scripts/utilities/importpedant.py (+1/-3) lib/lp/scripts/utilities/test.py (+1/-1) lib/lp/services/compat.py (+10/-16) lib/lp/services/encoding.py (+1/-1) lib/lp/services/limitedlist.py (+0/-11) lib/lp/services/mail/interfaces.py (+0/-4) lib/lp/services/mail/notificationrecipientset.py (+0/-3) lib/lp/services/scripts/base.py (+1/-5) lib/lp/services/tests/test_encoding.py (+2/-12) lib/lp/services/twistedsupport/tests/test_xmlrpc.py (+0/-10) lib/lp/services/twistedsupport/xmlrpc.py (+1/-6) lib/lp/services/webapp/pgsession.py (+21/-24) lib/lp/services/webapp/publisher.py (+0/-5) lib/lp/services/webapp/servers.py (+3/-17) lib/lp/services/webapp/tests/test_servers.py (+6/-10) lib/lp/services/webapp/url.py (+1/-4) lib/lp/services/webhooks/payload.py (+0/-6) lib/lp/soyuz/adapters/archivesourcepublication.py (+0/-4) lib/lp/soyuz/interfaces/binarypackagename.py (+0/-5) lib/lp/testing/factory.py (+2/-6) lib/lp/testing/systemdocs.py (+4/-7) lib/lp/translations/doc/poexport-queue.txt (+5/-7) lib/lp/translations/model/translatedlanguage.py (+0/-4) lib/sqlobject/__init__.py (+0/-2) scripts/process-one-mail.py (+1/-3) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cristian Gonzalez (community) | Approve | ||
Review via email: mp+406806@code.launchpad.net |
Commit message
Remove simple cases of Python 2 version detection
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/app/security.py b/lib/lp/app/security.py |
2 | index 6fae684..08fe1e5 100644 |
3 | --- a/lib/lp/app/security.py |
4 | +++ b/lib/lp/app/security.py |
5 | @@ -13,7 +13,6 @@ __all__ = [ |
6 | |
7 | from itertools import repeat |
8 | |
9 | -import six |
10 | from six.moves import zip as izip |
11 | from zope.component import queryAdapter |
12 | from zope.interface import implementer |
13 | @@ -128,9 +127,6 @@ class non_boolean_izip(izip): |
14 | "DelegatedAuthorization results can't be used in boolean " |
15 | "expressions.") |
16 | |
17 | - if six.PY2: |
18 | - __nonzero__ = __bool__ |
19 | - |
20 | |
21 | class DelegatedAuthorization(AuthorizationBase): |
22 | |
23 | diff --git a/lib/lp/bugs/externalbugtracker/bugzilla.py b/lib/lp/bugs/externalbugtracker/bugzilla.py |
24 | index 830f680..2f941e8 100644 |
25 | --- a/lib/lp/bugs/externalbugtracker/bugzilla.py |
26 | +++ b/lib/lp/bugs/externalbugtracker/bugzilla.py |
27 | @@ -13,7 +13,6 @@ __all__ = [ |
28 | |
29 | from email.utils import parseaddr |
30 | import re |
31 | -import string |
32 | import xml.parsers.expat |
33 | |
34 | from defusedxml import minidom |
35 | @@ -190,8 +189,7 @@ class Bugzilla(ExternalBugTracker): |
36 | bad_chars = b''.join(six.int2byte(i) for i in range(0, 32)) |
37 | for char in b'\n', b'\r', b'\t': |
38 | bad_chars = bad_chars.replace(char, b'') |
39 | - maketrans = bytes.maketrans if six.PY3 else string.maketrans |
40 | - trans_map = maketrans(bad_chars, b' ' * len(bad_chars)) |
41 | + trans_map = bytes.maketrans(bad_chars, b' ' * len(bad_chars)) |
42 | contents = contents.translate(trans_map) |
43 | # Don't use forbid_dtd=True here; Bugzilla XML responses seem to |
44 | # include DOCTYPE declarations. |
45 | diff --git a/lib/lp/bugs/mail/handler.py b/lib/lp/bugs/mail/handler.py |
46 | index 3a151e2..fdf9a31 100644 |
47 | --- a/lib/lp/bugs/mail/handler.py |
48 | +++ b/lib/lp/bugs/mail/handler.py |
49 | @@ -13,7 +13,6 @@ import os |
50 | |
51 | from lazr.lifecycle.event import ObjectCreatedEvent |
52 | from lazr.lifecycle.interfaces import IObjectCreatedEvent |
53 | -import six |
54 | import transaction |
55 | from zope.component import getUtility |
56 | from zope.event import notify |
57 | @@ -69,9 +68,6 @@ class BugTaskCommandGroup: |
58 | def __bool__(self): |
59 | return len(self._commands) > 0 |
60 | |
61 | - if six.PY2: |
62 | - __nonzero__ = __bool__ |
63 | - |
64 | def __str__(self): |
65 | text_commands = [str(cmd) for cmd in self.commands] |
66 | return '\n'.join(text_commands).strip() |
67 | @@ -98,9 +94,6 @@ class BugCommandGroup(BugTaskCommandGroup): |
68 | else: |
69 | return super(BugCommandGroup, self).__bool__() |
70 | |
71 | - if six.PY2: |
72 | - __nonzero__ = __bool__ |
73 | - |
74 | def __str__(self): |
75 | text_commands = [super(BugCommandGroup, self).__str__()] |
76 | for group in self.groups: |
77 | diff --git a/lib/lp/bugs/scripts/bugexport.py b/lib/lp/bugs/scripts/bugexport.py |
78 | index 70e340c..b607f40 100644 |
79 | --- a/lib/lp/bugs/scripts/bugexport.py |
80 | +++ b/lib/lp/bugs/scripts/bugexport.py |
81 | @@ -8,7 +8,6 @@ __all__ = [ |
82 | ] |
83 | |
84 | import base64 |
85 | -import sys |
86 | |
87 | |
88 | try: |
89 | @@ -28,12 +27,6 @@ from lp.services.librarian.browser import ProxiedLibraryFileAlias |
90 | BUGS_XMLNS = 'https://launchpad.net/xmlns/2006/bugs' |
91 | |
92 | |
93 | -if sys.version_info[0] >= 3: |
94 | - encodebytes = base64.encodebytes |
95 | -else: |
96 | - encodebytes = base64.encodestring |
97 | - |
98 | - |
99 | def addnode(parent, elementname, content, **attrs): |
100 | node = ET.SubElement(parent, elementname, attrs) |
101 | node.text = content |
102 | @@ -104,7 +97,8 @@ def serialise_bugtask(bugtask): |
103 | attachment.libraryfile.mimetype) |
104 | # Attach the attachment file contents, base 64 encoded. |
105 | addnode(attachment_node, 'contents', |
106 | - encodebytes(attachment.libraryfile.read()).decode('ASCII')) |
107 | + base64.encodebytes( |
108 | + attachment.libraryfile.read()).decode('ASCII')) |
109 | |
110 | return bug_node |
111 | |
112 | diff --git a/lib/lp/bugs/scripts/tests/test_bugsummaryrebuild.py b/lib/lp/bugs/scripts/tests/test_bugsummaryrebuild.py |
113 | index 70ae789..f7530e2 100644 |
114 | --- a/lib/lp/bugs/scripts/tests/test_bugsummaryrebuild.py |
115 | +++ b/lib/lp/bugs/scripts/tests/test_bugsummaryrebuild.py |
116 | @@ -3,8 +3,6 @@ |
117 | |
118 | __metaclass__ = type |
119 | |
120 | -import sys |
121 | - |
122 | from testtools.content import text_content |
123 | from testtools.matchers import MatchesRegex |
124 | import transaction |
125 | @@ -153,12 +151,10 @@ class TestBugSummaryRebuild(TestCaseWithFactory): |
126 | rebuild_bugsummary_for_target(product, log) |
127 | self.assertEqual(1, get_bugsummary_rows(product).count()) |
128 | self.assertEqual(0, get_bugsummaryjournal_rows(product).count()) |
129 | - long_type = int if sys.version_info[0] >= 3 else long |
130 | self.assertThat( |
131 | log.getLogBufferAndClear(), |
132 | MatchesRegex( |
133 | - 'DEBUG Rebuilding %s\nDEBUG Added {.*: %r}' % |
134 | - (product.name, long_type(1)))) |
135 | + 'DEBUG Rebuilding %s\nDEBUG Added {.*: 1}' % product.name)) |
136 | |
137 | def test_script(self): |
138 | product = self.factory.makeProduct() |
139 | diff --git a/lib/lp/code/browser/tests/test_branchmergeproposal.py b/lib/lp/code/browser/tests/test_branchmergeproposal.py |
140 | index c4a776d..5f21254 100644 |
141 | --- a/lib/lp/code/browser/tests/test_branchmergeproposal.py |
142 | +++ b/lib/lp/code/browser/tests/test_branchmergeproposal.py |
143 | @@ -13,9 +13,11 @@ from datetime import ( |
144 | datetime, |
145 | timedelta, |
146 | ) |
147 | -from difflib import unified_diff |
148 | +from difflib import ( |
149 | + diff_bytes, |
150 | + unified_diff, |
151 | + ) |
152 | import doctest |
153 | -from functools import partial |
154 | import hashlib |
155 | import re |
156 | |
157 | @@ -144,14 +146,6 @@ from lp.testing.views import ( |
158 | ) |
159 | |
160 | |
161 | -if six.PY3: |
162 | - from difflib import diff_bytes |
163 | - |
164 | - unified_diff_bytes = partial(diff_bytes, unified_diff) |
165 | -else: |
166 | - unified_diff_bytes = unified_diff |
167 | - |
168 | - |
169 | class GitHostingClientMixin: |
170 | |
171 | def setUp(self): |
172 | @@ -1427,22 +1421,21 @@ class TestBranchMergeProposalView(TestCaseWithFactory): |
173 | def test_preview_diff_utf8(self): |
174 | """A preview_diff in utf-8 should be decoded as utf-8.""" |
175 | text = ''.join(six.unichr(x) for x in range(255)) |
176 | - diff_bytes = ''.join(unified_diff([''], [text])).encode('utf-8') |
177 | - self.setPreviewDiff(diff_bytes) |
178 | + diff = ''.join(unified_diff([''], [text])).encode('utf-8') |
179 | + self.setPreviewDiff(diff) |
180 | transaction.commit() |
181 | view = create_initialized_view(self.bmp, '+index') |
182 | - self.assertEqual(diff_bytes.decode('utf-8'), |
183 | - view.preview_diff_text) |
184 | + self.assertEqual(diff.decode('utf-8'), view.preview_diff_text) |
185 | self.assertTrue(view.diff_available) |
186 | |
187 | def test_preview_diff_all_chars(self): |
188 | """preview_diff should work on diffs containing all possible bytes.""" |
189 | text = b''.join(six.int2byte(x) for x in range(255)) |
190 | - diff_bytes = b''.join(unified_diff_bytes([b''], [text])) |
191 | - self.setPreviewDiff(diff_bytes) |
192 | + diff = b''.join(diff_bytes(unified_diff, [b''], [text])) |
193 | + self.setPreviewDiff(diff) |
194 | transaction.commit() |
195 | view = create_initialized_view(self.bmp, '+index') |
196 | - self.assertEqual(diff_bytes.decode('windows-1252', 'replace'), |
197 | + self.assertEqual(diff.decode('windows-1252', 'replace'), |
198 | view.preview_diff_text) |
199 | self.assertTrue(view.diff_available) |
200 | |
201 | @@ -1450,8 +1443,8 @@ class TestBranchMergeProposalView(TestCaseWithFactory): |
202 | # The preview_diff will recover from a timeout set to get the |
203 | # librarian content. |
204 | text = b''.join(six.int2byte(x) for x in range(255)) |
205 | - diff_bytes = b''.join(unified_diff_bytes([b''], [text])) |
206 | - preview_diff = self.setPreviewDiff(diff_bytes) |
207 | + diff = b''.join(diff_bytes(unified_diff, [b''], [text])) |
208 | + preview_diff = self.setPreviewDiff(diff) |
209 | transaction.commit() |
210 | |
211 | def fake_open(*args): |
212 | @@ -1470,8 +1463,8 @@ class TestBranchMergeProposalView(TestCaseWithFactory): |
213 | # librarian content. (This can happen e.g. on staging replicas of |
214 | # the production database.) |
215 | text = b''.join(six.int2byte(x) for x in range(255)) |
216 | - diff_bytes = b''.join(unified_diff_bytes([b''], [text])) |
217 | - preview_diff = self.setPreviewDiff(diff_bytes) |
218 | + diff = b''.join(diff_bytes(unified_diff, [b''], [text])) |
219 | + preview_diff = self.setPreviewDiff(diff) |
220 | transaction.commit() |
221 | |
222 | def fake_open(*args): |
223 | diff --git a/lib/lp/registry/browser/person.py b/lib/lp/registry/browser/person.py |
224 | index 28239d7..2cb78bc 100644 |
225 | --- a/lib/lp/registry/browser/person.py |
226 | +++ b/lib/lp/registry/browser/person.py |
227 | @@ -4296,9 +4296,6 @@ class ContactViaWebNotificationRecipientSet: |
228 | """See `INotificationRecipientSet`.""" |
229 | return len(self) > 0 |
230 | |
231 | - if six.PY2: |
232 | - __nonzero__ = __bool__ |
233 | - |
234 | def getReason(self, person_or_email): |
235 | """See `INotificationRecipientSet`.""" |
236 | if person_or_email not in self: |
237 | diff --git a/lib/lp/registry/interfaces/sourcepackagename.py b/lib/lp/registry/interfaces/sourcepackagename.py |
238 | index 89c0a8c..1d07542 100644 |
239 | --- a/lib/lp/registry/interfaces/sourcepackagename.py |
240 | +++ b/lib/lp/registry/interfaces/sourcepackagename.py |
241 | @@ -10,7 +10,6 @@ __all__ = [ |
242 | 'ISourcePackageNameSet', |
243 | ] |
244 | |
245 | -import six |
246 | from zope.interface import ( |
247 | Attribute, |
248 | Interface, |
249 | @@ -40,10 +39,6 @@ class ISourcePackageName(Interface): |
250 | def __str__(): |
251 | """Return the name""" |
252 | |
253 | - if six.PY2: |
254 | - def __unicode__(): |
255 | - """Return the name""" |
256 | - |
257 | |
258 | class ISourcePackageNameSet(Interface): |
259 | """A set of SourcePackageName.""" |
260 | diff --git a/lib/lp/registry/model/productrelease.py b/lib/lp/registry/model/productrelease.py |
261 | index 7ae8b4b..6dfc8b3 100644 |
262 | --- a/lib/lp/registry/model/productrelease.py |
263 | +++ b/lib/lp/registry/model/productrelease.py |
264 | @@ -14,7 +14,6 @@ from io import ( |
265 | BytesIO, |
266 | ) |
267 | import os |
268 | -import sys |
269 | |
270 | from sqlobject import ( |
271 | ForeignKey, |
272 | @@ -137,10 +136,7 @@ class ProductRelease(SQLBase): |
273 | file_size = len(file_or_data) |
274 | file_obj = BytesIO(file_or_data) |
275 | else: |
276 | - file_types = [BufferedIOBase] |
277 | - if sys.version_info[0] < 3: |
278 | - file_types.append(file) |
279 | - assert isinstance(file_or_data, tuple(file_types)), ( |
280 | + assert isinstance(file_or_data, BufferedIOBase), ( |
281 | "file_or_data is not an expected type") |
282 | file_obj = file_or_data |
283 | start = file_obj.tell() |
284 | diff --git a/lib/lp/registry/tests/test_nickname.py b/lib/lp/registry/tests/test_nickname.py |
285 | index dbe5c45..6ca86bb 100644 |
286 | --- a/lib/lp/registry/tests/test_nickname.py |
287 | +++ b/lib/lp/registry/tests/test_nickname.py |
288 | @@ -5,8 +5,6 @@ |
289 | |
290 | __metaclass__ = type |
291 | |
292 | -import sys |
293 | - |
294 | from zope.component import getUtility |
295 | |
296 | from lp.registry.interfaces.person import IPersonSet |
297 | @@ -45,26 +43,17 @@ class TestNicknameGeneration(TestCaseWithFactory): |
298 | # adding random suffixes to the required length. |
299 | self.assertIs(None, getUtility(IPersonSet).getByName('i')) |
300 | nick = generate_nick('i@example.com') |
301 | - if sys.version_info[0] >= 3: |
302 | - self.assertEqual('i-d', nick) |
303 | - else: |
304 | - self.assertEqual('i-b', nick) |
305 | + self.assertEqual('i-d', nick) |
306 | |
307 | def test_can_create_noncolliding_nicknames(self): |
308 | # Given the same email address, generate_nick doesn't recreate the |
309 | # same nick once that nick is used. |
310 | self.factory.makePerson(name='bar') |
311 | nick = generate_nick('bar@example.com') |
312 | - if sys.version_info[0] >= 3: |
313 | - self.assertEqual('bar-1', nick) |
314 | - else: |
315 | - self.assertEqual('bar-3', nick) |
316 | + self.assertEqual('bar-1', nick) |
317 | |
318 | # If we used the previously created nick and get another bar@ email |
319 | # address, another new nick is generated. |
320 | self.factory.makePerson(name=nick) |
321 | nick = generate_nick('bar@example.com') |
322 | - if sys.version_info[0] >= 3: |
323 | - self.assertEqual('3-bar', nick) |
324 | - else: |
325 | - self.assertEqual('5-bar', nick) |
326 | + self.assertEqual('3-bar', nick) |
327 | diff --git a/lib/lp/registry/tests/test_ssh.py b/lib/lp/registry/tests/test_ssh.py |
328 | index 2f3e700..006e185 100644 |
329 | --- a/lib/lp/registry/tests/test_ssh.py |
330 | +++ b/lib/lp/registry/tests/test_ssh.py |
331 | @@ -5,8 +5,6 @@ |
332 | |
333 | __metaclass__ = type |
334 | |
335 | -import sys |
336 | - |
337 | from testtools.matchers import StartsWith |
338 | from zope.component import getUtility |
339 | from zope.security.proxy import removeSecurityProxy |
340 | @@ -205,14 +203,10 @@ class TestSSHKeySet(TestCaseWithFactory): |
341 | keyset.new, |
342 | person, 'ssh-rsa badkeytext comment' |
343 | ) |
344 | - if sys.version_info[0] >= 3: |
345 | - expected_message = "unknown blob type: b'\\xc7_'" |
346 | - else: |
347 | - expected_message = "unknown blob type: \\xc7_" |
348 | self.assertRaisesWithContent( |
349 | SSHKeyAdditionError, |
350 | "Invalid SSH key data: 'ssh-rsa asdfasdf comment' " |
351 | - "(%s)" % expected_message, |
352 | + "(unknown blob type: b'\\xc7_')", |
353 | keyset.new, |
354 | person, 'ssh-rsa asdfasdf comment' |
355 | ) |
356 | diff --git a/lib/lp/scripts/utilities/importpedant.py b/lib/lp/scripts/utilities/importpedant.py |
357 | index 5bf143e..93e7da9 100644 |
358 | --- a/lib/lp/scripts/utilities/importpedant.py |
359 | +++ b/lib/lp/scripts/utilities/importpedant.py |
360 | @@ -7,7 +7,6 @@ from operator import attrgetter |
361 | import types |
362 | import warnings |
363 | |
364 | -import six |
365 | from six.moves import builtins |
366 | |
367 | |
368 | @@ -174,8 +173,7 @@ class NotFoundPolicyViolation(PedantDisagreesError): |
369 | # The names of the arguments form part of the interface of __import__(...), |
370 | # and must not be changed, as code may choose to invoke __import__ using |
371 | # keyword arguments - e.g. the encodings module in Python 2.6. |
372 | -def import_pedant(name, globals={}, locals={}, fromlist=[], |
373 | - level=(0 if six.PY3 else -1)): |
374 | +def import_pedant(name, globals={}, locals={}, fromlist=[], level=0): |
375 | global naughty_imports |
376 | |
377 | module = original_import(name, globals, locals, fromlist, level) |
378 | diff --git a/lib/lp/scripts/utilities/test.py b/lib/lp/scripts/utilities/test.py |
379 | index 375d70c..00795c2 100755 |
380 | --- a/lib/lp/scripts/utilities/test.py |
381 | +++ b/lib/lp/scripts/utilities/test.py |
382 | @@ -91,7 +91,7 @@ def configure_environment(): |
383 | # Suppress accessibility warning because the test runner does not have UI. |
384 | os.environ['GTK_MODULES'] = '' |
385 | |
386 | - if six.PY3 and distro.linux_distribution()[:2] == ('Ubuntu', '18.04'): |
387 | + if distro.linux_distribution()[:2] == ('Ubuntu', '18.04'): |
388 | # XXX cjwatson 2020-10-09: Certain versions of Python crash when |
389 | # importing readline into a process that has libedit loaded |
390 | # (https://bugs.python.org/issue38634, |
391 | diff --git a/lib/lp/services/compat.py b/lib/lp/services/compat.py |
392 | index 4d8ee9d..3673a45 100644 |
393 | --- a/lib/lp/services/compat.py |
394 | +++ b/lib/lp/services/compat.py |
395 | @@ -32,19 +32,13 @@ try: |
396 | except ImportError: |
397 | from unittest import mock |
398 | |
399 | -import six |
400 | - |
401 | - |
402 | -if six.PY3: |
403 | - def message_as_bytes(message): |
404 | - from email.generator import BytesGenerator |
405 | - from email.policy import compat32 |
406 | - |
407 | - fp = io.BytesIO() |
408 | - g = BytesGenerator( |
409 | - fp, mangle_from_=False, maxheaderlen=0, policy=compat32) |
410 | - g.flatten(message) |
411 | - return fp.getvalue() |
412 | -else: |
413 | - def message_as_bytes(message): |
414 | - return message.as_string() |
415 | + |
416 | +def message_as_bytes(message): |
417 | + from email.generator import BytesGenerator |
418 | + from email.policy import compat32 |
419 | + |
420 | + fp = io.BytesIO() |
421 | + g = BytesGenerator( |
422 | + fp, mangle_from_=False, maxheaderlen=0, policy=compat32) |
423 | + g.flatten(message) |
424 | + return fp.getvalue() |
425 | diff --git a/lib/lp/services/encoding.py b/lib/lp/services/encoding.py |
426 | index 3c1728b..aa5f74e 100644 |
427 | --- a/lib/lp/services/encoding.py |
428 | +++ b/lib/lp/services/encoding.py |
429 | @@ -228,7 +228,7 @@ def wsgi_native_string(s): |
430 | Python 2, we enforce this here. |
431 | """ |
432 | result = six.ensure_str(s, encoding='ISO-8859-1') |
433 | - if six.PY3 and isinstance(s, six.text_type): |
434 | + if isinstance(s, six.text_type): |
435 | # Ensure we're limited to ISO-8859-1. |
436 | result.encode('ISO-8859-1') |
437 | return result |
438 | diff --git a/lib/lp/services/limitedlist.py b/lib/lp/services/limitedlist.py |
439 | index 9c9ca8b..1cb0db5 100644 |
440 | --- a/lib/lp/services/limitedlist.py |
441 | +++ b/lib/lp/services/limitedlist.py |
442 | @@ -6,8 +6,6 @@ __all__ = [ |
443 | 'LimitedList', |
444 | ] |
445 | |
446 | -import sys |
447 | - |
448 | |
449 | class LimitedList(list): |
450 | """A mutable sequence that takes a limited number of elements.""" |
451 | @@ -64,15 +62,6 @@ class LimitedList(list): |
452 | self._ensureLength() |
453 | return result |
454 | |
455 | - if sys.version_info[0] < 3: |
456 | - # list.__setslice__ exists on Python 2, so we must override it in |
457 | - # this subclass. (If it didn't exist, as is the case on Python 3, |
458 | - # then __setitem__ above would be good enough.) |
459 | - def __setslice__(self, i, j, sequence): |
460 | - result = super(LimitedList, self).__setslice__(i, j, sequence) |
461 | - self._ensureLength() |
462 | - return result |
463 | - |
464 | def append(self, value): |
465 | result = super(LimitedList, self).append(value) |
466 | self._ensureLength() |
467 | diff --git a/lib/lp/services/mail/interfaces.py b/lib/lp/services/mail/interfaces.py |
468 | index 41818a4..59fdfec 100644 |
469 | --- a/lib/lp/services/mail/interfaces.py |
470 | +++ b/lib/lp/services/mail/interfaces.py |
471 | @@ -19,7 +19,6 @@ __all__ = [ |
472 | 'UnknownRecipientError', |
473 | ] |
474 | |
475 | -import six |
476 | from zope.interface import ( |
477 | Attribute, |
478 | Interface, |
479 | @@ -156,9 +155,6 @@ class INotificationRecipientSet(Interface): |
480 | def __bool__(): |
481 | """Return False when the set is empty, True when it's not.""" |
482 | |
483 | - if six.PY2: |
484 | - __nonzero__ = __bool__ |
485 | - |
486 | def getReason(person_or_email): |
487 | """Return a reason tuple containing (text, header) for an address. |
488 | |
489 | diff --git a/lib/lp/services/mail/notificationrecipientset.py b/lib/lp/services/mail/notificationrecipientset.py |
490 | index 6004399..68f9014 100644 |
491 | --- a/lib/lp/services/mail/notificationrecipientset.py |
492 | +++ b/lib/lp/services/mail/notificationrecipientset.py |
493 | @@ -88,9 +88,6 @@ class NotificationRecipientSet: |
494 | """See `INotificationRecipientSet`.""" |
495 | return bool(self._personToRationale) |
496 | |
497 | - if six.PY2: |
498 | - __nonzero__ = __bool__ |
499 | - |
500 | def getReason(self, person_or_email): |
501 | """See `INotificationRecipientSet`.""" |
502 | if zope_isinstance(person_or_email, six.string_types): |
503 | diff --git a/lib/lp/services/scripts/base.py b/lib/lp/services/scripts/base.py |
504 | index cd3f19b..989eab6 100644 |
505 | --- a/lib/lp/services/scripts/base.py |
506 | +++ b/lib/lp/services/scripts/base.py |
507 | @@ -468,11 +468,7 @@ def cronscript_enabled(control_url, name, log): |
508 | # traceback and continue on using the defaults. |
509 | try: |
510 | with response: |
511 | - if sys.version_info[:2] >= (3, 2): |
512 | - read_file = cron_config.read_file |
513 | - else: |
514 | - read_file = cron_config.readfp |
515 | - read_file(io.StringIO(response.text)) |
516 | + cron_config.read_file(io.StringIO(response.text)) |
517 | except Exception: |
518 | log.exception("Error parsing %s", control_url) |
519 | |
520 | diff --git a/lib/lp/services/tests/test_encoding.py b/lib/lp/services/tests/test_encoding.py |
521 | index 4a0e235..ed44acc 100644 |
522 | --- a/lib/lp/services/tests/test_encoding.py |
523 | +++ b/lib/lp/services/tests/test_encoding.py |
524 | @@ -7,8 +7,6 @@ from doctest import ( |
525 | ) |
526 | import unittest |
527 | |
528 | -import six |
529 | - |
530 | import lp.services.encoding |
531 | from lp.services.encoding import wsgi_native_string |
532 | from lp.testing import TestCase |
533 | @@ -16,22 +14,14 @@ from lp.testing import TestCase |
534 | |
535 | class TestWSGINativeString(TestCase): |
536 | |
537 | - def _toNative(self, s): |
538 | - if six.PY3: |
539 | - return s |
540 | - else: |
541 | - return s.encode('ISO-8859-1') |
542 | - |
543 | def test_not_bytes_or_unicode(self): |
544 | self.assertRaises(TypeError, wsgi_native_string, object()) |
545 | |
546 | def test_bytes_iso_8859_1(self): |
547 | - self.assertEqual( |
548 | - self._toNative(u'foo\xfe'), wsgi_native_string(b'foo\xfe')) |
549 | + self.assertEqual(u'foo\xfe', wsgi_native_string(b'foo\xfe')) |
550 | |
551 | def test_unicode_iso_8859_1(self): |
552 | - self.assertEqual( |
553 | - self._toNative(u'foo\xfe'), wsgi_native_string(u'foo\xfe')) |
554 | + self.assertEqual(u'foo\xfe', wsgi_native_string(u'foo\xfe')) |
555 | |
556 | def test_unicode_not_iso_8859_1(self): |
557 | self.assertRaises(UnicodeEncodeError, wsgi_native_string, u'foo\u2014') |
558 | diff --git a/lib/lp/services/twistedsupport/tests/test_xmlrpc.py b/lib/lp/services/twistedsupport/tests/test_xmlrpc.py |
559 | index 126d275..59e45fc 100644 |
560 | --- a/lib/lp/services/twistedsupport/tests/test_xmlrpc.py |
561 | +++ b/lib/lp/services/twistedsupport/tests/test_xmlrpc.py |
562 | @@ -5,12 +5,6 @@ |
563 | |
564 | __metaclass__ = type |
565 | |
566 | -import sys |
567 | - |
568 | -from testtools.matchers import ( |
569 | - LessThan, |
570 | - Not, |
571 | - ) |
572 | from twisted.python.failure import Failure |
573 | |
574 | from lp.services.twistedsupport import extract_result |
575 | @@ -58,11 +52,7 @@ class TestTrapFault(TestCase): |
576 | def assertRaisesFailure(self, failure, function, *args, **kwargs): |
577 | try: |
578 | function(*args, **kwargs) |
579 | - except Failure as raised_failure: |
580 | - self.assertThat(sys.version_info, LessThan((3, 0))) |
581 | - self.assertEqual(failure, raised_failure) |
582 | except Exception as raised_exception: |
583 | - self.assertThat(sys.version_info, Not(LessThan((3, 0)))) |
584 | self.assertEqual(failure.value, raised_exception) |
585 | |
586 | def test_raises_non_faults(self): |
587 | diff --git a/lib/lp/services/twistedsupport/xmlrpc.py b/lib/lp/services/twistedsupport/xmlrpc.py |
588 | index 3521641..70f5598 100644 |
589 | --- a/lib/lp/services/twistedsupport/xmlrpc.py |
590 | +++ b/lib/lp/services/twistedsupport/xmlrpc.py |
591 | @@ -10,8 +10,6 @@ __all__ = [ |
592 | 'trap_fault', |
593 | ] |
594 | |
595 | -import sys |
596 | - |
597 | from twisted.internet import defer |
598 | from twisted.web import xmlrpc |
599 | |
600 | @@ -68,7 +66,4 @@ def trap_fault(failure, *fault_classes): |
601 | fault = failure.value |
602 | if fault.faultCode in [cls.error_code for cls in fault_classes]: |
603 | return fault |
604 | - if sys.version_info >= (3, 0): |
605 | - failure.raiseException() |
606 | - else: |
607 | - raise failure |
608 | + failure.raiseException() |
609 | diff --git a/lib/lp/services/webapp/pgsession.py b/lib/lp/services/webapp/pgsession.py |
610 | index 0a5c664..de05da4 100644 |
611 | --- a/lib/lp/services/webapp/pgsession.py |
612 | +++ b/lib/lp/services/webapp/pgsession.py |
613 | @@ -32,33 +32,30 @@ HOURS = 60 * MINUTES |
614 | DAYS = 24 * HOURS |
615 | |
616 | |
617 | -if six.PY3: |
618 | - class Python2FriendlyUnpickler(pickle._Unpickler): |
619 | - """An unpickler that handles Python 2 datetime objects. |
620 | - |
621 | - Python 3 versions before 3.6 fail to unpickle Python 2 datetime |
622 | - objects (https://bugs.python.org/issue22005); even in Python >= 3.6 |
623 | - they require passing a different encoding to pickle.loads, which may |
624 | - have undesirable effects on other objects being unpickled. Work |
625 | - around this by instead patching in a different encoding just for the |
626 | - argument to datetime.datetime. |
627 | - """ |
628 | +class Python2FriendlyUnpickler(pickle._Unpickler): |
629 | + """An unpickler that handles Python 2 datetime objects. |
630 | + |
631 | + Python 3 versions before 3.6 fail to unpickle Python 2 datetime objects |
632 | + (https://bugs.python.org/issue22005); even in Python >= 3.6 they require |
633 | + passing a different encoding to pickle.loads, which may have undesirable |
634 | + effects on other objects being unpickled. Work around this by instead |
635 | + patching in a different encoding just for the argument to |
636 | + datetime.datetime. |
637 | + """ |
638 | |
639 | - def find_class(self, module, name): |
640 | - if module == 'datetime' and name == 'datetime': |
641 | - original_encoding = self.encoding |
642 | - self.encoding = 'bytes' |
643 | + def find_class(self, module, name): |
644 | + if module == 'datetime' and name == 'datetime': |
645 | + original_encoding = self.encoding |
646 | + self.encoding = 'bytes' |
647 | |
648 | - def datetime_factory(pickle_data): |
649 | - self.encoding = original_encoding |
650 | - return datetime(pickle_data) |
651 | + def datetime_factory(pickle_data): |
652 | + self.encoding = original_encoding |
653 | + return datetime(pickle_data) |
654 | |
655 | - return datetime_factory |
656 | - else: |
657 | - return super(Python2FriendlyUnpickler, self).find_class( |
658 | - module, name) |
659 | -else: |
660 | - Python2FriendlyUnpickler = pickle.Unpickler |
661 | + return datetime_factory |
662 | + else: |
663 | + return super(Python2FriendlyUnpickler, self).find_class( |
664 | + module, name) |
665 | |
666 | |
667 | class PGSessionBase: |
668 | diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py |
669 | index 168b22e..f4d42cd 100644 |
670 | --- a/lib/lp/services/webapp/publisher.py |
671 | +++ b/lib/lp/services/webapp/publisher.py |
672 | @@ -632,11 +632,6 @@ class CanonicalAbsoluteURL: |
673 | self.context = context |
674 | self.request = request |
675 | |
676 | - if six.PY2: |
677 | - def __unicode__(self): |
678 | - """Returns the URL as a unicode string.""" |
679 | - raise NotImplementedError() |
680 | - |
681 | def __str__(self): |
682 | """Returns an ASCII string with all unicode characters url quoted.""" |
683 | return canonical_url(self.context, self.request) |
684 | diff --git a/lib/lp/services/webapp/servers.py b/lib/lp/services/webapp/servers.py |
685 | index d637916..a2ef356 100644 |
686 | --- a/lib/lp/services/webapp/servers.py |
687 | +++ b/lib/lp/services/webapp/servers.py |
688 | @@ -211,9 +211,6 @@ class StepsToGo(six.Iterator): |
689 | def __bool__(self): |
690 | return bool(self._stack) |
691 | |
692 | - if six.PY2: |
693 | - __nonzero__ = __bool__ |
694 | - |
695 | |
696 | class ApplicationServerSettingRequestFactory: |
697 | """Create a request and call its setApplicationServer method. |
698 | @@ -527,20 +524,9 @@ def get_query_string_params(request): |
699 | if query_string is None: |
700 | query_string = '' |
701 | |
702 | - kwargs = {} |
703 | - if not six.PY2: |
704 | - kwargs['encoding'] = 'UTF-8' |
705 | - kwargs['errors'] = 'replace' |
706 | - parsed_qs = parse_qs(query_string, keep_blank_values=True, **kwargs) |
707 | - if six.PY2: |
708 | - decoded_qs = {} |
709 | - for key, values in six.iteritems(parsed_qs): |
710 | - decoded_qs[key] = [ |
711 | - (value.decode('UTF-8', 'replace') if isinstance(value, bytes) |
712 | - else value) |
713 | - for value in values] |
714 | - parsed_qs = decoded_qs |
715 | - return parsed_qs |
716 | + return parse_qs( |
717 | + query_string, keep_blank_values=True, |
718 | + encoding='UTF-8', errors='replace') |
719 | |
720 | |
721 | class LaunchpadBrowserRequestMixin: |
722 | diff --git a/lib/lp/services/webapp/tests/test_servers.py b/lib/lp/services/webapp/tests/test_servers.py |
723 | index ed66bfa..1b09775 100644 |
724 | --- a/lib/lp/services/webapp/tests/test_servers.py |
725 | +++ b/lib/lp/services/webapp/tests/test_servers.py |
726 | @@ -21,7 +21,6 @@ from lazr.restful.testing.webservice import ( |
727 | IGenericEntry, |
728 | WebServiceTestCase, |
729 | ) |
730 | -import six |
731 | from talisker.context import Context |
732 | from talisker.logs import logging_context |
733 | from zope.component import ( |
734 | @@ -441,15 +440,12 @@ class TestBasicLaunchpadRequest(TestCase): |
735 | def test_request_with_invalid_query_string_recovers(self): |
736 | # When the query string has invalid utf-8, it is decoded with |
737 | # replacement. |
738 | - if six.PY2: |
739 | - env = {'QUERY_STRING': 'field.title=subproc\xe9s '} |
740 | - else: |
741 | - # PEP 3333 requires environment variables to be native strings, |
742 | - # so we can't actually get a bytes object in here on Python 3 |
743 | - # (both because the WSGI runner will never put it there, and |
744 | - # because parse_qs would crash if we did). Test the next best |
745 | - # thing, namely percent-encoded invalid UTF-8. |
746 | - env = {'QUERY_STRING': 'field.title=subproc%E9s '} |
747 | + # PEP 3333 requires environment variables to be native strings, so |
748 | + # we can't actually get a bytes object in here on Python 3 (both |
749 | + # because the WSGI runner will never put it there, and because |
750 | + # parse_qs would crash if we did). Test the next best thing, namely |
751 | + # percent-encoded invalid UTF-8. |
752 | + env = {'QUERY_STRING': 'field.title=subproc%E9s '} |
753 | request = LaunchpadBrowserRequest(io.BytesIO(b''), env) |
754 | self.assertEqual( |
755 | [u'subproc\ufffds '], request.query_string_params['field.title']) |
756 | diff --git a/lib/lp/services/webapp/url.py b/lib/lp/services/webapp/url.py |
757 | index e438fd9..3a05c33 100644 |
758 | --- a/lib/lp/services/webapp/url.py |
759 | +++ b/lib/lp/services/webapp/url.py |
760 | @@ -6,7 +6,6 @@ |
761 | __metaclass__ = type |
762 | __all__ = ['urlappend', 'urlparse', 'urlsplit'] |
763 | |
764 | -import six |
765 | import six.moves.urllib.parse as urlparse_module |
766 | from six.moves.urllib.parse import ( |
767 | urljoin, |
768 | @@ -81,9 +80,7 @@ def urlappend(baseurl, path): |
769 | |
770 | def _ensure_ascii_str(url): |
771 | """Ensure that `url` only contains ASCII, and convert it to a `str`.""" |
772 | - if six.PY2: |
773 | - url = url.encode('ascii') |
774 | - elif isinstance(url, bytes): |
775 | + if isinstance(url, bytes): |
776 | url = url.decode('ascii') |
777 | else: |
778 | # Ignore the result; just check that `url` is pure ASCII. |
779 | diff --git a/lib/lp/services/webhooks/payload.py b/lib/lp/services/webhooks/payload.py |
780 | index f7c7e3d..d73cd1b 100644 |
781 | --- a/lib/lp/services/webhooks/payload.py |
782 | +++ b/lib/lp/services/webhooks/payload.py |
783 | @@ -12,7 +12,6 @@ __all__ = [ |
784 | from io import BytesIO |
785 | |
786 | from lazr.restful.interfaces import IFieldMarshaller |
787 | -import six |
788 | from zope.component import getMultiAdapter |
789 | from zope.interface import implementer |
790 | from zope.traversing.browser.interfaces import IAbsoluteURL |
791 | @@ -43,11 +42,6 @@ class WebhookAbsoluteURL: |
792 | self.context = context |
793 | self.request = request |
794 | |
795 | - if six.PY2: |
796 | - def __unicode__(self): |
797 | - """Returns the URL as a unicode string.""" |
798 | - raise NotImplementedError() |
799 | - |
800 | def __str__(self): |
801 | """Returns an ASCII string with all unicode characters url quoted.""" |
802 | return canonical_url(self.context, force_local_path=True) |
803 | diff --git a/lib/lp/soyuz/adapters/archivesourcepublication.py b/lib/lp/soyuz/adapters/archivesourcepublication.py |
804 | index 34e4919..f04807d 100644 |
805 | --- a/lib/lp/soyuz/adapters/archivesourcepublication.py |
806 | +++ b/lib/lp/soyuz/adapters/archivesourcepublication.py |
807 | @@ -17,7 +17,6 @@ __all__ = [ |
808 | from collections import defaultdict |
809 | |
810 | from lazr.delegates import delegate_to |
811 | -import six |
812 | from zope.component import getUtility |
813 | |
814 | from lp.registry.model.distroseries import DistroSeries |
815 | @@ -104,9 +103,6 @@ class ArchiveSourcePublications: |
816 | """Are there any sources to iterate?""" |
817 | return self.has_sources |
818 | |
819 | - if six.PY2: |
820 | - __nonzero__ = __bool__ |
821 | - |
822 | def __iter__(self): |
823 | """`ArchiveSourcePublication` iterator.""" |
824 | results = [] |
825 | diff --git a/lib/lp/soyuz/interfaces/binarypackagename.py b/lib/lp/soyuz/interfaces/binarypackagename.py |
826 | index bfef027..69973c6 100644 |
827 | --- a/lib/lp/soyuz/interfaces/binarypackagename.py |
828 | +++ b/lib/lp/soyuz/interfaces/binarypackagename.py |
829 | @@ -11,7 +11,6 @@ __all__ = [ |
830 | 'IBinaryPackageNameSet', |
831 | ] |
832 | |
833 | -import six |
834 | from zope.interface import Interface |
835 | from zope.schema import ( |
836 | Int, |
837 | @@ -31,10 +30,6 @@ class IBinaryPackageName(Interface): |
838 | def __str__(): |
839 | """Return the name""" |
840 | |
841 | - if six.PY2: |
842 | - def __unicode__(): |
843 | - """Return the name""" |
844 | - |
845 | |
846 | class IBinaryPackageNameSet(Interface): |
847 | |
848 | diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py |
849 | index 32c9923..084cee1 100644 |
850 | --- a/lib/lp/testing/factory.py |
851 | +++ b/lib/lp/testing/factory.py |
852 | @@ -38,7 +38,6 @@ from itertools import count |
853 | import os |
854 | import sys |
855 | from textwrap import dedent |
856 | -import types |
857 | import uuid |
858 | import warnings |
859 | |
860 | @@ -5210,7 +5209,7 @@ class BareLaunchpadObjectFactory(ObjectFactory): |
861 | # Some factory methods return simple Python types. We don't add |
862 | # security wrappers for them, as well as for objects created by |
863 | # other Python libraries. |
864 | -unwrapped_types = { |
865 | +unwrapped_types = frozenset({ |
866 | BaseRecipeBranch, |
867 | DSCFile, |
868 | Message, |
869 | @@ -5218,10 +5217,7 @@ unwrapped_types = { |
870 | int, |
871 | str, |
872 | six.text_type, |
873 | - } |
874 | -if sys.version_info[0] < 3: |
875 | - unwrapped_types.add(types.InstanceType) |
876 | -unwrapped_types = frozenset(unwrapped_types) |
877 | + }) |
878 | |
879 | |
880 | def is_security_proxied_or_harmless(obj): |
881 | diff --git a/lib/lp/testing/systemdocs.py b/lib/lp/testing/systemdocs.py |
882 | index 5e9bdac..29bb200 100644 |
883 | --- a/lib/lp/testing/systemdocs.py |
884 | +++ b/lib/lp/testing/systemdocs.py |
885 | @@ -232,19 +232,16 @@ class PrettyPrinter(pprint.PrettyPrinter, object): |
886 | return '"%s"' % obj, True, False |
887 | else: |
888 | return "'%s'" % obj.replace("'", "\\'"), True, False |
889 | - elif sys.version_info[0] < 3 and isinstance(obj, long): |
890 | - return repr(int(obj)), True, False |
891 | else: |
892 | return super(PrettyPrinter, self).format( |
893 | obj, contexts, maxlevels, level) |
894 | |
895 | # Disable wrapping of long strings on Python >= 3.5, which is unhelpful |
896 | # in doctests. There seems to be no reasonable public API for this. |
897 | - if sys.version_info[:2] >= (3, 5): |
898 | - _dispatch = dict(pprint.PrettyPrinter._dispatch) |
899 | - del _dispatch[six.text_type.__repr__] |
900 | - del _dispatch[bytes.__repr__] |
901 | - del _dispatch[bytearray.__repr__] |
902 | + _dispatch = dict(pprint.PrettyPrinter._dispatch) |
903 | + del _dispatch[six.text_type.__repr__] |
904 | + del _dispatch[bytes.__repr__] |
905 | + del _dispatch[bytearray.__repr__] |
906 | |
907 | |
908 | # XXX cjwatson 2018-05-13: Once all doctests are made safe for the standard |
909 | diff --git a/lib/lp/translations/doc/poexport-queue.txt b/lib/lp/translations/doc/poexport-queue.txt |
910 | index 7854639..562eb08 100644 |
911 | --- a/lib/lp/translations/doc/poexport-queue.txt |
912 | +++ b/lib/lp/translations/doc/poexport-queue.txt |
913 | @@ -139,14 +139,12 @@ It's not clear that it's possible to trigger this failure mode normally on |
914 | Python 3 at all, because bytes will just be formatted as b'...'. For now, |
915 | inject a mock exception in that case so that the test can pass. |
916 | |
917 | - >>> if six.PY3: |
918 | - ... from lp.services.compat import mock |
919 | - ... patcher = mock.patch.object(result, 'failure') |
920 | - ... mock_failure = patcher.start() |
921 | - ... mock_failure.__str__.side_effect = lambda: b'\xc3'.decode('UTF-8') |
922 | + >>> from lp.services.compat import mock |
923 | + >>> patcher = mock.patch.object(result, 'failure') |
924 | + >>> mock_failure = patcher.start() |
925 | + >>> mock_failure.__str__.side_effect = lambda: b'\xc3'.decode('UTF-8') |
926 | >>> result.notify() |
927 | - >>> if six.PY3: |
928 | - ... patcher.stop() |
929 | + >>> patcher.stop() |
930 | |
931 | >>> test_emails = pop_notifications() |
932 | >>> len(test_emails) |
933 | diff --git a/lib/lp/translations/model/translatedlanguage.py b/lib/lp/translations/model/translatedlanguage.py |
934 | index e9d120a..7c7606c 100644 |
935 | --- a/lib/lp/translations/model/translatedlanguage.py |
936 | +++ b/lib/lp/translations/model/translatedlanguage.py |
937 | @@ -4,7 +4,6 @@ |
938 | __all__ = ['TranslatedLanguageMixin'] |
939 | |
940 | import pytz |
941 | -import six |
942 | from storm.expr import ( |
943 | Coalesce, |
944 | Desc, |
945 | @@ -75,9 +74,6 @@ class POFilesByPOTemplates(object): |
946 | def __bool__(self): |
947 | return bool(self.templates_collection.select(POTemplate).any()) |
948 | |
949 | - if six.PY2: |
950 | - __nonzero__ = __bool__ |
951 | - |
952 | |
953 | @implementer(ITranslatedLanguage) |
954 | class TranslatedLanguageMixin(object): |
955 | diff --git a/lib/sqlobject/__init__.py b/lib/sqlobject/__init__.py |
956 | index 5450477..bc94046 100644 |
957 | --- a/lib/sqlobject/__init__.py |
958 | +++ b/lib/sqlobject/__init__.py |
959 | @@ -51,8 +51,6 @@ def sqlrepr(value, dbname=None): |
960 | return "'f'" |
961 | elif isinstance(value, int): |
962 | return repr(int(value)) |
963 | - elif six.PY2 and isinstance(value, long): |
964 | - return str(value) |
965 | elif isinstance(value, float): |
966 | return repr(value) |
967 | elif value is None: |
968 | diff --git a/scripts/process-one-mail.py b/scripts/process-one-mail.py |
969 | index 0fa7484..3cb8598 100755 |
970 | --- a/scripts/process-one-mail.py |
971 | +++ b/scripts/process-one-mail.py |
972 | @@ -31,10 +31,8 @@ class ProcessMail(LaunchpadScript): |
973 | # with handling a mailbox, which we're avoiding here. |
974 | if len(self.args) >= 1: |
975 | from_file = open(self.args[0], 'rb') |
976 | - elif sys.version_info[0] >= 3: |
977 | - from_file = sys.stdin.buffer |
978 | else: |
979 | - from_file = sys.stdin |
980 | + from_file = sys.stdin.buffer |
981 | self.logger.debug("reading message from %r" % (from_file,)) |
982 | raw_mail = from_file.read() |
983 | if from_file != sys.stdin: |
Looks good!