Merge ~cjwatson/launchpad:reduce-ensure-str into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 84ad29369c11fcaef75eff96df0fe73a56ad855f
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:reduce-ensure-str
Merge into: launchpad:master
Diff against target: 1607 lines (+153/-211)
57 files modified
lib/launchpad_loggerhead/app.py (+1/-2)
lib/lp/answers/stories/question-obfuscation.txt (+2/-2)
lib/lp/app/doc/displaying-paragraphs-of-text.txt (+7/-12)
lib/lp/app/doc/launchpadform.txt (+1/-1)
lib/lp/app/doc/launchpadview.txt (+2/-2)
lib/lp/app/doc/menus.txt (+1/-1)
lib/lp/app/doc/textformatting.txt (+2/-2)
lib/lp/app/widgets/doc/announcement-date-widget.txt (+1/-1)
lib/lp/app/widgets/doc/noneable-text-widgets.txt (+1/-1)
lib/lp/app/widgets/doc/project-scope-widget.txt (+1/-2)
lib/lp/app/widgets/doc/stripped-text-widget.txt (+1/-1)
lib/lp/blueprints/browser/sprint.py (+0/-7)
lib/lp/blueprints/stories/blueprints/xx-editing.txt (+2/-2)
lib/lp/blueprints/stories/blueprints/xx-productseries.txt (+5/-6)
lib/lp/blueprints/stories/standalone/subscribing.txt (+10/-14)
lib/lp/bugs/model/tests/test_bugtasksearch.py (+4/-7)
lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt (+2/-2)
lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt (+3/-3)
lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt (+5/-5)
lib/lp/bugs/stories/bugs/xx-bug-edit.txt (+2/-2)
lib/lp/bugs/stories/bugs/xx-bug-index.txt (+2/-2)
lib/lp/bugs/stories/bugs/xx-bug-obfuscation.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-bug-text-pages.txt (+1/-1)
lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt (+2/-3)
lib/lp/code/browser/tests/test_codereviewcomment.py (+1/-1)
lib/lp/code/model/branch.py (+1/-1)
lib/lp/coop/answersbugs/visibility.py (+1/-3)
lib/lp/registry/browser/tests/person-admin-views.txt (+3/-3)
lib/lp/registry/browser/tests/test_announcements.py (+1/-2)
lib/lp/registry/doc/person-account.txt (+3/-3)
lib/lp/registry/scripts/tests/test_closeaccount.py (+33/-34)
lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt (+2/-2)
lib/lp/services/database/doc/enumcol.txt (+1/-1)
lib/lp/services/database/doc/textsearching.txt (+2/-2)
lib/lp/services/doc/limitedlist.txt (+1/-1)
lib/lp/services/gpg/doc/gpg-encryption.txt (+4/-4)
lib/lp/services/gpg/handler.py (+1/-2)
lib/lp/services/gpg/tests/test_gpghandler.py (+2/-2)
lib/lp/services/librarian/model.py (+1/-2)
lib/lp/services/mail/doc/notification-recipient-set.txt (+1/-1)
lib/lp/services/webapp/breadcrumb.py (+1/-6)
lib/lp/services/webapp/doc/canonical_url.txt (+1/-2)
lib/lp/services/webapp/doc/menus.txt (+1/-2)
lib/lp/services/webapp/doc/test_adapter.txt (+2/-2)
lib/lp/services/webapp/publication.py (+1/-5)
lib/lp/services/webapp/publisher.py (+3/-5)
lib/lp/services/webapp/servers.py (+1/-3)
lib/lp/services/webservice/doc/launchpadlib.txt (+1/-3)
lib/lp/soyuz/scripts/gina/packages.py (+2/-6)
lib/lp/soyuz/scripts/ppareport.py (+2/-3)
lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt (+1/-2)
lib/lp/translations/model/pomsgid.py (+1/-1)
lib/lp/translations/model/potranslation.py (+1/-1)
lib/lp/translations/stories/standalone/xx-language.txt (+2/-3)
lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt (+5/-6)
lib/lp/translations/stories/translations/xx-translations.txt (+10/-12)
scripts/list-team-members (+1/-3)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+415902@code.launchpad.net

Commit message

Remove simple uses of six.ensure_str

Description of the change

These were clearly no-ops on Python 3, but missed by pyupgrade for various reasons, such as being in doctests.

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) wrote :

LGTM 👍

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/launchpad_loggerhead/app.py b/lib/launchpad_loggerhead/app.py
2index 7ada98a..3e693f2 100644
3--- a/lib/launchpad_loggerhead/app.py
4+++ b/lib/launchpad_loggerhead/app.py
5@@ -40,7 +40,6 @@ from paste.request import (
6 parse_querystring,
7 path_info_pop,
8 )
9-import six
10 from six.moves.urllib.parse import (
11 urlencode,
12 urljoin,
13@@ -256,7 +255,7 @@ class RootApp:
14 self.log.info('Using branch: %s', branch_name)
15 if trail and not trail.startswith('/'):
16 trail = '/' + trail
17- environ['PATH_INFO'] = six.ensure_str(trail)
18+ environ['PATH_INFO'] = trail
19 environ['SCRIPT_NAME'] += consumed.rstrip('/')
20 branch_url = lp_server.get_url() + branch_name
21 branch_link = urljoin(
22diff --git a/lib/lp/answers/stories/question-obfuscation.txt b/lib/lp/answers/stories/question-obfuscation.txt
23index f6a23c9..1f082fd 100644
24--- a/lib/lp/answers/stories/question-obfuscation.txt
25+++ b/lib/lp/answers/stories/question-obfuscation.txt
26@@ -96,7 +96,7 @@ Anonymous cannot see the email address anywhere on the Answers front
27 page.
28
29 >>> anon_browser.open('http://answers.launchpad.test/')
30- >>> six.ensure_str('user@domain.com') in anon_browser.contents
31+ >>> 'user@domain.com' in anon_browser.contents
32 False
33
34 >>> question_portlet = find_tag_by_id(
35@@ -132,7 +132,7 @@ They cannot see the address reading the question either.
36 link ...
37
38 >>> anon_browser.getLink('mailto: problem in webpage').click()
39- >>> six.ensure_str('user@domain.com') in anon_browser.contents
40+ >>> 'user@domain.com' in anon_browser.contents
41 False
42
43 >>> description = find_main_content(anon_browser.contents).p
44diff --git a/lib/lp/app/doc/displaying-paragraphs-of-text.txt b/lib/lp/app/doc/displaying-paragraphs-of-text.txt
45index 94171e0..c50955a 100644
46--- a/lib/lp/app/doc/displaying-paragraphs-of-text.txt
47+++ b/lib/lp/app/doc/displaying-paragraphs-of-text.txt
48@@ -494,7 +494,7 @@ we want to replace a variable number of spaces with the same number of
49
50 >>> from lp.app.browser.stringformatter import FormattersAPI
51 >>> import re
52- >>> matchobj = re.match('foo(.*)bar', six.ensure_str('fooX Ybar'))
53+ >>> matchobj = re.match('foo(.*)bar', 'fooX Ybar')
54 >>> matchobj.groups()
55 ('X Y',)
56 >>> FormattersAPI._substitute_matchgroup_for_spaces(matchobj)
57@@ -508,10 +508,9 @@ First, let's try a match of nothing it understands. This is a bug, so we get
58 an AssertionError.
59
60 >>> matchobj = re.match(
61- ... six.ensure_str(
62- ... '(?P<bug>xxx)?(?P<faq>www)?(?P<url>yyy)?(?P<oops>zzz)?'
63- ... '(?P<lpbranchurl>www)?(?P<clbug>vvv)?'),
64- ... six.ensure_str('fish'))
65+ ... '(?P<bug>xxx)?(?P<faq>www)?(?P<url>yyy)?(?P<oops>zzz)?'
66+ ... '(?P<lpbranchurl>www)?(?P<clbug>vvv)?',
67+ ... 'fish')
68 >>> sorted(matchobj.groupdict().items())
69 [('bug', None),
70 ('clbug', None),
71@@ -527,9 +526,7 @@ an AssertionError.
72 When we have a URL, the URL is made into a link. A quote is added to the
73 url to demonstrate quoting in the HTML attribute.
74
75- >>> matchobj = re.match(
76- ... six.ensure_str('(?P<bug>xxx)?(?P<url>y"y)?'),
77- ... six.ensure_str('y"y'))
78+ >>> matchobj = re.match('(?P<bug>xxx)?(?P<url>y"y)?', 'y"y')
79 >>> sorted(matchobj.groupdict().items())
80 [('bug', None), ('url', 'y"y')]
81 >>> print(FormattersAPI._linkify_substitution(matchobj))
82@@ -539,8 +536,7 @@ When we have a bug reference, the 'bug' group is used as the text of the link,
83 and the 'bugnum' is used to look up the bug.
84
85 >>> matchobj = re.match(
86- ... six.ensure_str('(?P<bug>xxxx)?(?P<bugnum>2)?(?P<url>yyy)?'),
87- ... six.ensure_str('xxxx2'))
88+ ... '(?P<bug>xxxx)?(?P<bugnum>2)?(?P<url>yyy)?', 'xxxx2')
89 >>> sorted(matchobj.groupdict().items())
90 [('bug', 'xxxx'), ('bugnum', '2'), ('url', None)]
91 >>> FormattersAPI._linkify_substitution(matchobj)
92@@ -550,8 +546,7 @@ When the bugnum doesn't match any bug, we still get a link, but get a message
93 in the link's title.
94
95 >>> matchobj = re.match(
96- ... six.ensure_str('(?P<bug>xxxx)?(?P<bugnum>2000)?(?P<url>yyy)?'),
97- ... six.ensure_str('xxxx2000'))
98+ ... '(?P<bug>xxxx)?(?P<bugnum>2000)?(?P<url>yyy)?', 'xxxx2000')
99 >>> sorted(matchobj.groupdict().items())
100 [('bug', 'xxxx'), ('bugnum', '2000'), ('url', None)]
101 >>> FormattersAPI._linkify_substitution(matchobj)
102diff --git a/lib/lp/app/doc/launchpadform.txt b/lib/lp/app/doc/launchpadform.txt
103index db59937..6fa4e8e 100644
104--- a/lib/lp/app/doc/launchpadform.txt
105+++ b/lib/lp/app/doc/launchpadform.txt
106@@ -229,7 +229,7 @@ setFieldError() method (for errors specific to a field):
107 ... self.addError('your password may not be the same '
108 ... 'as your name')
109 ... if data.get('password') == 'password':
110- ... self.setFieldError(six.ensure_str('password'),
111+ ... self.setFieldError('password',
112 ... 'your password must not be "password"')
113
114 >>> context = FormTest()
115diff --git a/lib/lp/app/doc/launchpadview.txt b/lib/lp/app/doc/launchpadview.txt
116index f49c1ef..2951085 100644
117--- a/lib/lp/app/doc/launchpadview.txt
118+++ b/lib/lp/app/doc/launchpadview.txt
119@@ -62,7 +62,7 @@ an IStructuredString implementation.
120 >>> print(view.info_message)
121 None
122
123- >>> view.error_message = six.ensure_str('A simple string.')
124+ >>> view.error_message = 'A simple string.'
125 Traceback (most recent call last):
126 ...
127 ValueError: <... 'str'> is not a valid value for error_message,
128@@ -70,7 +70,7 @@ an IStructuredString implementation.
129 >>> print(view.error_message)
130 None
131
132- >>> view.info_message = six.ensure_str('A simple string.')
133+ >>> view.info_message = 'A simple string.'
134 Traceback (most recent call last):
135 ...
136 ValueError: <... 'str'> is not a valid value for info_message,
137diff --git a/lib/lp/app/doc/menus.txt b/lib/lp/app/doc/menus.txt
138index c76ac01..001eac8 100644
139--- a/lib/lp/app/doc/menus.txt
140+++ b/lib/lp/app/doc/menus.txt
141@@ -33,7 +33,7 @@ later, implementations having facets and menus will be defined.
142
143 >>> import sys
144 >>> import types
145- >>> cookingexample = types.ModuleType(six.ensure_str('cookingexample'))
146+ >>> cookingexample = types.ModuleType('cookingexample')
147 >>> sys.modules['lp.app.cookingexample'] = cookingexample
148
149 >>> cookingexample.ICookbook = ICookbook
150diff --git a/lib/lp/app/doc/textformatting.txt b/lib/lp/app/doc/textformatting.txt
151index 3d9dd40..faee73c 100644
152--- a/lib/lp/app/doc/textformatting.txt
153+++ b/lib/lp/app/doc/textformatting.txt
154@@ -230,14 +230,14 @@ The line endings are normalized to \n, so if we get a text with
155 dos-style line endings, we get the following result:
156
157 >>> mailwrapper = MailWrapper(width=56)
158- >>> dos_style_comment = six.ensure_str(
159+ >>> dos_style_comment = (
160 ... "This paragraph is longer than 56 characters, so it should"
161 ... " be wrapped even though the paragraphs are separated with"
162 ... " dos-style line endings."
163 ... "\r\n\r\n"
164 ... "Here's the second paragraph.")
165 >>> wrapped_text = mailwrapper.format(dos_style_comment)
166- >>> wrapped_text.split(six.ensure_str('\n'))
167+ >>> wrapped_text.split('\n')
168 ['This paragraph is longer than 56 characters, so it',
169 'should be wrapped even though the paragraphs are',
170 'separated with dos-style line endings.',
171diff --git a/lib/lp/app/widgets/doc/announcement-date-widget.txt b/lib/lp/app/widgets/doc/announcement-date-widget.txt
172index d90250c..3b901ce 100644
173--- a/lib/lp/app/widgets/doc/announcement-date-widget.txt
174+++ b/lib/lp/app/widgets/doc/announcement-date-widget.txt
175@@ -9,7 +9,7 @@ future, or to manually publish it later.
176 >>> from lp.testing.pages import extract_text
177 >>> from lp.services.webapp.servers import LaunchpadTestRequest
178 >>> from lp.app.widgets.announcementdate import AnnouncementDateWidget
179- >>> field = Field(__name__=six.ensure_str('foo'), title=u'Foo')
180+ >>> field = Field(__name__='foo', title='Foo')
181 >>> widget = AnnouncementDateWidget(field, LaunchpadTestRequest())
182 >>> print(extract_text(widget()))
183 Publish this announcement:
184diff --git a/lib/lp/app/widgets/doc/noneable-text-widgets.txt b/lib/lp/app/widgets/doc/noneable-text-widgets.txt
185index 85ca174..6f79a1c 100644
186--- a/lib/lp/app/widgets/doc/noneable-text-widgets.txt
187+++ b/lib/lp/app/widgets/doc/noneable-text-widgets.txt
188@@ -65,5 +65,5 @@ Excess whitespace is stripped, but newlines are preserved.
189 >>> request = LaunchpadTestRequest(
190 ... form={'field.summary' : ' flower \n grass '})
191 >>> widget = NoneableDescriptionWidget(field, request)
192- >>> six.ensure_str(widget.getInputValue())
193+ >>> widget.getInputValue()
194 'flower \n grass'
195diff --git a/lib/lp/app/widgets/doc/project-scope-widget.txt b/lib/lp/app/widgets/doc/project-scope-widget.txt
196index 366a4bd..1871412 100644
197--- a/lib/lp/app/widgets/doc/project-scope-widget.txt
198+++ b/lib/lp/app/widgets/doc/project-scope-widget.txt
199@@ -15,8 +15,7 @@ selected.
200
201 >>> empty_request = LaunchpadTestRequest()
202 >>> scope_field = Choice(
203- ... __name__=six.ensure_str('scope'), vocabulary='ProjectGroup',
204- ... required=False)
205+ ... __name__='scope', vocabulary='ProjectGroup', required=False)
206 >>> scope_field = scope_field.bind(object())
207 >>> widget = ProjectScopeWidget(
208 ... scope_field, scope_field.vocabulary, empty_request)
209diff --git a/lib/lp/app/widgets/doc/stripped-text-widget.txt b/lib/lp/app/widgets/doc/stripped-text-widget.txt
210index 3343cd7..c4612d1 100644
211--- a/lib/lp/app/widgets/doc/stripped-text-widget.txt
212+++ b/lib/lp/app/widgets/doc/stripped-text-widget.txt
213@@ -57,7 +57,7 @@ provided.
214 True
215
216 >>> required_field = StrippedTextLine(
217- ... __name__=six.ensure_str('field'), title=u'Title', required=True)
218+ ... __name__='field', title=u'Title', required=True)
219 >>> request = LaunchpadTestRequest(form={'field.field':' \n '})
220 >>> widget = StrippedTextWidget(required_field, request)
221 >>> widget.getInputValue()
222diff --git a/lib/lp/blueprints/browser/sprint.py b/lib/lp/blueprints/browser/sprint.py
223index 84ac65e..95bf105 100644
224--- a/lib/lp/blueprints/browser/sprint.py
225+++ b/lib/lp/blueprints/browser/sprint.py
226@@ -612,13 +612,6 @@ class SprintAttendeesCsvExportView(LaunchpadView):
227 attendance.time_starts.strftime('%Y-%m-%dT%H:%M:%SZ'),
228 attendance.time_ends.strftime('%Y-%m-%dT%H:%M:%SZ'),
229 str(attendance.is_physical)))
230- # On Python 2, CSV can't handle unicode, so we encode everything as
231- # UTF-8. Note that none of the columns constructed above can ever
232- # be None, so it's safe to use six.ensure_str here (which will raise
233- # TypeError if given None).
234- rows = [[six.ensure_str(column)
235- for column in row]
236- for row in rows]
237 self.request.response.setHeader(
238 'Content-type', 'text/csv;charset="utf-8"')
239 self.request.response.setHeader(
240diff --git a/lib/lp/blueprints/stories/blueprints/xx-editing.txt b/lib/lp/blueprints/stories/blueprints/xx-editing.txt
241index b5b3e2c..fd1a89a 100644
242--- a/lib/lp/blueprints/stories/blueprints/xx-editing.txt
243+++ b/lib/lp/blueprints/stories/blueprints/xx-editing.txt
244@@ -26,7 +26,7 @@ Launchpad won't let us use an URL already used in another blueprint.
245 >>> browser.getControl('Specification URL').value = url
246 >>> browser.getControl('Change').click()
247
248- >>> message = six.ensure_str(
249+ >>> message = (
250 ... 'https://wiki.ubuntu.com/MediaIntegrityCheck is already '
251 ... 'registered by')
252 >>> message in browser.contents
253@@ -40,7 +40,7 @@ product.
254 >>> browser.getControl('Specification URL').value = url
255 >>> browser.getControl('Change').click()
256
257- >>> message = six.ensure_str('e4x is already in use by another blueprint')
258+ >>> message = 'e4x is already in use by another blueprint'
259 >>> message in browser.contents
260 True
261
262diff --git a/lib/lp/blueprints/stories/blueprints/xx-productseries.txt b/lib/lp/blueprints/stories/blueprints/xx-productseries.txt
263index 309a17f..4b3f4a3 100644
264--- a/lib/lp/blueprints/stories/blueprints/xx-productseries.txt
265+++ b/lib/lp/blueprints/stories/blueprints/xx-productseries.txt
266@@ -153,8 +153,7 @@ there are none left in the queue.
267 ... 'http://blueprints.launchpad.test/firefox/1.0/+setgoals')
268 >>> driver_browser.getControl('Support E4X').selected = True
269 >>> driver_browser.getControl('Decline').click()
270- >>> six.ensure_str('Declined 1 specification(s)') in (
271- ... driver_browser.contents)
272+ >>> 'Declined 1 specification(s)' in driver_browser.contents
273 True
274
275 The accepted item should show up in the list of specs for this series:
276@@ -216,9 +215,9 @@ OK, lets see if it was immediately accepted:
277
278 >>> anon_browser.open(
279 ... 'http://launchpad.test/firefox/+spec/svg-support')
280- >>> six.ensure_str('firefox/trunk') in anon_browser.contents
281+ >>> 'firefox/trunk' in anon_browser.contents
282 True
283- >>> six.ensure_str('Accepted') in anon_browser.contents
284+ >>> 'Accepted' in anon_browser.contents
285 True
286
287 And lets put it back:
288@@ -258,7 +257,7 @@ And again, it should be accepted automatically.
289
290 >>> anon_browser.open(
291 ... 'http://launchpad.test/firefox/+spec/svg-support')
292- >>> six.ensure_str('firefox/1.0') in anon_browser.contents
293+ >>> 'firefox/1.0' in anon_browser.contents
294 True
295- >>> six.ensure_str('Accepted') in anon_browser.contents
296+ >>> 'Accepted' in anon_browser.contents
297 True
298diff --git a/lib/lp/blueprints/stories/standalone/subscribing.txt b/lib/lp/blueprints/stories/standalone/subscribing.txt
299index beab847..f8289a0 100644
300--- a/lib/lp/blueprints/stories/standalone/subscribing.txt
301+++ b/lib/lp/blueprints/stories/standalone/subscribing.txt
302@@ -52,11 +52,10 @@ Now, we'll POST the form. We should see a message that we have just
303 subscribed.
304
305 >>> browser.getControl('Subscribe').click()
306- >>> six.ensure_str('You have subscribed to this blueprint') in (
307- ... browser.contents)
308+ >>> 'You have subscribed to this blueprint' in browser.contents
309 True
310
311- >>> six.ensure_str('subscriber-essential') in browser.contents
312+ >>> 'subscriber-essential' in browser.contents
313 True
314
315 Now the link should say "Update subscription" in the actions menu.
316@@ -77,11 +76,10 @@ We will unset the essential flag and resubmit:
317
318 >>> essential.selected = False
319 >>> browser.getControl('Change').click()
320- >>> six.ensure_str('Your subscription has been updated') in (
321- ... browser.contents)
322+ >>> 'Your subscription has been updated' in browser.contents
323 True
324
325- >>> six.ensure_str('subscriber-inessential') in browser.contents
326+ >>> 'subscriber-inessential' in browser.contents
327 True
328
329 It's also possible to change the essential flag clicking on the star
330@@ -93,7 +91,7 @@ icon in the Subscribers portlet.
331 >>> browser.url
332 'http://blueprints.launchpad.test/firefox/+spec/e4x'
333
334- >>> six.ensure_str('subscriber-essential') in browser.contents
335+ >>> 'subscriber-essential' in browser.contents
336 True
337
338 We don't really want to be subscribed, so lets unsubscribe from that
339@@ -104,14 +102,13 @@ unsubscribe confirmation page loads.
340 >>> unsubit.click()
341 >>> confirm = browser.getControl('Unsubscribe')
342 >>> confirm.click()
343- >>> six.ensure_str('You have unsubscribed from this blueprint.') in (
344- ... browser.contents)
345+ >>> 'You have unsubscribed from this blueprint.' in browser.contents
346 True
347
348- >>> six.ensure_str('subscriber-inessential') in browser.contents
349+ >>> 'subscriber-inessential' in browser.contents
350 False
351
352- >>> six.ensure_str('subscriber-essential') in browser.contents
353+ >>> 'subscriber-essential' in browser.contents
354 False
355
356
357@@ -128,8 +125,7 @@ When we want other users to track a specification we can subscribe them.
358
359 >>> browser.getControl('Subscriber').value = 'stub'
360 >>> browser.getControl('Subscribe').click()
361- >>> msg = six.ensure_str(
362- ... "Stuart Bishop has been subscribed to this blueprint.")
363+ >>> msg = "Stuart Bishop has been subscribed to this blueprint."
364 >>> msg in browser.contents
365 True
366
367@@ -280,7 +276,7 @@ list, and now the unsubscribe confirmation page loads.
368 >>> unsubit.click()
369 >>> confirm = browser.getControl('Unsubscribe')
370 >>> confirm.click()
371- >>> msg = six.ensure_str(
372+ >>> msg = (
373 ... "Launchpad Administrators has been unsubscribed from this "
374 ... "blueprint.")
375 >>> msg in browser.contents
376diff --git a/lib/lp/bugs/model/tests/test_bugtasksearch.py b/lib/lp/bugs/model/tests/test_bugtasksearch.py
377index a8bd7a7..c19503e 100644
378--- a/lib/lp/bugs/model/tests/test_bugtasksearch.py
379+++ b/lib/lp/bugs/model/tests/test_bugtasksearch.py
380@@ -9,7 +9,6 @@ from operator import attrgetter
381 import unittest
382
383 import pytz
384-import six
385 from storm.expr import Or
386 from testtools.matchers import Equals
387 from testtools.testcase import ExpectedException
388@@ -2460,8 +2459,7 @@ def test_suite():
389 loader = unittest.TestLoader()
390 for bug_target_search_type_class in (
391 PreloadBugtaskTargets, NoPreloadBugtaskTargets, QueryBugIDs):
392- class_name = six.ensure_str(
393- 'Test%s' % bug_target_search_type_class.__name__)
394+ class_name = 'Test%s' % bug_target_search_type_class.__name__
395 class_bases = (
396 bug_target_search_type_class, ProductTarget, OnceTests,
397 SearchTestBase, TestCaseWithFactory)
398@@ -2469,10 +2467,9 @@ def test_suite():
399 suite.addTest(loader.loadTestsFromTestCase(test_class))
400
401 for target_mixin in bug_targets_mixins:
402- class_name = six.ensure_str(
403- 'Test%s%s' % (
404- bug_target_search_type_class.__name__,
405- target_mixin.__name__))
406+ class_name = 'Test%s%s' % (
407+ bug_target_search_type_class.__name__,
408+ target_mixin.__name__)
409 mixins = [
410 target_mixin, bug_target_search_type_class]
411 class_bases = (
412diff --git a/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt b/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
413index d58193d..7a7ebf8 100644
414--- a/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
415+++ b/lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt
416@@ -704,7 +704,7 @@ confirmation.
417 mailto:dark-master-o-bugs@mylittlepony.com
418
419 >>> user_browser.contents.count(
420- ... six.ensure_str('mailto:dark-master-o-bugs@mylittlepony.com'))
421+ ... 'mailto:dark-master-o-bugs@mylittlepony.com')
422 3
423
424 To evade harvesting, the email address above is obfuscated if you're not
425@@ -720,5 +720,5 @@ logged in.
426 auto-dark-master-o-bugs
427
428 >>> anon_browser.contents.count(
429- ... six.ensure_str('mailto:dark-master-o-bugs@mylittlepony.com'))
430+ ... 'mailto:dark-master-o-bugs@mylittlepony.com')
431 0
432diff --git a/lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt b/lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt
433index 918cf50..e4b2e8d 100644
434--- a/lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt
435+++ b/lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt
436@@ -34,11 +34,11 @@ Let's specify two valid tags.
437
438 Now the tags will be displayed on the bug page:
439
440- >>> six.ensure_str('Tags:') in user_browser.contents
441+ >>> 'Tags:' in user_browser.contents
442 True
443- >>> six.ensure_str('foo') in user_browser.contents
444+ >>> 'foo' in user_browser.contents
445 True
446- >>> six.ensure_str('bar') in user_browser.contents
447+ >>> 'bar' in user_browser.contents
448 True
449
450 Simply changing the ordering of the bug tags won't cause anything to
451diff --git a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
452index ec8e157..ae6db94 100644
453--- a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
454+++ b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
455@@ -44,14 +44,14 @@ We can check that the attachment is there
456 >>> link.url
457 'http://bugs.launchpad.test/firefox/+bug/1/+attachment/.../+files/foo.txt'
458
459- >>> six.ensure_str('Added some information') in user_browser.contents
460+ >>> 'Added some information' in user_browser.contents
461 True
462
463 And that we stripped the leading and trailing whitespace correctly
464
465- >>> six.ensure_str(' Some information ') in user_browser.contents
466+ >>> ' Some information ' in user_browser.contents
467 False
468- >>> six.ensure_str('Some information') in user_browser.contents
469+ >>> 'Some information' in user_browser.contents
470 True
471
472 If no description is given it gets set to the attachment filename. It's
473@@ -265,7 +265,7 @@ We can also edit the attachment details, let's navigate to that page.
474 >>> user_browser.url
475 'http://bugs.launchpad.test/firefox/+bug/1/+attachment/...'
476
477- >>> six.ensure_str('Edit attachment') in user_browser.contents
478+ >>> 'Edit attachment' in user_browser.contents
479 True
480
481 There's also an option to cancel, which takes you back to the bug
482@@ -286,7 +286,7 @@ whitespace to test that's correctly stripped)...
483 >>> user_browser.url
484 'http://bugs.launchpad.test/firefox/+bug/1'
485
486- >>> six.ensure_str('Another title') in user_browser.contents
487+ >>> 'Another title' in user_browser.contents
488 True
489
490 We can edit the attachment to be a patch.
491diff --git a/lib/lp/bugs/stories/bugs/xx-bug-edit.txt b/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
492index 7700e4a..2456c33 100644
493--- a/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
494+++ b/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
495@@ -73,9 +73,9 @@ Now we are back at the bug page, and the tag has been added.
496
497 >>> user_browser.url
498 'http://bugs.launchpad.test/firefox/+bug/1'
499- >>> six.ensure_str('layout-test') in user_browser.contents
500+ >>> 'layout-test' in user_browser.contents
501 True
502- >>> six.ensure_str('new-tag') in user_browser.contents
503+ >>> 'new-tag' in user_browser.contents
504 False
505
506 Now, let's add 'new-tag' again, and confirm it this time.
507diff --git a/lib/lp/bugs/stories/bugs/xx-bug-index.txt b/lib/lp/bugs/stories/bugs/xx-bug-index.txt
508index 590df67..540000e 100644
509--- a/lib/lp/bugs/stories/bugs/xx-bug-index.txt
510+++ b/lib/lp/bugs/stories/bugs/xx-bug-index.txt
511@@ -43,7 +43,7 @@ highlighted.
512 ...<tr>
513 ...mozilla-firefox (Ubuntu)...
514 ...
515- >>> anon_browser.contents.count(six.ensure_str('<tr class="highlight"'))
516+ >>> anon_browser.contents.count('<tr class="highlight"')
517 1
518
519 >>> anon_browser.open(
520@@ -60,7 +60,7 @@ highlighted.
521 ...<tr>
522 ...mozilla-firefox (Ubuntu)...
523 ...
524- >>> anon_browser.contents.count(six.ensure_str('<tr class="highlight"'))
525+ >>> anon_browser.contents.count('<tr class="highlight"')
526 1
527
528 If the context is a distribution package, the package name has a
529diff --git a/lib/lp/bugs/stories/bugs/xx-bug-obfuscation.txt b/lib/lp/bugs/stories/bugs/xx-bug-obfuscation.txt
530index a7dc948..7864052 100644
531--- a/lib/lp/bugs/stories/bugs/xx-bug-obfuscation.txt
532+++ b/lib/lp/bugs/stories/bugs/xx-bug-obfuscation.txt
533@@ -29,7 +29,7 @@ An anonymous cannot see the email address anywhere in the page.
534 >>> print(anon_browser.title)
535 Bug #3 ...
536
537- >>> six.ensure_str('user@domain.org') in anon_browser.contents
538+ >>> 'user@domain.org' in anon_browser.contents
539 False
540
541 >>> description = find_tag_by_id(
542diff --git a/lib/lp/bugs/stories/bugs/xx-bug-text-pages.txt b/lib/lp/bugs/stories/bugs/xx-bug-text-pages.txt
543index f4e5a39..f25404c 100644
544--- a/lib/lp/bugs/stories/bugs/xx-bug-text-pages.txt
545+++ b/lib/lp/bugs/stories/bugs/xx-bug-text-pages.txt
546@@ -127,7 +127,7 @@ are replaced by a single space.
547
548 >>> attachments_text = text_bug[text_bug.find('attachments:'):]
549 >>> attachment_2 = attachments_text.split('\n')[2]
550- >>> six.ensure_str(attachment_2)
551+ >>> attachment_2
552 ' http://bugs.launchpad.test/.../file%20with%20space.txt text/plain;
553 name="file with space.txt"'
554
555diff --git a/lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt b/lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt
556index 2488478..d86a58d 100644
557--- a/lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt
558+++ b/lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt
559@@ -10,9 +10,8 @@ After a bug watch is recorded, it is possible to go back and change it.
560 >>> admin_browser.getControl('Change').click()
561 >>> admin_browser.url
562 'http://bugs.launchpad.test/firefox/+bug/1'
563- >>> six.ensure_str(
564- ... 'https://bugzilla.mozilla.org/show_bug.cgi?id=1000') in (
565- ... admin_browser.contents)
566+ >>> 'https://bugzilla.mozilla.org/show_bug.cgi?id=1000' in (
567+ ... admin_browser.contents)
568 True
569
570 The URL supplied must be a valid bug tracker URL and must point to a
571diff --git a/lib/lp/code/browser/tests/test_codereviewcomment.py b/lib/lp/code/browser/tests/test_codereviewcomment.py
572index 458f67a..ac402fe 100644
573--- a/lib/lp/code/browser/tests/test_codereviewcomment.py
574+++ b/lib/lp/code/browser/tests/test_codereviewcomment.py
575@@ -207,7 +207,7 @@ class TestCodeReviewCommentHtmlMixin:
576 contents = 'test-comment'
577 comment = self.makeCodeReviewComment(body=contents)
578 browser = self.getViewBrowser(comment, view_name='+reply')
579- self.assertIn(six.ensure_str(contents), browser.contents)
580+ self.assertIn(contents, browser.contents)
581
582 def test_footer_for_mergeable_and_admin(self):
583 """An admin sees Hide/Reply links for a comment on a mergeable MP."""
584diff --git a/lib/lp/code/model/branch.py b/lib/lp/code/model/branch.py
585index 98952be..f86f754 100644
586--- a/lib/lp/code/model/branch.py
587+++ b/lib/lp/code/model/branch.py
588@@ -743,7 +743,7 @@ class Branch(SQLBase, WebhookTargetMixin, BzrIdentityMixin):
589
590 def getInternalBzrUrl(self):
591 """See `IBranch`."""
592- return six.ensure_str('lp-internal:///' + self.unique_name)
593+ return 'lp-internal:///' + self.unique_name
594
595 def getBzrBranch(self):
596 """See `IBranch`."""
597diff --git a/lib/lp/coop/answersbugs/visibility.py b/lib/lp/coop/answersbugs/visibility.py
598index b167ef2..cbb3815 100644
599--- a/lib/lp/coop/answersbugs/visibility.py
600+++ b/lib/lp/coop/answersbugs/visibility.py
601@@ -8,8 +8,6 @@ __all__ = [
602 'TestMessageVisibilityMixin',
603 ]
604
605-import six
606-
607 from lp.services.webapp.escaping import html_escape
608 from lp.testing.pages import find_tag_by_id
609
610@@ -17,7 +15,7 @@ from lp.testing.pages import find_tag_by_id
611 class TestMessageVisibilityMixin:
612
613 comment_text = "You can't see me."
614- html_comment_text = six.ensure_str(html_escape(comment_text))
615+ html_comment_text = html_escape(comment_text)
616
617 def makeHiddenMessage(self):
618 """To be overwridden by subclasses.
619diff --git a/lib/lp/registry/browser/tests/person-admin-views.txt b/lib/lp/registry/browser/tests/person-admin-views.txt
620index 9e4d33d..34d0d8f 100644
621--- a/lib/lp/registry/browser/tests/person-admin-views.txt
622+++ b/lib/lp/registry/browser/tests/person-admin-views.txt
623@@ -129,7 +129,7 @@ an account is suspended, the preferred email address is disabled.
624 >>> transaction.commit()
625 >>> user.account_status
626 <DBItem AccountStatus.SUSPENDED, ...>
627- >>> six.ensure_str(user.account_status_history)
628+ >>> user.account_status_history
629 '... name16: Active -> Suspended: Wanted by the galactic police.\n'
630 >>> print(user.preferredemail)
631 None
632@@ -161,7 +161,7 @@ user must log in to restore the email addresses using the reactivate step.
633 []
634 >>> user.account_status
635 <DBItem AccountStatus.DEACTIVATED, ...>
636- >>> six.ensure_str(user.account_status_history)
637+ >>> user.account_status_history
638 "... name16: Active -> Suspended: Wanted by the galactic police.\n...
639 name16: Suspended -> Deactivated: Zaphod's a hoopy frood.\n"
640 >>> print(user.preferredemail)
641@@ -180,7 +180,7 @@ An admin can mark an account as belonging to a user who has died.
642 []
643 >>> user.account_status
644 <DBItem AccountStatus.DECEASED, ...>
645- >>> six.ensure_str(user.account_status_history)
646+ >>> user.account_status_history
647 "... name16: Active -> Suspended: Wanted by the galactic police.\n...
648 name16: Suspended -> Deactivated: Zaphod's a hoopy frood.\n...
649 name16: Deactivated -> Deceased: In memoriam.\n"
650diff --git a/lib/lp/registry/browser/tests/test_announcements.py b/lib/lp/registry/browser/tests/test_announcements.py
651index 5f005c6..af459b4 100644
652--- a/lib/lp/registry/browser/tests/test_announcements.py
653+++ b/lib/lp/registry/browser/tests/test_announcements.py
654@@ -7,7 +7,6 @@ from datetime import datetime
655
656 from lxml import html
657 from pytz import utc
658-import six
659 from zope.component import getUtility
660 from zope.security.proxy import removeSecurityProxy
661
662@@ -107,7 +106,7 @@ class TestAnnouncementPage(BrowserTestCase):
663 removeSecurityProxy(inactive_product).active = False
664
665 browser = self.getViewBrowser(context, view_name, user=user)
666- contents = six.ensure_str(browser.contents, "utf-8")
667+ contents = browser.contents
668
669 self.assertIn(first_announcement.title, contents)
670 self.assertIn(first_announcement.summary, contents)
671diff --git a/lib/lp/registry/doc/person-account.txt b/lib/lp/registry/doc/person-account.txt
672index 576ab7d..0ed70c6 100644
673--- a/lib/lp/registry/doc/person-account.txt
674+++ b/lib/lp/registry/doc/person-account.txt
675@@ -49,7 +49,7 @@ Matsubara can.
676 True
677 >>> matsubara.account.status
678 <DBItem AccountStatus.ACTIVE, ...>
679- >>> six.ensure_str(removeSecurityProxy(matsubara.account).status_history)
680+ >>> removeSecurityProxy(matsubara.account).status_history
681 '...: Unactivated -> Active: test\n'
682 >>> print(removeSecurityProxy(matsubara.preferredemail).email)
683 matsubara@async.com.br
684@@ -156,7 +156,7 @@ adds a '-deactivatedaccount' suffix to the person's name...
685 >>> foobar.account.status
686 <DBItem AccountStatus.DEACTIVATED...
687
688- >>> six.ensure_str(removeSecurityProxy(foobar.account).status_history)
689+ >>> removeSecurityProxy(foobar.account).status_history
690 "... name16: Active -> Deactivated:
691 I'm a person who doesn't want to be listed as a Launchpad user.\n"
692
693@@ -232,7 +232,7 @@ Accounts can be reactivated.
694 >>> foobar.account.status
695 <DBItem AccountStatus.ACTIVE...
696
697- >>> six.ensure_str(removeSecurityProxy(foobar.account).status_history)
698+ >>> removeSecurityProxy(foobar.account).status_history
699 "... name16: Active -> Deactivated: I'm a person
700 who doesn't want to be listed as a Launchpad user.\n...:
701 Deactivated -> Active:
702diff --git a/lib/lp/registry/scripts/tests/test_closeaccount.py b/lib/lp/registry/scripts/tests/test_closeaccount.py
703index ada1dd5..66277ea 100644
704--- a/lib/lp/registry/scripts/tests/test_closeaccount.py
705+++ b/lib/lp/registry/scripts/tests/test_closeaccount.py
706@@ -3,7 +3,6 @@
707
708 """Test the close-account script."""
709
710-import six
711 from storm.store import Store
712 from testtools.matchers import (
713 MatchesSetwise,
714@@ -178,7 +177,7 @@ class TestCloseAccount(TestCaseWithFactory):
715 person_id = person.id
716 account_id = person.account.id
717 self.factory.makeProduct(owner=person)
718- script = self.makeScript([six.ensure_str(person.name)])
719+ script = self.makeScript([person.name])
720 with dbuser('launchpad'):
721 self.assertRaisesWithContent(
722 LaunchpadScriptFailure,
723@@ -192,7 +191,7 @@ class TestCloseAccount(TestCaseWithFactory):
724
725 def test_dry_run(self):
726 person, person_id, account_id = self.makePopulatedUser()
727- script = self.makeScript(['--dry-run', six.ensure_str(person.name)])
728+ script = self.makeScript(['--dry-run', person.name])
729 with dbuser('launchpad'):
730 self.runScript(script)
731 self.assertIn(
732@@ -201,14 +200,14 @@ class TestCloseAccount(TestCaseWithFactory):
733
734 def test_single_by_name(self):
735 person, person_id, account_id = self.makePopulatedUser()
736- script = self.makeScript([six.ensure_str(person.name)])
737+ script = self.makeScript([person.name])
738 with dbuser('launchpad'):
739 self.runScript(script)
740 self.assertRemoved(account_id, person_id)
741
742 def test_single_by_email(self):
743 person, person_id, account_id = self.makePopulatedUser()
744- script = self.makeScript([six.ensure_str(person.preferredemail.email)])
745+ script = self.makeScript([person.preferredemail.email])
746 with dbuser('launchpad'):
747 self.runScript(script)
748 self.assertRemoved(account_id, person_id)
749@@ -227,7 +226,7 @@ class TestCloseAccount(TestCaseWithFactory):
750 def test_multiple_email_addresses(self):
751 person, person_id, account_id = self.makePopulatedUser()
752 self.factory.makeEmail('%s@another-domain.test' % person.name, person)
753- script = self.makeScript([six.ensure_str(person.name)])
754+ script = self.makeScript([person.name])
755 with dbuser('launchpad'):
756 self.runScript(script)
757 self.assertRemoved(account_id, person_id)
758@@ -251,7 +250,7 @@ class TestCloseAccount(TestCaseWithFactory):
759 snap = self.factory.makeSnap()
760 snap_build = self.factory.makeSnapBuild(requester=person, snap=snap)
761 specification = self.factory.makeSpecification(drafter=person)
762- script = self.makeScript([six.ensure_str(person.name)])
763+ script = self.makeScript([person.name])
764 with dbuser('launchpad'):
765 self.runScript(script)
766 self.assertRemoved(account_id, person_id)
767@@ -271,7 +270,7 @@ class TestCloseAccount(TestCaseWithFactory):
768 question.addComment(person, "comment")
769 removeSecurityProxy(question).status = status
770 questions.append(question)
771- script = self.makeScript([six.ensure_str(person.name)])
772+ script = self.makeScript([person.name])
773 with dbuser('launchpad'):
774 self.runScript(script)
775 self.assertRemoved(account_id, person_id)
776@@ -293,7 +292,7 @@ class TestCloseAccount(TestCaseWithFactory):
777 question.addComment(person, "comment")
778 removeSecurityProxy(question).status = status
779 questions[status] = question
780- script = self.makeScript([six.ensure_str(person.name)])
781+ script = self.makeScript([person.name])
782 with dbuser('launchpad'):
783 self.runScript(script)
784 self.assertRemoved(account_id, person_id)
785@@ -308,7 +307,7 @@ class TestCloseAccount(TestCaseWithFactory):
786 spec = self.factory.makeSpecification()
787 branch = self.factory.makeAnyBranch()
788 spec.linkBranch(branch, person)
789- script = self.makeScript([six.ensure_str(person.name)])
790+ script = self.makeScript([person.name])
791 with dbuser('launchpad'):
792 self.runScript(script)
793 self.assertRemoved(account_id, person_id)
794@@ -331,7 +330,7 @@ class TestCloseAccount(TestCaseWithFactory):
795 while not job.isDone():
796 job(chunk_size=100)
797 self.assertTrue(person.hasMaintainedPackages())
798- script = self.makeScript([six.ensure_str(person.name)])
799+ script = self.makeScript([person.name])
800 with dbuser('launchpad'):
801 self.runScript(script)
802 self.assertRemoved(account_id, person_id)
803@@ -345,7 +344,7 @@ class TestCloseAccount(TestCaseWithFactory):
804 bugtask = self.factory.makeBugTask(bug=bug, owner=person)
805 person_id = person.id
806 account_id = person.account.id
807- script = self.makeScript([six.ensure_str(person.name)])
808+ script = self.makeScript([person.name])
809 with dbuser('launchpad'):
810 self.runScript(script)
811 self.assertRemoved(account_id, person_id)
812@@ -358,7 +357,7 @@ class TestCloseAccount(TestCaseWithFactory):
813 self.factory.makeBugWatch(owner=person)
814 person_id = person.id
815 account_id = person.account.id
816- script = self.makeScript([six.ensure_str(person.name)])
817+ script = self.makeScript([person.name])
818 with dbuser('launchpad'):
819 self.runScript(script)
820 self.assertRemoved(account_id, person_id)
821@@ -370,7 +369,7 @@ class TestCloseAccount(TestCaseWithFactory):
822 self.assertTrue(bug.isUserAffected(person))
823 person_id = person.id
824 account_id = person.account.id
825- script = self.makeScript([six.ensure_str(person.name)])
826+ script = self.makeScript([person.name])
827 with dbuser('launchpad'):
828 self.runScript(script)
829 self.assertRemoved(account_id, person_id)
830@@ -382,7 +381,7 @@ class TestCloseAccount(TestCaseWithFactory):
831 translations_person.translations_relicensing_agreement = True
832 person_id = person.id
833 account_id = person.account.id
834- script = self.makeScript([six.ensure_str(person.name)])
835+ script = self.makeScript([person.name])
836 with dbuser('launchpad'):
837 self.runScript(script)
838 self.assertRemoved(account_id, person_id)
839@@ -399,7 +398,7 @@ class TestCloseAccount(TestCaseWithFactory):
840 person, pofile))
841 person_id = person.id
842 account_id = person.account.id
843- script = self.makeScript([six.ensure_str(person.name)])
844+ script = self.makeScript([person.name])
845 with dbuser('launchpad'):
846 self.runScript(script)
847 self.assertRemoved(account_id, person_id)
848@@ -413,7 +412,7 @@ class TestCloseAccount(TestCaseWithFactory):
849 pofile.owner = person
850 person_id = person.id
851 account_id = person.account.id
852- script = self.makeScript([six.ensure_str(person.name)])
853+ script = self.makeScript([person.name])
854 with dbuser('launchpad'):
855 self.runScript(script)
856 self.assertRemoved(account_id, person_id)
857@@ -429,7 +428,7 @@ class TestCloseAccount(TestCaseWithFactory):
858 self.assertIsNotNone(ppa.getAuthToken(person))
859 person_id = person.id
860 account_id = person.account.id
861- script = self.makeScript([six.ensure_str(person.name)])
862+ script = self.makeScript([person.name])
863 with dbuser('launchpad'):
864 now = get_transaction_timestamp(Store.of(person))
865 self.runScript(script)
866@@ -557,7 +556,7 @@ class TestCloseAccount(TestCaseWithFactory):
867 submission_ids[0], get_submission_by_submission_key(keys[0]))
868 person_id = person.id
869 account_id = person.account.id
870- script = self.makeScript([six.ensure_str(person.name)])
871+ script = self.makeScript([person.name])
872 with dbuser('launchpad'):
873 self.runScript(script)
874 self.assertRemoved(account_id, person_id)
875@@ -584,7 +583,7 @@ class TestCloseAccount(TestCaseWithFactory):
876 MatchesStructure.byEquality(count=1, viewed_by=other_person)))
877 person_id = person.id
878 account_id = person.account.id
879- script = self.makeScript([six.ensure_str(person.name)])
880+ script = self.makeScript([person.name])
881 with dbuser('launchpad'):
882 self.runScript(script)
883 self.assertRemoved(account_id, person_id)
884@@ -620,7 +619,7 @@ class TestCloseAccount(TestCaseWithFactory):
885 MatchesStructure.byEquality(owner=other_person)))
886 person_id = person.id
887 account_id = person.account.id
888- script = self.makeScript([six.ensure_str(person.name)])
889+ script = self.makeScript([person.name])
890 with dbuser('launchpad'):
891 self.runScript(script)
892 self.assertRemoved(account_id, person_id)
893@@ -634,7 +633,7 @@ class TestCloseAccount(TestCaseWithFactory):
894 product.active = False
895 person_id = person.id
896 account_id = person.account.id
897- script = self.makeScript([six.ensure_str(person.name)])
898+ script = self.makeScript([person.name])
899 with dbuser('launchpad'):
900 self.runScript(script)
901 self.assertRemoved(account_id, person_id)
902@@ -652,7 +651,7 @@ class TestCloseAccount(TestCaseWithFactory):
903 TargetRevisionControlSystems.GIT)]
904 person_id = person.id
905 account_id = person.account.id
906- script = self.makeScript([six.ensure_str(person.name)])
907+ script = self.makeScript([person.name])
908 with dbuser('launchpad'):
909 self.runScript(script)
910 self.assertRemoved(account_id, person_id)
911@@ -680,7 +679,7 @@ class TestCloseAccount(TestCaseWithFactory):
912 result_status=CodeImportResultStatus.SUCCESS)
913 person_id = person.id
914 account_id = person.account.id
915- script = self.makeScript([six.ensure_str(person.name)])
916+ script = self.makeScript([person.name])
917 with dbuser('launchpad'):
918 self.runScript(script)
919 self.assertRemoved(account_id, person_id)
920@@ -708,7 +707,7 @@ class TestCloseAccount(TestCaseWithFactory):
921 removeSecurityProxy(ppa).owner = other_person
922 person_id = person.id
923 account_id = person.account.id
924- script = self.makeScript([six.ensure_str(person.name)])
925+ script = self.makeScript([person.name])
926 with dbuser('launchpad'):
927 self.runScript(script)
928 self.assertRemoved(account_id, person_id)
929@@ -719,7 +718,7 @@ class TestCloseAccount(TestCaseWithFactory):
930 person_id = person.id
931 account_id = person.account.id
932 specification = self.factory.makeSpecification(owner=person)
933- script = self.makeScript([six.ensure_str(person.name)])
934+ script = self.makeScript([person.name])
935 with dbuser('launchpad'):
936 self.runScript(script)
937 self.assertRemoved(account_id, person_id)
938@@ -738,7 +737,7 @@ class TestCloseAccount(TestCaseWithFactory):
939
940 person_id = member.id
941 account_id = member.account.id
942- script = self.makeScript([six.ensure_str(member.name)])
943+ script = self.makeScript([member.name])
944 with dbuser('launchpad'):
945 self.runScript(script)
946 self.assertRemoved(account_id, person_id)
947@@ -751,7 +750,7 @@ class TestCloseAccount(TestCaseWithFactory):
948 owned_team2 = self.factory.makeTeam(name='target2', owner=person)
949 person_id = person.id
950 account_id = person.account.id
951- script = self.makeScript([six.ensure_str(person.name)])
952+ script = self.makeScript([person.name])
953
954 # Closing account fails as the user still owns team2
955 with dbuser('launchpad'):
956@@ -776,7 +775,7 @@ class TestCloseAccount(TestCaseWithFactory):
957 self.assertEqual(token, login_token_set[plaintext_token])
958 person_id = person.id
959 account_id = person.account.id
960- script = self.makeScript([six.ensure_str(person.name)])
961+ script = self.makeScript([person.name])
962 with dbuser('launchpad'):
963 self.runScript(script)
964 self.assertRemoved(account_id, person_id)
965@@ -794,7 +793,7 @@ class TestCloseAccount(TestCaseWithFactory):
966 [other_request_token], other_person.oauth_request_tokens)
967 person_id = person.id
968 account_id = person.account.id
969- script = self.makeScript([six.ensure_str(person.name)])
970+ script = self.makeScript([person.name])
971 with dbuser('launchpad'):
972 self.runScript(script)
973 self.assertRemoved(account_id, person_id)
974@@ -813,7 +812,7 @@ class TestCloseAccount(TestCaseWithFactory):
975 [other_access_token], other_person.oauth_access_tokens)
976 person_id = person.id
977 account_id = person.account.id
978- script = self.makeScript([six.ensure_str(person.name)])
979+ script = self.makeScript([person.name])
980 with dbuser('launchpad'):
981 self.runScript(script)
982 self.assertRemoved(account_id, person_id)
983@@ -828,7 +827,7 @@ class TestCloseAccount(TestCaseWithFactory):
984 ppa.setProcessors(procs)
985 person_id = person.id
986 account_id = person.account.id
987- script = self.makeScript([six.ensure_str(person.name)])
988+ script = self.makeScript([person.name])
989 with dbuser('launchpad'):
990 self.assertRaisesWithContent(
991 LaunchpadScriptFailure,
992@@ -851,7 +850,7 @@ class TestCloseAccount(TestCaseWithFactory):
993 DevNullLogger(), getPubConfig(ppa), None, ppa).deleteArchive()
994 person_id = person.id
995 account_id = person.account.id
996- script = self.makeScript([six.ensure_str(person.name)])
997+ script = self.makeScript([person.name])
998 with dbuser('launchpad'):
999 self.assertRaisesWithContent(
1000 LaunchpadScriptFailure,
1001@@ -873,7 +872,7 @@ class TestCloseAccount(TestCaseWithFactory):
1002 store = Store.of(ppa)
1003 person_id = person.id
1004 account_id = person.account.id
1005- script = self.makeScript([six.ensure_str(person.name)])
1006+ script = self.makeScript([person.name])
1007 with dbuser('launchpad'):
1008 self.runScript(script)
1009 self.assertRemoved(account_id, person_id)
1010diff --git a/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt b/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
1011index 1b81c27..d9c465e 100644
1012--- a/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
1013+++ b/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
1014@@ -111,7 +111,7 @@ Import the secret keys needed for this test:
1015 access the current IGpghandler instance to access this key and decrypt the
1016 message.
1017
1018- >>> body = decrypt_content(cipher_body, six.ensure_str('test'))
1019+ >>> body = decrypt_content(cipher_body, 'test')
1020
1021 Extract the token URL from the email:
1022
1023@@ -514,7 +514,7 @@ Get the token from the body of the email sent.
1024 >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
1025 >>> msg = email.message_from_bytes(raw_msg)
1026 >>> cipher_body = msg.get_payload(decode=1)
1027- >>> body = decrypt_content(cipher_body, six.ensure_str('test'))
1028+ >>> body = decrypt_content(cipher_body, 'test')
1029 >>> link = get_token_url_from_bytes(body)
1030 >>> token = re.sub(r'.*token/', '', link)
1031 >>> token_url = 'http://launchpad.test/token/%s' % token
1032diff --git a/lib/lp/services/database/doc/enumcol.txt b/lib/lp/services/database/doc/enumcol.txt
1033index 4685182..9cb728b 100644
1034--- a/lib/lp/services/database/doc/enumcol.txt
1035+++ b/lib/lp/services/database/doc/enumcol.txt
1036@@ -85,7 +85,7 @@ You cannot use integers or strings as DBEnum values:
1037 ...
1038 TypeError: Not a DBItem: 2
1039
1040- >>> t.foo = six.ensure_str("TWO")
1041+ >>> t.foo = "TWO"
1042 Traceback (most recent call last):
1043 ...
1044 TypeError: Not a DBItem: 'TWO'
1045diff --git a/lib/lp/services/database/doc/textsearching.txt b/lib/lp/services/database/doc/textsearching.txt
1046index 6aa25a7..5ced23b 100644
1047--- a/lib/lp/services/database/doc/textsearching.txt
1048+++ b/lib/lp/services/database/doc/textsearching.txt
1049@@ -121,7 +121,7 @@ The following examples show the text version of the query using
1050 ... "SELECT to_tsvector(%s) @@ ftq(%s)",
1051 ... (text_to_search, search_phrase))
1052 ... match = result.get_all()[0][0]
1053- ... return six.ensure_str("FTI data: %s query: %s match: %s") % (
1054+ ... return "FTI data: %s query: %s match: %s" % (
1055 ... ts_vector, ts_query, str(match))
1056 >>>
1057 >>> def search_same(text):
1058@@ -248,7 +248,7 @@ Punctuation is handled consistently. If a string containing punctuation
1059 appears in an FTI, it can also be passed to ftq(),and a search for this
1060 string finds the indexed text.
1061
1062- >>> punctuation = six.ensure_str('\'"#$%*+,./:;<=>?@[\]^`{}~')
1063+ >>> punctuation = '\'"#$%*+,./:;<=>?@[\]^`{}~'
1064 >>> for symbol in punctuation:
1065 ... print(repr(symbol), search_same('foo%sbar' % symbol))
1066 "'" FTI data: 'bar':2 'foo':1 query: 'foo' & 'bar' match: True
1067diff --git a/lib/lp/services/doc/limitedlist.txt b/lib/lp/services/doc/limitedlist.txt
1068index e8bdf08..10f1fed 100644
1069--- a/lib/lp/services/doc/limitedlist.txt
1070+++ b/lib/lp/services/doc/limitedlist.txt
1071@@ -22,7 +22,7 @@ We can optionally specify the initial content of the sequence. Note that
1072 only the last N elements of the second parameter are stored, where N is
1073 the given maximum size of the LimitedList.
1074
1075- >>> LimitedList(3, (0, six.ensure_str('one'), 2, 3))
1076+ >>> LimitedList(3, (0, 'one', 2, 3))
1077 <LimitedList(3, ['one', 2, 3])>
1078
1079 If the initial content has more elements than the given maximum length,
1080diff --git a/lib/lp/services/gpg/doc/gpg-encryption.txt b/lib/lp/services/gpg/doc/gpg-encryption.txt
1081index b1a1b0c..21da208 100644
1082--- a/lib/lp/services/gpg/doc/gpg-encryption.txt
1083+++ b/lib/lp/services/gpg/doc/gpg-encryption.txt
1084@@ -57,7 +57,7 @@ cipher constains the encrypted content.
1085 Storing the raw password may compromise the security, but is the
1086 only way we can decrypt the cipher content.
1087
1088- >>> password = six.ensure_str('test')
1089+ >>> password = 'test'
1090 >>> plain = decrypt_content(cipher, password)
1091
1092 voilá, the same content shows up again.
1093@@ -69,7 +69,7 @@ Verify if the encrytion process support passing another charset string
1094
1095 >>> content = u'a\xe7ucar'
1096 >>> cipher = gpghandler.encryptContent(content.encode('iso-8859-1'), key)
1097- >>> plain = decrypt_content(cipher, six.ensure_str('test'))
1098+ >>> plain = decrypt_content(cipher, 'test')
1099 >>> print(backslashreplace(plain.decode('iso-8859-1')))
1100 a\xe7ucar
1101
1102@@ -85,7 +85,7 @@ Decrypt a unicode content:
1103 >>> content = u'a\xe7ucar'
1104 >>> cipher = gpghandler.encryptContent(content.encode('iso-8859-1'), key)
1105 >>> cipher = six.ensure_text(cipher)
1106- >>> plain = decrypt_content(cipher, six.ensure_str('test'))
1107+ >>> plain = decrypt_content(cipher, 'test')
1108 Traceback (most recent call last):
1109 ...
1110 TypeError: Content must be bytes.
1111@@ -113,7 +113,7 @@ What about a message encrypted for an unknown key.
1112 ... =LQK5
1113 ... -----END PGP MESSAGE-----
1114 ... """
1115- >>> plain = decrypt_content(cipher, six.ensure_str('test'))
1116+ >>> plain = decrypt_content(cipher, 'test')
1117 >>> plain is None
1118 True
1119
1120diff --git a/lib/lp/services/gpg/handler.py b/lib/lp/services/gpg/handler.py
1121index bad85f1..005ca79 100644
1122--- a/lib/lp/services/gpg/handler.py
1123+++ b/lib/lp/services/gpg/handler.py
1124@@ -341,8 +341,7 @@ class GPGHandler:
1125 # See more information at:
1126 # http://pyme.sourceforge.net/doc/gpgme/Generating-Keys.html
1127 with gpgme_timeline("genkey", name):
1128- result = context.genkey(
1129- six.ensure_str(signing_only_param % {'name': name}))
1130+ result = context.genkey(signing_only_param % {'name': name})
1131
1132 # Right, it might seem paranoid to have this many assertions,
1133 # but we have to take key generation very seriously.
1134diff --git a/lib/lp/services/gpg/tests/test_gpghandler.py b/lib/lp/services/gpg/tests/test_gpghandler.py
1135index 6dba52c..4072646 100644
1136--- a/lib/lp/services/gpg/tests/test_gpghandler.py
1137+++ b/lib/lp/services/gpg/tests/test_gpghandler.py
1138@@ -77,9 +77,9 @@ class FakeGenerateKey(Fixture):
1139 self.secret_key)
1140
1141 # Fail if the key generation parameters aren't what we expect.
1142- expected_params = six.ensure_str(signing_only_param % {
1143+ expected_params = signing_only_param % {
1144 "name": imported_key.uids[0].name,
1145- })
1146+ }
1147 if params != expected_params:
1148 raise ValueError(
1149 "Got params %r, expected %r" % (params, expected_params))
1150diff --git a/lib/lp/services/librarian/model.py b/lib/lp/services/librarian/model.py
1151index 10a387e..6b0ea19 100644
1152--- a/lib/lp/services/librarian/model.py
1153+++ b/lib/lp/services/librarian/model.py
1154@@ -15,7 +15,6 @@ import hashlib
1155
1156 from lazr.delegates import delegate_to
1157 import pytz
1158-import six
1159 from six.moves.urllib.parse import urlparse
1160 from storm.locals import (
1161 Date,
1162@@ -358,7 +357,7 @@ class TimeLimitedToken(StormBase):
1163 # allocation the external librarian must be able to serve the file
1164 # immediately.
1165 store.commit()
1166- return six.ensure_str(token)
1167+ return token
1168
1169 @staticmethod
1170 def url_to_token_path(url):
1171diff --git a/lib/lp/services/mail/doc/notification-recipient-set.txt b/lib/lp/services/mail/doc/notification-recipient-set.txt
1172index d06e7c4..6ed6b2c 100644
1173--- a/lib/lp/services/mail/doc/notification-recipient-set.txt
1174+++ b/lib/lp/services/mail/doc/notification-recipient-set.txt
1175@@ -120,7 +120,7 @@ UnknownRecipientError:
1176 ...
1177 lp.services.mail.interfaces.UnknownRecipientError: ...
1178
1179- >>> recipients.getReason(six.ensure_str('no-priv@canonical.com'))
1180+ >>> recipients.getReason('no-priv@canonical.com')
1181 Traceback (most recent call last):
1182 ...
1183 lp.services.mail.interfaces.UnknownRecipientError: 'no-priv@canonical.com'
1184diff --git a/lib/lp/services/webapp/breadcrumb.py b/lib/lp/services/webapp/breadcrumb.py
1185index 1281fe2..eae2074 100644
1186--- a/lib/lp/services/webapp/breadcrumb.py
1187+++ b/lib/lp/services/webapp/breadcrumb.py
1188@@ -10,7 +10,6 @@ __all__ = [
1189 'TitleBreadcrumb',
1190 ]
1191
1192-import six
1193 from zope.interface import implementer
1194
1195 from lp.services.webapp import canonical_url
1196@@ -77,12 +76,8 @@ class Breadcrumb:
1197 return self._detail or self.text
1198
1199 def __repr__(self):
1200- # XXX: salgado, 2009-10-14, http://bugs.python.org/issue5876: In
1201- # python 2.5-2.7, the return value of __repr__() may be forced into a
1202- # type(str), so we can't include unicode here.
1203- text = six.ensure_str(self.text, 'raw-unicode-escape')
1204 return "<%s url='%s' text='%s'>" % (
1205- self.__class__.__name__, self.url, text)
1206+ self.__class__.__name__, self.url, self.text)
1207
1208
1209 class NameBreadcrumb(Breadcrumb):
1210diff --git a/lib/lp/services/webapp/doc/canonical_url.txt b/lib/lp/services/webapp/doc/canonical_url.txt
1211index 90d4df5..60f824a 100644
1212--- a/lib/lp/services/webapp/doc/canonical_url.txt
1213+++ b/lib/lp/services/webapp/doc/canonical_url.txt
1214@@ -18,8 +18,7 @@ will put in a temporary module.
1215 >>> from lp.services.webapp.interfaces import ICanonicalUrlData
1216 >>> from zope.interface import Interface, Attribute, implementer
1217
1218- >>> module = types.ModuleType(
1219- ... six.ensure_str(factory.getUniqueString().replace('-', '_')))
1220+ >>> module = types.ModuleType(factory.getUniqueString().replace('-', '_'))
1221 >>> sys.modules[module.__name__] = module
1222
1223 >>> class ICountrySet(Interface):
1224diff --git a/lib/lp/services/webapp/doc/menus.txt b/lib/lp/services/webapp/doc/menus.txt
1225index c1cf9b4..7f910c8 100644
1226--- a/lib/lp/services/webapp/doc/menus.txt
1227+++ b/lib/lp/services/webapp/doc/menus.txt
1228@@ -561,8 +561,7 @@ First, we define a couple of interfaces, and put them in a temporary module.
1229 >>> import sys
1230 >>> import types
1231
1232- >>> module = types.ModuleType(
1233- ... six.ensure_str(factory.getUniqueString().replace('-', '_')))
1234+ >>> module = types.ModuleType(factory.getUniqueString().replace('-', '_'))
1235 >>> sys.modules[module.__name__] = module
1236
1237 >>> class IThingHavingFacets(Interface):
1238diff --git a/lib/lp/services/webapp/doc/test_adapter.txt b/lib/lp/services/webapp/doc/test_adapter.txt
1239index abe5036..04378eb 100644
1240--- a/lib/lp/services/webapp/doc/test_adapter.txt
1241+++ b/lib/lp/services/webapp/doc/test_adapter.txt
1242@@ -211,7 +211,7 @@ timeout by sleeping for 200ms with a 100ms statement timeout:
1243 >>> set_request_started()
1244 >>> print(current_statement_timeout(store))
1245 100ms
1246- >>> store.execute(six.ensure_str('SELECT pg_sleep(0.200)'), noresult=True)
1247+ >>> store.execute('SELECT pg_sleep(0.200)', noresult=True)
1248 Traceback (most recent call last):
1249 ...
1250 lp.services.webapp.adapter.LaunchpadTimeoutError:
1251@@ -285,7 +285,7 @@ issuing the SQL command as we have exceeded the precision period:
1252 This final invokation, we will actually sleep to ensure that the
1253 timeout being reported by PostgreSQL is actually working:
1254
1255- >>> store.execute(six.ensure_str('SELECT pg_sleep(0.2)'), noresult=True)
1256+ >>> store.execute('SELECT pg_sleep(0.2)', noresult=True)
1257 Traceback (most recent call last):
1258 ...
1259 lp.services.webapp.adapter.LaunchpadTimeoutError:
1260diff --git a/lib/lp/services/webapp/publication.py b/lib/lp/services/webapp/publication.py
1261index 80effc1..37cd383 100644
1262--- a/lib/lp/services/webapp/publication.py
1263+++ b/lib/lp/services/webapp/publication.py
1264@@ -17,7 +17,6 @@ from lazr.uri import (
1265 URI,
1266 )
1267 from psycopg2.extensions import TransactionRollbackError
1268-import six
1269 from six.moves.urllib.parse import quote
1270 from storm.database import STATE_DISCONNECTED
1271 from storm.exceptions import (
1272@@ -422,10 +421,7 @@ class LaunchpadBrowserPublication(
1273 return self.constructPageID(context, context.context, names)
1274 view_names = ':'.join(names)
1275 pageid = '%s:%s' % (context_name, view_names)
1276- # The view name used in the pageid usually comes from ZCML and so it
1277- # will be a Unicode string, but we want a native string. On Python
1278- # 2, to avoid problems we encode it into ASCII.
1279- return six.ensure_str(pageid, 'US-ASCII')
1280+ return pageid
1281
1282 def callObject(self, request, ob):
1283 """See `zope.publisher.interfaces.IPublication`.
1284diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py
1285index c0f00aa..2f5960d 100644
1286--- a/lib/lp/services/webapp/publisher.py
1287+++ b/lib/lp/services/webapp/publisher.py
1288@@ -504,8 +504,7 @@ class LaunchpadView(UserAttributeCache):
1289 """See IBrowserPublisher."""
1290 # By default, a LaunchpadView cannot be traversed through.
1291 # Those that can be must override this method.
1292- raise NotFound(
1293- self, six.ensure_str(name, errors='replace'), request=request)
1294+ raise NotFound(self, name, request=request)
1295
1296 @property
1297 def recommended_canonical_url(self):
1298@@ -964,8 +963,7 @@ class Navigation:
1299 """
1300 # Avoid circular imports.
1301 if nextobj is None:
1302- raise NotFound(
1303- self.context, six.ensure_str(name, errors='replace'))
1304+ raise NotFound(self.context, name)
1305 elif isinstance(nextobj, redirection):
1306 return RedirectionView(
1307 nextobj.name, request, status=nextobj.status)
1308@@ -1185,7 +1183,7 @@ class RenamedView:
1309
1310 def publishTraverse(self, request, name):
1311 """See zope.publisher.interfaces.browser.IBrowserPublisher."""
1312- raise NotFound(self.context, six.ensure_str(name, errors='replace'))
1313+ raise NotFound(self.context, name)
1314
1315 def browserDefault(self, request):
1316 """See zope.publisher.interfaces.browser.IBrowserPublisher."""
1317diff --git a/lib/lp/services/webapp/servers.py b/lib/lp/services/webapp/servers.py
1318index 32ebf7f..e644e05 100644
1319--- a/lib/lp/services/webapp/servers.py
1320+++ b/lib/lp/services/webapp/servers.py
1321@@ -870,9 +870,7 @@ class LaunchpadBrowserResponse(NotificationResponse, BrowserResponse):
1322 status = 307
1323 else:
1324 status = 303
1325- super().redirect(
1326- six.ensure_str(str(location)),
1327- status=status, trusted=trusted)
1328+ super().redirect(str(location), status=status, trusted=trusted)
1329
1330
1331 def adaptResponseToSession(response):
1332diff --git a/lib/lp/services/webservice/doc/launchpadlib.txt b/lib/lp/services/webservice/doc/launchpadlib.txt
1333index 25d2e0b..20288ba 100644
1334--- a/lib/lp/services/webservice/doc/launchpadlib.txt
1335+++ b/lib/lp/services/webservice/doc/launchpadlib.txt
1336@@ -5,9 +5,7 @@ Just to show that we're actually talking to the appserver, first check to see
1337 if a specific user exists...
1338
1339 >>> browser = Browser()
1340- >>> browser.addHeader(
1341- ... 'Authorization',
1342- ... six.ensure_str('Basic foo.bar@canonical.com:test'))
1343+ >>> browser.addHeader('Authorization', 'Basic foo.bar@canonical.com:test')
1344 >>> from lp.testing.layers import BaseLayer
1345 >>> root_url = BaseLayer.appserver_root_url()
1346 >>> browser.open(root_url)
1347diff --git a/lib/lp/soyuz/scripts/gina/packages.py b/lib/lp/soyuz/scripts/gina/packages.py
1348index e8b6dae..15b4a45 100644
1349--- a/lib/lp/soyuz/scripts/gina/packages.py
1350+++ b/lib/lp/soyuz/scripts/gina/packages.py
1351@@ -110,9 +110,7 @@ def unpack_dsc(package, version, component, distro_name, archive_root):
1352 extract_dpkg_source(dsc_path, ".", vendor=distro_name)
1353 except DpkgSourceError as e:
1354 if os.path.isdir(source_dir):
1355- # Coerce to str to avoid https://bugs.python.org/issue24672 on
1356- # Python 2.
1357- shutil.rmtree(six.ensure_str(source_dir))
1358+ shutil.rmtree(source_dir)
1359 raise ExecutionError("Error %d unpacking source" % e.result)
1360
1361 return source_dir, dsc_path
1362@@ -149,9 +147,7 @@ def read_dsc(package, version, component, distro_name, archive_root):
1363 "No copyright file found for %s in %s" % (package, source_dir))
1364 copyright = b''
1365 finally:
1366- # Coerce to str to avoid https://bugs.python.org/issue24672 on
1367- # Python 2.
1368- shutil.rmtree(six.ensure_str(source_dir))
1369+ shutil.rmtree(source_dir)
1370
1371 return dsc, changelog, copyright
1372
1373diff --git a/lib/lp/soyuz/scripts/ppareport.py b/lib/lp/soyuz/scripts/ppareport.py
1374index c9e106c..e93c85a 100644
1375--- a/lib/lp/soyuz/scripts/ppareport.py
1376+++ b/lib/lp/soyuz/scripts/ppareport.py
1377@@ -15,7 +15,6 @@ import operator
1378 import os
1379 import sys
1380
1381-import six
1382 from storm.locals import Join
1383 from storm.store import Store
1384 from zope.component import getUtility
1385@@ -175,7 +174,7 @@ class PPAReportScript(LaunchpadScript):
1386 if size <= (threshold * limit):
1387 continue
1388 line = "%s | %d | %d\n" % (canonical_url(ppa), limit, size)
1389- self.output.write(six.ensure_str(line))
1390+ self.output.write(line)
1391 self.output.write('\n')
1392
1393 def reportUserEmails(self):
1394@@ -188,7 +187,7 @@ class PPAReportScript(LaunchpadScript):
1395 for user in sorted_people_to_email:
1396 line = "%s | %s | %s\n" % (
1397 user.name, user.displayname, user.preferredemail.email)
1398- self.output.write(six.ensure_str(line))
1399+ self.output.write(line)
1400 self.output.write('\n')
1401
1402 @cachedproperty
1403diff --git a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
1404index 6b1ab8c..4c49953 100644
1405--- a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
1406+++ b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
1407@@ -21,8 +21,7 @@ according to the selected buildstate, by default All.
1408 ... provide only part of the required arguments to enable filter by
1409 ... name.
1410 ... """
1411- ... assert six.ensure_str(
1412- ... '<input type="submit" value="Filter" />') in contents
1413+ ... assert '<input type="submit" value="Filter" />' in contents
1414 ...
1415 ... field_state = find_tag_by_id(contents, 'build_state') is not None
1416 ... field_name = find_tag_by_id(contents, 'build_text') is not None
1417diff --git a/lib/lp/translations/model/pomsgid.py b/lib/lp/translations/model/pomsgid.py
1418index 85bcd87..5f38c08 100644
1419--- a/lib/lp/translations/model/pomsgid.py
1420+++ b/lib/lp/translations/model/pomsgid.py
1421@@ -50,5 +50,5 @@ class POMsgID(StormBase):
1422 Func('sha1', POMsgID.msgid) ==
1423 Func('sha1', six.ensure_text(key))).one()
1424 if r is None:
1425- raise NotFoundError(six.ensure_str(key, errors='replace'))
1426+ raise NotFoundError(key)
1427 return r
1428diff --git a/lib/lp/translations/model/potranslation.py b/lib/lp/translations/model/potranslation.py
1429index b342098..9c01c45 100644
1430--- a/lib/lp/translations/model/potranslation.py
1431+++ b/lib/lp/translations/model/potranslation.py
1432@@ -51,7 +51,7 @@ class POTranslation(StormBase):
1433 if r is not None:
1434 return r
1435 else:
1436- raise NotFoundError(six.ensure_str(key, errors='replace'))
1437+ raise NotFoundError(key)
1438
1439 @classmethod
1440 def getOrCreateTranslation(cls, key):
1441diff --git a/lib/lp/translations/stories/standalone/xx-language.txt b/lib/lp/translations/stories/standalone/xx-language.txt
1442index 438f687..0476573 100644
1443--- a/lib/lp/translations/stories/standalone/xx-language.txt
1444+++ b/lib/lp/translations/stories/standalone/xx-language.txt
1445@@ -274,9 +274,8 @@ Changing values to correct content works:
1446 >>> admin_browser.getControl('ISO 639').value = 'bars'
1447 >>> admin_browser.getControl('English name').value = 'Changed field'
1448 >>> spokenin_control = admin_browser.getControl(name='field.countries')
1449- >>> spokenin_control.getControl(
1450- ... six.ensure_str('Argentina')).selected = False
1451- >>> spokenin_control.getControl(six.ensure_str('France')).selected = True
1452+ >>> spokenin_control.getControl('Argentina').selected = False
1453+ >>> spokenin_control.getControl('France').selected = True
1454 >>> admin_browser.getControl('Admin Language').click()
1455 >>> print(admin_browser.url)
1456 http://translations.launchpad.test/+languages/bars
1457diff --git a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
1458index c049b94..804cd1c 100644
1459--- a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
1460+++ b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
1461@@ -331,7 +331,7 @@ Now, we will check suggestions in this form.
1462
1463 Check that suggestions come in from other contexts:
1464
1465- >>> six.ensure_str("Suggested in") in browser.contents
1466+ >>> "Suggested in" in browser.contents
1467 True
1468
1469 >>> find_tag_by_id(browser.contents, 'msgset_143_es_suggestion_697_0')
1470@@ -340,16 +340,15 @@ Check that suggestions come in from other contexts:
1471 Check that no other suggestions are presented (since no others are
1472 relevant for this message):
1473
1474- >>> six.ensure_str("Suggested by") in browser.contents
1475+ >>> "Suggested by" in browser.contents
1476 False
1477
1478- >>> six.ensure_str("Used in") in browser.contents
1479+ >>> "Used in" in browser.contents
1480 False
1481
1482 Check for the translator note:
1483
1484- >>> note = six.ensure_str(
1485- ... "This is an example of commenttext for a multiline")
1486+ >>> note = "This is an example of commenttext for a multiline"
1487 >>> note in browser.contents
1488 True
1489
1490@@ -410,7 +409,7 @@ And submit it.
1491 Now, we check that the translation we are going to add is not yet in the
1492 form, so we can check later that it's added as a suggestion:
1493
1494- >>> six.ensure_str('foo!!') in fast_submission.contents
1495+ >>> 'foo!!' in fast_submission.contents
1496 False
1497
1498 Now, we update the translation in slow_submission.
1499diff --git a/lib/lp/translations/stories/translations/xx-translations.txt b/lib/lp/translations/stories/translations/xx-translations.txt
1500index 9c26cb1..ee8309a 100644
1501--- a/lib/lp/translations/stories/translations/xx-translations.txt
1502+++ b/lib/lp/translations/stories/translations/xx-translations.txt
1503@@ -94,7 +94,7 @@ page, and that it has all the data we are expecting, in terms of languages.
1504 >>> from lp.testing.pages import extract_url_parameter
1505 >>> browser.open('http://translations.launchpad.test/ubuntu/hoary/'
1506 ... '+translations')
1507- >>> six.ensure_str('Translation status by language') in browser.contents
1508+ >>> 'Translation status by language' in browser.contents
1509 True
1510 >>> print(browser.getLink('Catalan').url)
1511 http://translations.launchpad.test/ubuntu/hoary/+lang/ca
1512@@ -113,7 +113,7 @@ put Afrihili into the list of "preferred languages".
1513 >>> browser.addHeader('Accept-Language', 'en-us,en;q=0.7,afh;q=0.3')
1514 >>> browser.open('http://translations.launchpad.test/ubuntu/hoary/'
1515 ... '+translations')
1516- >>> six.ensure_str('Translation status by language') in browser.contents
1517+ >>> 'Translation status by language' in browser.contents
1518 True
1519 >>> print(browser.getLink('Catalan').url)
1520 http://translations.launchpad.test/ubuntu/hoary/+lang/ca
1521@@ -130,9 +130,9 @@ pofile) for evolution-2.2
1522 >>> browser.open(
1523 ... 'http://translations.launchpad.test/ubuntu/hoary/+lang/hr'
1524 ... '?batch=2')
1525- >>> six.ensure_str('Croatian') in browser.contents
1526+ >>> 'Croatian' in browser.contents
1527 True
1528- >>> six.ensure_str('Translatable templates') in browser.contents
1529+ >>> 'Translatable templates' in browser.contents
1530 True
1531 >>> print(browser.getLink('evolution-2.2').url) # noqa
1532 http://translations.launchpad.test/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/hr/+translate
1533@@ -173,7 +173,7 @@ And finally, we will get pmount.
1534
1535 With its latest translator.
1536
1537- >>> six.ensure_str('Edgar Bursic') in browser.contents
1538+ >>> 'Edgar Bursic' in browser.contents
1539 True
1540
1541 Last translator
1542@@ -213,7 +213,7 @@ file):
1543 batch=10
1544 >>> print(extract_url_parameter(browser.url, 'show'))
1545 show=untranslated
1546- >>> six.ensure_str('10.') in browser.contents
1547+ >>> '10.' in browser.contents
1548 True
1549
1550 If everything works out ok, that means that DummyPOFile has actually
1551@@ -225,9 +225,7 @@ Finally, lets also check that translated entries show up as well.
1552 >>> browser.getControl('Change').click()
1553 >>> print(extract_url_parameter(browser.url, 'show'))
1554 show=translated
1555- >>> six.ensure_str(
1556- ... "There are no messages that match this filtering.") in (
1557- ... browser.contents)
1558+ >>> "There are no messages that match this filtering." in browser.contents
1559 True
1560
1561 Links to filtered pages
1562@@ -386,20 +384,20 @@ should see Catalan in the list.
1563 >>> browser.open(
1564 ... 'http://translations.launchpad.test/ubuntu/hoary/+source/'
1565 ... 'evolution/+translations')
1566- >>> six.ensure_str('Catalan') in browser.contents
1567+ >>> 'Catalan' in browser.contents
1568 True
1569
1570 But also, he doesn't want to see other languages in the list. So, he
1571 shouldn't see eg. Japanese.
1572
1573- >>> six.ensure_str('Japanese') in browser.contents
1574+ >>> 'Japanese' in browser.contents
1575 False
1576
1577 Next, if he chooses to view all the languages, he should see Japanese
1578 among the languages on the page.
1579
1580 >>> browser.getLink('View template & all languages...').click()
1581- >>> six.ensure_str('Japanese') in browser.contents
1582+ >>> 'Japanese' in browser.contents
1583 True
1584
1585 So, everything is fine, and Carlos can sleep calmly.
1586diff --git a/scripts/list-team-members b/scripts/list-team-members
1587index 507d590..b7a7e61 100755
1588--- a/scripts/list-team-members
1589+++ b/scripts/list-team-members
1590@@ -8,8 +8,6 @@ import _pythonpath # noqa: F401
1591 import logging
1592 import sys
1593
1594-import six
1595-
1596 from lp.registry.scripts.listteammembers import (
1597 NoSuchTeamError,
1598 process_team,
1599@@ -55,7 +53,7 @@ class ListTeamMembersScript(LaunchpadScript):
1600 except NoSuchTeamError:
1601 raise LaunchpadScriptFailure("No such team: %s" % teamname)
1602 for detail in sorted(member_details):
1603- print(six.ensure_str(detail))
1604+ print(detail)
1605
1606
1607 if __name__ == '__main__':

Subscribers

People subscribed via source and target branches

to status/vote changes: