← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:pyupgrade-py3-bugs-1 into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:pyupgrade-py3-bugs-1 into launchpad:master.

Commit message:
lp.bugs.{browser,externalbugtracker}: Apply "pyupgrade --py3-plus"

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/413079

lp.bugs is large, so I split it up a bit further.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:pyupgrade-py3-bugs-1 into launchpad:master.
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8eaaf20..3eea6c7 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -45,6 +45,7 @@ repos:
             |archivepublisher
             |archiveuploader
             |blueprints
+            |bugs/(browser|externalbugtracker)
           )/
 -   repo: https://github.com/PyCQA/isort
     rev: 5.9.2
diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py
index f4e5eea..f495e7b 100644
--- a/lib/lp/bugs/browser/bug.py
+++ b/lib/lp/bugs/browser/bug.py
@@ -40,7 +40,6 @@ from lazr.restful import (
 from lazr.restful.interface import copy_field
 from lazr.restful.interfaces import IJSONRequestCache
 from simplejson import dumps
-import six
 from zope import formlib
 from zope.component import (
     getMultiAdapter,
@@ -408,7 +407,7 @@ class MaloneView(LaunchpadFormView):
 
     def _redirectToBug(self, bug_id):
         """Redirect to the specified bug id."""
-        if not isinstance(bug_id, six.string_types):
+        if not isinstance(bug_id, str):
             self.error_message = "Bug %r is not registered." % bug_id
             return
         if bug_id.startswith("#"):
@@ -708,7 +707,7 @@ class BugWithoutContextView(RedirectionView):
         viewname = getDefaultViewName(redirected_context, request)
         cache_view = getMultiAdapter(
             (redirected_context, request), name=viewname)
-        super(BugWithoutContextView, self).__init__(
+        super().__init__(
             canonical_url(redirected_context), request, cache_view=cache_view)
 
 
@@ -764,7 +763,7 @@ class BugMarkAsDuplicateView(BugEditViewBase):
 
     def setUpFields(self):
         """Make the readonly version of duplicateof available."""
-        super(BugMarkAsDuplicateView, self).setUpFields()
+        super().setUpFields()
 
         duplicateof_field = DuplicateBug(
             __name__='duplicateof', title=_('Duplicate Of'), required=True)
@@ -786,7 +785,7 @@ class BugMarkAsDuplicateView(BugEditViewBase):
 
     def _validate(self, action, data):
         if action.name != 'remove':
-            return super(BugMarkAsDuplicateView, self)._validate(action, data)
+            return super()._validate(action, data)
         return []
 
     @action('Set Duplicate', name='change',
@@ -856,7 +855,7 @@ class BugSecrecyEditView(LaunchpadFormView, BugSubscriptionPortletDetails):
             # should be validated to ensure the bug does not become invisible
             # after the change.
             validate_change = Bool(
-                title=u"Validate change", required=False, default=False)
+                title="Validate change", required=False, default=False)
         return information_type_schema
 
     @property
@@ -997,7 +996,7 @@ class DeprecatedAssignedBugsView(RedirectionView):
     def __call__(self):
         self.target = canonical_url(
             getUtility(ILaunchBag).user, view_name='+assignedbugs')
-        super(DeprecatedAssignedBugsView, self).__call__()
+        super().__call__()
 
     @property
     def context(self):
@@ -1193,7 +1192,7 @@ class BugURL:
     @property
     def path(self):
         """Return the path component of the URL."""
-        return u"bugs/%d" % self.context.id
+        return "bugs/%d" % self.context.id
 
 
 class BugAffectingUserChoice(EnumeratedType):
diff --git a/lib/lp/bugs/browser/bugalsoaffects.py b/lib/lp/bugs/browser/bugalsoaffects.py
index 40f30f4..7372c56 100644
--- a/lib/lp/bugs/browser/bugalsoaffects.py
+++ b/lib/lp/bugs/browser/bugalsoaffects.py
@@ -14,7 +14,6 @@ from lazr.enum import (
     Item,
     )
 from lazr.lifecycle.event import ObjectCreatedEvent
-import six
 from zope.browserpage import ViewPageTemplateFile
 from zope.component import getUtility
 from zope.event import notify
@@ -126,7 +125,7 @@ class ChooseProductStep(LinkPackgingMixin, AlsoAffectsStep):
         '../templates/bugtask-choose-affected-product.pt')
 
     custom_widget_product = SearchForUpstreamPopupWidget
-    label = u"Record as affecting another project"
+    label = "Record as affecting another project"
     step_name = "choose_product"
 
     @property
@@ -138,7 +137,7 @@ class ChooseProductStep(LinkPackgingMixin, AlsoAffectsStep):
         return names
 
     def initialize(self):
-        super(ChooseProductStep, self).initialize()
+        super().initialize()
         if (self.widgets['product'].hasInput() or
             not IDistributionSourcePackage.providedBy(self.context.target)):
             return
@@ -235,12 +234,12 @@ class BugTaskCreationStep(AlsoAffectsStep):
     task_added = None
 
     def __init__(self, context, request):
-        super(BugTaskCreationStep, self).__init__(context, request)
+        super().__init__(context, request)
         self.notifications = []
         self._field_names = ['bug_url'] + list(self.target_field_names)
 
     def setUpWidgets(self):
-        super(BugTaskCreationStep, self).setUpWidgets()
+        super().setUpWidgets()
         self.target_widgets = [
             self.widgets[field_name]
             for field_name in self.field_names
@@ -410,7 +409,7 @@ class DistroBugTaskCreationStep(BugTaskCreationStep):
                 confirm_button).escapedtext)
             return None
         # Create the task.
-        return super(DistroBugTaskCreationStep, self).main_action(data)
+        return super().main_action(data)
 
     def validateStep(self, data):
         """Check that
@@ -462,7 +461,7 @@ class DistroBugTaskCreationStep(BugTaskCreationStep):
                 else:
                     self.setFieldError('distribution', e.args[0])
 
-        super(DistroBugTaskCreationStep, self).validateStep(data)
+        super().validateStep(data)
 
     def render(self):
         for bugtask in IBug(self.context).bugtasks:
@@ -475,7 +474,7 @@ class DistroBugTaskCreationStep(BugTaskCreationStep):
                 self.widgets['sourcepackagename'].setRenderedValue(
                     bugtask.sourcepackagename.name)
                 break
-        return super(DistroBugTaskCreationStep, self).render()
+        return super().render()
 
 
 class LinkUpstreamHowOptions(EnumeratedType):
@@ -560,7 +559,7 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
 
     label = "Confirm project"
     target_field_names = ('product', 'add_packaging')
-    main_action_label = u'Add to Bug Report'
+    main_action_label = 'Add to Bug Report'
     schema = IAddBugTaskWithUpstreamLinkForm
 
     custom_widget_link_upstream_how = CustomWidgetFactory(
@@ -573,7 +572,7 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
     @property
     def field_names(self):
         return ['link_upstream_how', 'upstream_email_address_done'] + (
-            super(ProductBugTaskCreationStep, self).field_names)
+            super().field_names)
 
     def validate_widgets(self, data, names=None):
         # The form is essentially just a radio group, with zero or one
@@ -604,7 +603,7 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
 
             # Don't request validation for text widgets that are not
             # related to the current radio selection.
-            for option, name in six.iteritems(link_upstream_options):
+            for option, name in link_upstream_options.items():
                 if link_upstream_how != option:
                     names.discard(name)
                 elif self.widgets[name].hasValidInput():
@@ -618,10 +617,9 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
         else:
             # Don't validate these widgets when we don't yet know how
             # we intend to link upstream.
-            names.difference_update(six.itervalues(link_upstream_options))
+            names.difference_update(link_upstream_options.values())
 
-        return super(ProductBugTaskCreationStep,
-                     self).validate_widgets(data, names)
+        return super().validate_widgets(data, names)
 
     def getTarget(self, data=None):
         if data is not None:
@@ -677,7 +675,7 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
                     sourcepackagename=self.context.target.sourcepackagename,
                     distroseries=series, packaging=PackagingType.PRIME,
                     owner=self.user)
-        return super(ProductBugTaskCreationStep, self).main_action(data)
+        return super().main_action(data)
 
     @property
     def upstream_bugtracker_links(self):
@@ -694,7 +692,7 @@ class ProductBugTaskCreationStep(BugTaskCreationStep):
 
         bug = self.context.bug
         title = bug.title
-        description = u"Originally reported at:\n  %s\n\n%s" % (
+        description = "Originally reported at:\n  %s\n\n%s" % (
             canonical_url(bug), bug.description)
         return target.bugtracker.getBugFilingAndSearchLinks(
             target.remote_product, title, description)
@@ -711,7 +709,7 @@ class BugTrackerCreationStep(AlsoAffectsStep):
     custom_widget_bug_url = CustomWidgetFactory(
         StrippedTextWidget, displayWidth=62)
     step_name = "bugtracker_creation"
-    main_action_label = u'Register Bug Tracker and Add to Bug Report'
+    main_action_label = 'Register Bug Tracker and Add to Bug Report'
     _next_step = None
 
     def main_action(self, data):
@@ -821,8 +819,7 @@ class BugAlsoAffectsProductWithProductCreationView(LinkPackgingMixin,
         This extra field is setup only if there is one or more products using
         that bugtracker.
         """
-        super(
-            BugAlsoAffectsProductWithProductCreationView, self).setUpFields()
+        super().setUpFields()
         self._loadProductsUsingBugTracker()
         if self.existing_products is None or len(self.existing_products) < 1:
             # No need to setup any extra fields.
diff --git a/lib/lp/bugs/browser/bugattachment.py b/lib/lp/bugs/browser/bugattachment.py
index 17ac98f..324c4e7 100644
--- a/lib/lp/bugs/browser/bugattachment.py
+++ b/lib/lp/bugs/browser/bugattachment.py
@@ -113,7 +113,7 @@ class BugAttachmentURL:
     @property
     def path(self):
         """Return the path component of the URL."""
-        return u"+attachment/%d" % self.context.id
+        return "+attachment/%d" % self.context.id
 
 
 class BugAttachmentEditView(LaunchpadFormView, BugAttachmentContentCheck):
@@ -207,7 +207,7 @@ class BugAttachmentPatchConfirmationView(LaunchpadFormView):
             canonical_url(ICanonicalUrlData(context).inside))
 
     def initialize(self):
-        super(BugAttachmentPatchConfirmationView, self).initialize()
+        super().initialize()
         self.widgets['patch'].setRenderedValue(self.is_patch)
 
     @property
diff --git a/lib/lp/bugs/browser/bugcomment.py b/lib/lp/bugs/browser/bugcomment.py
index 4687c29..5d2d087 100644
--- a/lib/lp/bugs/browser/bugcomment.py
+++ b/lib/lp/bugs/browser/bugcomment.py
@@ -217,7 +217,7 @@ class BugComment(MessageComment):
             comment_limit = config.malone.max_comment_size
         else:
             comment_limit = None
-        super(BugComment, self).__init__(comment_limit)
+        super().__init__(comment_limit)
 
         self.index = index
         self.bugtask = bugtask
@@ -261,7 +261,7 @@ class BugComment(MessageComment):
         if self.hide_text:
             return ''
         else:
-            return super(BugComment, self).text_for_display
+            return super().text_for_display
 
     def isIdenticalTo(self, other):
         """Compare this BugComment to another and return True if they are
@@ -316,7 +316,7 @@ class BugCommentView(LaunchpadView):
         """View redirects to +download if comment is too long to render."""
         if self.comment.too_long_to_render:
             return self.request.response.redirect(self.comment.download_url)
-        return super(BugCommentView, self).__call__()
+        return super().__call__()
 
     def download(self):
         return download_body(self.comment, self.request)
@@ -391,7 +391,7 @@ class BugCommentBreadcrumb(Breadcrumb):
     """Breadcrumb for an `IBugComment`."""
 
     def __init__(self, context):
-        super(BugCommentBreadcrumb, self).__init__(context)
+        super().__init__(context)
 
     @property
     def text(self):
diff --git a/lib/lp/bugs/browser/buglinktarget.py b/lib/lp/bugs/browser/buglinktarget.py
index 122e4f4..f3e2655 100644
--- a/lib/lp/bugs/browser/buglinktarget.py
+++ b/lib/lp/bugs/browser/buglinktarget.py
@@ -75,9 +75,9 @@ class BugLinkView(LaunchpadFormView):
             return
         bug_props = {'bugid': bug.id, 'title': bug.title}
         response.addNotification(
-            _(u'Added link to bug #$bugid: '
-              u'\N{left double quotation mark}$title'
-              u'\N{right double quotation mark}.', mapping=bug_props))
+            _('Added link to bug #$bugid: '
+              '\N{left double quotation mark}$title'
+              '\N{right double quotation mark}.', mapping=bug_props))
         notify(ObjectModifiedEvent(
             self.context, target_unmodified, ['bugs']))
         self.next_url = canonical_url(self.context)
diff --git a/lib/lp/bugs/browser/buglisting.py b/lib/lp/bugs/browser/buglisting.py
index 3a4a6c3..9859581 100644
--- a/lib/lp/bugs/browser/buglisting.py
+++ b/lib/lp/bugs/browser/buglisting.py
@@ -315,7 +315,7 @@ class BugTaskListingView(LaunchpadView):
 
     def render(self):
         """Make rendering this template-less view not crash."""
-        return u""
+        return ""
 
 
 class BugsInfoMixin:
@@ -1031,7 +1031,7 @@ class BugTaskSearchListingView(LaunchpadFormView, FeedsMixin, BugsInfoMixin):
         if self.request.get('QUERY_STRING', '') == '':
             # There is no query in this request, so it's okay for this page to
             # have its feed links.
-            return super(BugTaskSearchListingView, self).feed_links
+            return super().feed_links
         else:
             # The query changes the results so that they would not match the
             # feed.  In this case, suppress the feed links.
@@ -1139,7 +1139,7 @@ class BugTaskSearchListingView(LaunchpadFormView, FeedsMixin, BugsInfoMixin):
         if 'batch_request' in query_params:
             return self.bugtask_table_template
         else:
-            return super(BugTaskSearchListingView, self).template
+            return super().template
 
     def validate_search_params(self):
         """Validate the params passed for the search.
@@ -1708,7 +1708,7 @@ class TextualBugTaskSearchListingView(BugTaskSearchListingView):
         search_params = self.buildSearchParams()
         search_params.setTarget(self.context)
 
-        return u"".join("%d\n" % bug_id for bug_id in
+        return "".join("%d\n" % bug_id for bug_id in
             getUtility(IBugTaskSet).searchBugIds(search_params))
 
 
diff --git a/lib/lp/bugs/browser/bugmessage.py b/lib/lp/bugs/browser/bugmessage.py
index 6a69c5c..1ba55da 100644
--- a/lib/lp/bugs/browser/bugmessage.py
+++ b/lib/lp/bugs/browser/bugmessage.py
@@ -54,13 +54,13 @@ class BugMessageAddFormView(LaunchpadFormView, BugAttachmentContentCheck):
         # Ensure either a comment or filecontent was provide, but only
         # if no errors have already been noted.
         if len(self.errors) == 0:
-            comment = data.get('comment') or u''
+            comment = data.get('comment') or ''
             filecontent = data.get('filecontent', None)
             if not comment.strip() and not filecontent:
                 self.addError("Either a comment or attachment "
                               "must be provided.")
 
-    @action(u"Post Comment", name='save')
+    @action("Post Comment", name='save')
     def save_action(self, action, data):
         """Add the comment and/or attachment."""
 
diff --git a/lib/lp/bugs/browser/bugnomination.py b/lib/lp/bugs/browser/bugnomination.py
index 9839ff8..1c2319e 100644
--- a/lib/lp/bugs/browser/bugnomination.py
+++ b/lib/lp/bugs/browser/bugnomination.py
@@ -218,7 +218,7 @@ class BugNominationEditView(LaunchpadFormView):
 
     def initialize(self):
         self.current_bugtask = getUtility(ILaunchBag).bugtask
-        super(BugNominationEditView, self).initialize()
+        super().initialize()
 
     @property
     def action_url(self):
diff --git a/lib/lp/bugs/browser/bugsubscription.py b/lib/lp/bugs/browser/bugsubscription.py
index 3d08282..b28876c 100644
--- a/lib/lp/bugs/browser/bugsubscription.py
+++ b/lib/lp/bugs/browser/bugsubscription.py
@@ -17,7 +17,6 @@ from lazr.restful.interfaces import (
     IWebServiceClientRequest,
     )
 from simplejson import dumps
-import six
 from zope import formlib
 from zope.formlib.itemswidgets import RadioWidget
 from zope.formlib.widget import CustomWidgetFactory
@@ -67,7 +66,7 @@ class BugSubscriptionAddView(LaunchpadFormView):
 
     def setUpFields(self):
         """Set up 'person' as an input field."""
-        super(BugSubscriptionAddView, self).setUpFields()
+        super().setUpFields()
         self.form_fields['person'].for_input = True
 
     @action('Subscribe user', name='add')
@@ -77,7 +76,7 @@ class BugSubscriptionAddView(LaunchpadFormView):
             self.context.bug.subscribe(
                 person, self.user, suppress_notify=False)
         except SubscriptionPrivacyViolation as error:
-            self.setFieldError('person', six.text_type(error))
+            self.setFieldError('person', str(error))
         else:
             if person.is_team:
                 message = '%s team has been subscribed to this bug.'
@@ -208,7 +207,7 @@ class BugSubscriptionSubscribeSelfView(LaunchpadFormView,
     def initialize(self):
         """See `LaunchpadFormView`."""
         self._redirecting_to_bug_list = False
-        super(BugSubscriptionSubscribeSelfView, self).initialize()
+        super().initialize()
 
     @cachedproperty
     def current_user_subscription(self):
@@ -300,7 +299,7 @@ class BugSubscriptionSubscribeSelfView(LaunchpadFormView,
 
     def setUpFields(self):
         """See `LaunchpadFormView`."""
-        super(BugSubscriptionSubscribeSelfView, self).setUpFields()
+        super().setUpFields()
         if self.user is None:
             return
 
@@ -311,7 +310,7 @@ class BugSubscriptionSubscribeSelfView(LaunchpadFormView,
 
     def setUpWidgets(self):
         """See `LaunchpadFormView`."""
-        super(BugSubscriptionSubscribeSelfView, self).setUpWidgets()
+        super().setUpWidgets()
         self.widgets['subscription'].widget_class = 'bug-subscription-basic'
         self.widgets['bug_notification_level'].widget_class = (
             'bug-notification-level-field')
@@ -631,7 +630,7 @@ class BugSubscriptionListView(LaunchpadView):
     """A view to show all a person's subscriptions to a bug."""
 
     def initialize(self):
-        super(BugSubscriptionListView, self).initialize()
+        super().initialize()
         subscriptions = list(get_structural_subscriptions_for_bug(
             self.context.bug, self.user))
         expose_structural_subscription_data_to_js(
@@ -674,7 +673,7 @@ class BugMuteSelfView(LaunchpadFormView):
 
     def initialize(self):
         self.is_muted = self.context.bug.isMuted(self.user)
-        super(BugMuteSelfView, self).initialize()
+        super().initialize()
 
     @action('Mute bug mail',
             name='mute',
diff --git a/lib/lp/bugs/browser/bugsubscriptionfilter.py b/lib/lp/bugs/browser/bugsubscriptionfilter.py
index 13f8046..e12219f 100644
--- a/lib/lp/bugs/browser/bugsubscriptionfilter.py
+++ b/lib/lp/bugs/browser/bugsubscriptionfilter.py
@@ -62,7 +62,7 @@ class BugSubscriptionFilterView(LaunchpadView):
         set the empty string is returned.
         """
         description = self.context.description
-        return u"" if description is None else description.strip()
+        return "" if description is None else description.strip()
 
     # At the moment, we never filter everything.
     # We could turn it into a property and check more later--
@@ -72,9 +72,9 @@ class BugSubscriptionFilterView(LaunchpadView):
     def _add_english_condition(self, conditions, variable, description):
         if len(variable) > 0:
             conditions.append(
-                u"the %s is %s" % (description, english_list(
+                "the %s is %s" % (description, english_list(
                     (kind.title for kind in sorted(variable)),
-                    conjunction=u"or")))
+                    conjunction="or")))
 
     @property
     def conditions(self):
@@ -93,9 +93,9 @@ class BugSubscriptionFilterView(LaunchpadView):
         tags = self.context.tags
         if len(tags) > 0:
             conditions.append(
-                u"the bug is tagged with %s" % english_list(
+                "the bug is tagged with %s" % english_list(
                     sorted(tags), conjunction=(
-                        u"and" if self.context.find_all_tags else u"or")))
+                        "and" if self.context.find_all_tags else "or")))
         self._add_english_condition(
             conditions, self.context.information_types, 'information type')
         return conditions
@@ -139,7 +139,7 @@ class BugSubscriptionFilterEditViewBase(LaunchpadEditFormView,
         """Set up fields for form.
 
         Overrides the usual implementation to also set up bug notification."""
-        super(BugSubscriptionFilterEditViewBase, self).setUpFields()
+        super().setUpFields()
         self._setUpBugNotificationLevelField()
 
     @property
@@ -158,7 +158,7 @@ class BugSubscriptionFilterEditView(
     :ivar context: A provider of `IBugSubscriptionFilter`.
     """
 
-    page_title = u"Edit filter"
+    page_title = "Edit filter"
 
     @action("Update", name="update")
     def update_action(self, action, data):
@@ -187,7 +187,7 @@ class BugSubscriptionFilterCreateView(
     :ivar context: A provider of `IStructuralSubscription`.
     """
 
-    page_title = u"Create new filter"
+    page_title = "Create new filter"
 
     # The context does not correspond to the thing we're creating - which,
     # somewhat obviously, doesn't exist yet - so don't even try to render it.
diff --git a/lib/lp/bugs/browser/bugtarget.py b/lib/lp/bugs/browser/bugtarget.py
index d140bca..000d2e6 100644
--- a/lib/lp/bugs/browser/bugtarget.py
+++ b/lib/lp/bugs/browser/bugtarget.py
@@ -26,7 +26,6 @@ from lazr.restful.interface import copy_field
 from lazr.restful.interfaces import IJSONRequestCache
 from pytz import timezone
 from simplejson import dumps
-import six
 from six.moves.urllib.parse import (
     quote,
     urlencode,
@@ -205,7 +204,7 @@ class ProductConfigureBugTrackerView(ProductConfigureBase):
 
     def validate(self, data):
         """Constrain bug expiration to Launchpad Bugs tracker."""
-        super(ProductConfigureBugTrackerView, self).validate(data)
+        super().validate(data)
         # enable_bug_expiration is disabled by JavaScript when bugtracker
         # is not 'In Launchpad'. The constraint is enforced here in case the
         # JavaScript fails to activate or run. Note that the bugtracker
@@ -234,7 +233,7 @@ class FileBugViewBase(LaunchpadFormView):
     extra_data_token = None
 
     def __init__(self, context, request):
-        super(FileBugViewBase, self).__init__(context, request)
+        super().__init__(context, request)
         self.extra_data = FileBugData()
 
     def initialize(self):
@@ -278,7 +277,7 @@ class FileBugViewBase(LaunchpadFormView):
         cache.objects['enable_bugfiling_duplicate_search'] = (
             self.context.enable_bugfiling_duplicate_search)
 
-        super(FileBugViewBase, self).initialize()
+        super().initialize()
 
         if (self.extra_data_token is not None and
             not self.extra_data_to_process):
@@ -452,7 +451,7 @@ class FileBugViewBase(LaunchpadFormView):
 
     def setUpWidgets(self):
         """Customize the onKeyPress event of the package name chooser."""
-        super(FileBugViewBase, self).setUpWidgets()
+        super().setUpWidgets()
 
         if "packagename" in self.field_names:
             self.widgets["packagename"].onKeyPress = (
@@ -460,7 +459,7 @@ class FileBugViewBase(LaunchpadFormView):
 
     def setUpFields(self):
         """Set up the form fields. See `LaunchpadFormView`."""
-        super(FileBugViewBase, self).setUpFields()
+        super().setUpFields()
 
         if self.is_bug_supervisor:
             info_type_vocab = InformationTypeVocabulary(
@@ -480,7 +479,7 @@ class FileBugViewBase(LaunchpadFormView):
         # field.
         subscribe_field = Choice(
             __name__='subscribe_to_existing_bug',
-            title=u'Subscribe to this bug',
+            title='Subscribe to this bug',
             vocabulary=SUBSCRIBE_TO_BUG_VOCABULARY,
             required=True, default=False)
 
@@ -1006,7 +1005,7 @@ class FileBugGuidedView(FilebugShowSimilarBugsView):
     show_summary_in_results = True
 
     def initialize(self):
-        super(FileBugGuidedView, self).initialize()
+        super().initialize()
         if self.redirect_ubuntu_filebug:
             # The user is trying to file a new Ubuntu bug via the web
             # interface and without using apport. Redirect to a page
@@ -1227,7 +1226,7 @@ class BugTargetBugTagsView(LaunchpadView):
                 count=count,
                 url=self._getSearchURL(tag),
                 )
-            for (tag, count) in six.iteritems(tags)),
+            for (tag, count) in tags.items()),
             key=lambda item: (-item['count'], item['tag']))
 
     @property
@@ -1371,7 +1370,7 @@ class TargetSubscriptionView(LaunchpadView):
             return "Your subscriptions to %s" % self.context.displayname
 
     def initialize(self):
-        super(TargetSubscriptionView, self).initialize()
+        super().initialize()
         expose_structural_subscription_data_to_js(
             self.context, self.request, self.user, self.subscriptions)
 
diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py
index a4b0fc0..f0197a2 100644
--- a/lib/lp/bugs/browser/bugtask.py
+++ b/lib/lp/bugs/browser/bugtask.py
@@ -548,7 +548,7 @@ class BugTaskView(LaunchpadView, BugViewMixin, FeedsMixin):
         # after unsubscribing from a private bug, because rendering the
         # bug page would raise Unauthorized errors!
         if self._redirecting_to_bug_list:
-            return u''
+            return ''
         else:
             return LaunchpadView.render(self)
 
@@ -1126,7 +1126,7 @@ class BugTaskEditView(LaunchpadEditFormView, BugTaskBugWatchMixin,
         # Initialize user_is_subscribed, if it hasn't already been set.
         if self.user_is_subscribed is None:
             self.user_is_subscribed = self.context.bug.isSubscribed(self.user)
-        super(BugTaskEditView, self).initialize()
+        super().initialize()
 
     page_title = 'Edit status'
 
@@ -1236,7 +1236,7 @@ class BugTaskEditView(LaunchpadEditFormView, BugTaskBugWatchMixin,
 
         See `LaunchpadFormView`.
         """
-        super(BugTaskEditView, self).setUpFields()
+        super().setUpFields()
         read_only_field_names = self._getReadOnlyFieldNames()
 
         if 'target' in self.editable_field_names:
@@ -2051,7 +2051,7 @@ class BugTaskTableRowView(LaunchpadView, BugTaskBugWatchMixin,
         '../templates/bugtask-tasks-and-nominations-table-row.pt')
 
     def __init__(self, context, request):
-        super(BugTaskTableRowView, self).__init__(context, request)
+        super().__init__(context, request)
         self.milestone_source = BugTaskMilestoneVocabulary
 
     @cachedproperty
@@ -2059,7 +2059,7 @@ class BugTaskTableRowView(LaunchpadView, BugTaskBugWatchMixin,
         return IWebServiceClientRequest(self.request)
 
     def initialize(self):
-        super(BugTaskTableRowView, self).initialize()
+        super().initialize()
         link = canonical_url(self.context)
         task_link = edit_link = canonical_url(
                                     self.context, view_name='+editstatus')
@@ -2564,7 +2564,7 @@ class BugTaskBreadcrumb(Breadcrumb):
     """Breadcrumb for an `IBugTask`."""
 
     def __init__(self, context):
-        super(BugTaskBreadcrumb, self).__init__(context)
+        super().__init__(context)
         # If the user does not have permission to view the bug for
         # whatever reason, raise ComponentLookupError.
         try:
diff --git a/lib/lp/bugs/browser/bugtracker.py b/lib/lp/bugs/browser/bugtracker.py
index dee3683..49cfb21 100644
--- a/lib/lp/bugs/browser/bugtracker.py
+++ b/lib/lp/bugs/browser/bugtracker.py
@@ -109,7 +109,7 @@ class BugTrackerSetContextMenu(ContextMenu):
 
 class BugTrackerAddView(LaunchpadFormView):
 
-    page_title = u"Register an external bug tracker"
+    page_title = "Register an external bug tracker"
     schema = IBugTracker
     label = page_title
     field_names = ['bugtrackertype', 'name', 'title', 'baseurl', 'summary',
@@ -132,7 +132,7 @@ class BugTrackerAddView(LaunchpadFormView):
             else:
                 fields.append(self.form_fields[field_name])
         self.form_fields = form.Fields(*fields)
-        super(BugTrackerAddView, self).setUpWidgets(context=context)
+        super().setUpWidgets(context=context)
 
     @action(_('Add'), name='add')
     def add(self, action, data):
@@ -156,7 +156,7 @@ class BugTrackerAddView(LaunchpadFormView):
 class BugTrackerSetView(LaunchpadView):
     """View for actions on the bugtracker index pages."""
 
-    page_title = u"Bug trackers registered in Launchpad"
+    page_title = "Bug trackers registered in Launchpad"
     pillar_limit = 3
 
     def initialize(self):
@@ -213,7 +213,7 @@ class BugTrackerView(LaunchpadView):
     @property
     def page_title(self):
         return smartquote(
-            u'The "%s" bug tracker in Launchpad' % self.context.title)
+            'The "%s" bug tracker in Launchpad' % self.context.title)
 
     def initialize(self):
         self.batchnav = BatchNavigator(self.context.watches, self.request)
@@ -251,7 +251,7 @@ class BugTrackerEditView(LaunchpadEditFormView):
     @property
     def page_title(self):
         return smartquote(
-            u'Change details for the "%s" bug tracker' % self.context.title)
+            'Change details for the "%s" bug tracker' % self.context.title)
 
     @cachedproperty
     def field_names(self):
@@ -279,7 +279,7 @@ class BugTrackerEditView(LaunchpadEditFormView):
 
         See `LaunchpadFormView`.
         """
-        super(BugTrackerEditView, self).setUpFields()
+        super().setUpFields()
 
         # If we're displaying the 'active' field we need to swap it out
         # and replace it with a field that uses our custom vocabulary.
@@ -545,7 +545,7 @@ class BugTrackerSetBreadcrumb(Breadcrumb):
 
     @property
     def text(self):
-        return u"Bug trackers"
+        return "Bug trackers"
 
 
 @implementer(IRemoteBug)
diff --git a/lib/lp/bugs/browser/cve.py b/lib/lp/bugs/browser/cve.py
index f1d2348..8b6ae28 100644
--- a/lib/lp/bugs/browser/cve.py
+++ b/lib/lp/bugs/browser/cve.py
@@ -134,7 +134,7 @@ class CveUnlinkView(CveLinkView):
 class CveSetView(LaunchpadView):
 
     def __init__(self, context, request):
-        super(CveSetView, self).__init__(context, request)
+        super().__init__(context, request)
         self.notices = []
         self.results = None
         self.text = self.request.form.get('text', None)
diff --git a/lib/lp/bugs/browser/cvereport.py b/lib/lp/bugs/browser/cvereport.py
index aa674e3..411b5c3 100644
--- a/lib/lp/bugs/browser/cvereport.py
+++ b/lib/lp/bugs/browser/cvereport.py
@@ -64,7 +64,7 @@ class CVEReportView(LaunchpadView):
 
     def initialize(self):
         """See `LaunchpadView`."""
-        super(CVEReportView, self).initialize()
+        super().initialize()
         search_params = BugTaskSearchParams(
             self.user, has_cve=True)
         bugtasks = shortlist(
diff --git a/lib/lp/bugs/browser/person.py b/lib/lp/bugs/browser/person.py
index 9372c6d..4b5de77 100644
--- a/lib/lp/bugs/browser/person.py
+++ b/lib/lp/bugs/browser/person.py
@@ -201,8 +201,7 @@ class FilteredSearchListingViewMixin(RelevantMilestonesMixin,
         context = context or self.context
         extra_params = extra_params or {}
         extra_params.update(self.getExtraParams(context))
-        return super(FilteredSearchListingViewMixin, self).searchUnbatched(
-            searchtext, context, extra_params)
+        return super().searchUnbatched(searchtext, context, extra_params)
 
 
 class PersonAssignedBugTaskSearchListingView(FilteredSearchListingViewMixin):
diff --git a/lib/lp/bugs/browser/structuralsubscription.py b/lib/lp/bugs/browser/structuralsubscription.py
index 5506bee..8481497 100644
--- a/lib/lp/bugs/browser/structuralsubscription.py
+++ b/lib/lp/bugs/browser/structuralsubscription.py
@@ -141,8 +141,8 @@ class StructuralSubscriptionView(LaunchpadFormView):
         team_vocabulary = SimpleVocabulary(terms)
         team_subscriptions_field = List(
             __name__='subscriptions_team',
-            title=u'Team subscriptions',
-            description=(u'You can subscribe the teams of '
+            title='Team subscriptions',
+            description=('You can subscribe the teams of '
                           'which you are an administrator.'),
             value_type=Choice(vocabulary=team_vocabulary),
             required=False)
@@ -178,7 +178,7 @@ class StructuralSubscriptionView(LaunchpadFormView):
         subscriptions_vocabulary = SimpleVocabulary(terms)
         other_subscriptions_field = List(
             __name__='remove_other_subscriptions',
-            title=u'Unsubscribe',
+            title='Unsubscribe',
             value_type=Choice(vocabulary=subscriptions_vocabulary),
             required=False)
         return form.FormField(other_subscriptions_field)
@@ -187,7 +187,7 @@ class StructuralSubscriptionView(LaunchpadFormView):
         """Create a field for a new subscription."""
         new_subscription_field = Choice(
             __name__='new_subscription',
-            title=u'Subscribe someone else',
+            title='Subscribe someone else',
             vocabulary='ValidPersonOrTeam',
             required=False)
         return form.FormField(new_subscription_field)
@@ -220,7 +220,7 @@ class StructuralSubscriptionView(LaunchpadFormView):
         if self.context.userCanAlterBugSubscription(self.user, self.user):
             return True
 
-    @action(u'Save these changes', name='save')
+    @action('Save these changes', name='save')
     def save_action(self, action, data):
         """Process the subscriptions submitted by the user."""
         self._handleUserSubscription(data)
diff --git a/lib/lp/bugs/browser/tests/test_breadcrumbs.py b/lib/lp/bugs/browser/tests/test_breadcrumbs.py
index 447f47d..5789cf9 100644
--- a/lib/lp/bugs/browser/tests/test_breadcrumbs.py
+++ b/lib/lp/bugs/browser/tests/test_breadcrumbs.py
@@ -12,7 +12,7 @@ from lp.testing.breadcrumbs import BaseBreadcrumbTestCase
 class TestBugTaskBreadcrumb(BaseBreadcrumbTestCase):
 
     def setUp(self):
-        super(TestBugTaskBreadcrumb, self).setUp()
+        super().setUp()
         product = self.factory.makeProduct(
             name='crumb-tester', displayname="Crumb Tester")
         self.bug = self.factory.makeBug(target=product, title='borked')
@@ -25,7 +25,7 @@ class TestBugTaskBreadcrumb(BaseBreadcrumbTestCase):
         self.assertEqual(self.bugtask_url, last_crumb.url)
         self.assertEqual("Bug #%d" % self.bug.id, last_crumb.text)
         self.assertEqual(
-            u"Bug #%d \u201cborked\u201d" % self.bug.id, last_crumb.detail)
+            "Bug #%d \u201cborked\u201d" % self.bug.id, last_crumb.detail)
 
     def test_bugtask_child(self):
         crumbs = self.getBreadcrumbsForObject(
@@ -54,7 +54,7 @@ class TestBugTaskBreadcrumb(BaseBreadcrumbTestCase):
 class TestBugTrackerBreadcrumbs(BaseBreadcrumbTestCase):
 
     def setUp(self):
-        super(TestBugTrackerBreadcrumbs, self).setUp()
+        super().setUp()
         self.bug_tracker_set = getUtility(IBugTrackerSet)
         self.bug_tracker_set_url = canonical_url(
             self.bug_tracker_set, rootsite='bugs')
diff --git a/lib/lp/bugs/browser/tests/test_bug_context_menu.py b/lib/lp/bugs/browser/tests/test_bug_context_menu.py
index ef81c5a..82a35fb 100644
--- a/lib/lp/bugs/browser/tests/test_bug_context_menu.py
+++ b/lib/lp/bugs/browser/tests/test_bug_context_menu.py
@@ -24,7 +24,7 @@ class TestBugContextMenu(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugContextMenu, self).setUp()
+        super().setUp()
         self.bug = self.factory.makeBug()
         # We need to put the Bug and default BugTask into the LaunchBag
         # because BugContextMenu relies on the LaunchBag to populate its
diff --git a/lib/lp/bugs/browser/tests/test_bug_views.py b/lib/lp/bugs/browser/tests/test_bug_views.py
index 6984640..9188dfd 100644
--- a/lib/lp/bugs/browser/tests/test_bug_views.py
+++ b/lib/lp/bugs/browser/tests/test_bug_views.py
@@ -217,7 +217,7 @@ class TestBugPortletSubscribers(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugPortletSubscribers, self).setUp()
+        super().setUp()
         self.target = self.factory.makeProduct()
         bug_owner = self.factory.makePerson(name="bug-owner")
         self.bug = self.factory.makeBug(owner=bug_owner, target=self.target)
@@ -536,8 +536,7 @@ class TestBugSecrecyViews(TestCaseWithFactory):
                 principal=bug.owner)
             html = view.render()
             soup = BeautifulSoup(html)
-        self.assertEqual(
-            u'Private', soup.find('label', text="Private").string)
+        self.assertEqual('Private', soup.find('label', text="Private").string)
 
     def test_bugtask_view_user_with_grant_on_bug_for_private_product(self):
         # The regular bug view is properly rendered even if the user
@@ -557,7 +556,7 @@ class TestBugSecrecyViews(TestCaseWithFactory):
             launchbag.add(bug.default_bugtask)
         with person_logged_in(user):
             view = create_initialized_view(
-                bug.default_bugtask, name=u'+index', principal=user)
+                bug.default_bugtask, name='+index', principal=user)
             contents = view.render()
             self.assertTrue(bug.title in contents)
 
@@ -664,12 +663,12 @@ class TestBugMessageAddFormView(TestCaseWithFactory):
         # considered valid.
         bug = self.factory.makeBug()
         form = {
-            'field.comment': u' ',
-            'field.actions.save': u'Post Comment',
+            'field.comment': ' ',
+            'field.actions.save': 'Post Comment',
             }
         view = create_initialized_view(
             bug.default_bugtask, '+addcomment', form=form)
-        expected_error = u'Either a comment or attachment must be provided.'
+        expected_error = 'Either a comment or attachment must be provided.'
         self.assertEqual(view.errors[0], expected_error)
 
     def test_whitespaces_message_with_attached_file(self):
@@ -677,10 +676,10 @@ class TestBugMessageAddFormView(TestCaseWithFactory):
         # is attached then the request has to be considered valid.
         bug = self.factory.makeBug()
         form = {
-            'field.comment': u' ',
-            'field.actions.save': u'Post Comment',
+            'field.comment': ' ',
+            'field.actions.save': 'Post Comment',
             'field.filecontent': self.factory.makeFakeFileUpload(),
-            'field.patch.used': u'',
+            'field.patch.used': '',
             }
         login_person(self.factory.makePerson())
         view = create_initialized_view(
@@ -694,7 +693,7 @@ class TestBugMarkAsDuplicateView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugMarkAsDuplicateView, self).setUp()
+        super().setUp()
         self.bug_owner = self.factory.makePerson()
         self.bug = self.factory.makeBug(owner=self.bug_owner)
         self.duplicate_bug = self.factory.makeBug(owner=self.bug_owner)
@@ -720,8 +719,8 @@ class TestBugMarkAsDuplicateView(TestCaseWithFactory):
     def test_create_duplicate(self):
         with person_logged_in(self.bug_owner):
             form = {
-                'field.actions.change': u'Set Duplicate',
-                'field.duplicateof': u'%s' % self.duplicate_bug.id
+                'field.actions.change': 'Set Duplicate',
+                'field.duplicateof': '%s' % self.duplicate_bug.id
                 }
             create_initialized_view(
                 self.bug.default_bugtask, name="+duplicate",
@@ -732,7 +731,7 @@ class TestBugMarkAsDuplicateView(TestCaseWithFactory):
         with person_logged_in(self.bug_owner):
             self.bug.markAsDuplicate(self.duplicate_bug)
             form = {
-                'field.actions.remove': u'Remove Duplicate',
+                'field.actions.remove': 'Remove Duplicate',
                 }
             create_initialized_view(
                 self.bug.default_bugtask, name="+duplicate",
@@ -746,8 +745,8 @@ class TestBugMarkAsDuplicateView(TestCaseWithFactory):
                 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
                 }
             form = {
-                'field.actions.change': u'Set Duplicate',
-                'field.duplicateof': u'%s' % self.duplicate_bug.id
+                'field.actions.change': 'Set Duplicate',
+                'field.duplicateof': '%s' % self.duplicate_bug.id
                 }
             view = create_initialized_view(
                 self.bug.default_bugtask, name="+duplicate",
@@ -771,7 +770,7 @@ class TestBugMarkAsDuplicateView(TestCaseWithFactory):
                 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
                 }
             form = {
-                'field.actions.remove': u'Remove Duplicate',
+                'field.actions.remove': 'Remove Duplicate',
                 }
 
             view = create_initialized_view(
@@ -817,7 +816,7 @@ class TestMainBugView(BrowserTestCase):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestMainBugView, self).setUp()
+        super().setUp()
         self.user = self.factory.makePerson()
         self.product_owner = self.factory.makePerson()
         self.proprietary_product = self.factory.makeProduct(
diff --git a/lib/lp/bugs/browser/tests/test_bugalsoaffects.py b/lib/lp/bugs/browser/tests/test_bugalsoaffects.py
index 49d7885..86aeb97 100644
--- a/lib/lp/bugs/browser/tests/test_bugalsoaffects.py
+++ b/lib/lp/bugs/browser/tests/test_bugalsoaffects.py
@@ -19,7 +19,7 @@ class TestBugAlsoAffectsDistribution(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugAlsoAffectsDistribution, self).setUp()
+        super().setUp()
         self.distribution = self.factory.makeDistribution(displayname='Distro')
         removeSecurityProxy(self.distribution).official_malone = True
 
@@ -57,7 +57,7 @@ class TestBugAlsoAffectsDistribution(TestCaseWithFactory):
             bug.addTask(bug.owner, dsp1)
         dsp2 = self.factory.makeDSPCache(
             distroseries=distroseries, sourcepackagename='snarf')
-        with FeatureFixture({u"disclosure.dsp_picker.enabled": u"on"}):
+        with FeatureFixture({"disclosure.dsp_picker.enabled": "on"}):
             browser = self.openBugPage(bug)
             browser.getLink(url='+distrotask').click()
             browser.getControl('Distribution').value = [self.distribution.name]
@@ -81,8 +81,8 @@ class TestBugAlsoAffectsDistribution(TestCaseWithFactory):
         browser.getControl('Source Package Name').value = 'does-not-exist'
         browser.getControl('Continue').click()
         expected = [
-            u'There is 1 error.',
-            u'There is no package in %s named "does-not-exist".' % (
+            'There is 1 error.',
+            'There is no package in %s named "does-not-exist".' % (
                 self.distribution.displayname)]
         self.assertEqual(expected, get_feedback_messages(browser.contents))
 
@@ -95,8 +95,8 @@ class TestBugAlsoAffectsDistribution(TestCaseWithFactory):
         browser.getControl('Source Package Name').value = 'does-not-exist'
         browser.getControl('Continue').click()
         expected = [
-            u'There is 1 error.',
-            u'There is no package in %s named "does-not-exist". Launchpad '
+            'There is 1 error.',
+            'There is no package in %s named "does-not-exist". Launchpad '
             'does not track binary package names in %s.' % (
                 self.distribution.displayname,
                 self.distribution.displayname)]
diff --git a/lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py b/lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py
index c052cf9..3517b0c 100644
--- a/lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py
+++ b/lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py
@@ -28,7 +28,7 @@ class TestBugAttachmentEditView(TestCaseWithFactory):
         }
 
     def setUp(self):
-        super(TestBugAttachmentEditView, self).setUp()
+        super().setUp()
         self.bug_owner = self.factory.makePerson()
         self.registry_expert = self.factory.makePerson()
         registry = getUtility(ILaunchpadCelebrities).registry_experts
diff --git a/lib/lp/bugs/browser/tests/test_bugattachment_file_access.py b/lib/lp/bugs/browser/tests/test_bugattachment_file_access.py
index f4a50e0..3b48f29 100644
--- a/lib/lp/bugs/browser/tests/test_bugattachment_file_access.py
+++ b/lib/lp/bugs/browser/tests/test_bugattachment_file_access.py
@@ -41,7 +41,7 @@ class TestAccessToBugAttachmentFiles(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestAccessToBugAttachmentFiles, self).setUp()
+        super().setUp()
         self.bug_owner = self.factory.makePerson()
         getUtility(ILaunchBag).clear()
         login_person(self.bug_owner)
@@ -121,7 +121,7 @@ class TestWebserviceAccessToBugAttachmentFiles(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestWebserviceAccessToBugAttachmentFiles, self).setUp()
+        super().setUp()
         self.bug_owner = self.factory.makePerson()
         getUtility(ILaunchBag).clear()
         login_person(self.bug_owner)
diff --git a/lib/lp/bugs/browser/tests/test_bugcomment.py b/lib/lp/bugs/browser/tests/test_bugcomment.py
index f93a5c9..2b15d6f 100644
--- a/lib/lp/bugs/browser/tests/test_bugcomment.py
+++ b/lib/lp/bugs/browser/tests/test_bugcomment.py
@@ -86,7 +86,7 @@ class TestGroupCommentsWithActivities(TestCase):
     """Tests for `group_comments_with_activities`."""
 
     def setUp(self):
-        super(TestGroupCommentsWithActivities, self).setUp()
+        super().setUp()
         self.now = datetime.now(utc)
         self.time_index = (
             (self.now + timedelta(minutes=counter), counter)
diff --git a/lib/lp/bugs/browser/tests/test_buglisting.py b/lib/lp/bugs/browser/tests/test_buglisting.py
index 96ca744..183fd17 100644
--- a/lib/lp/bugs/browser/tests/test_buglisting.py
+++ b/lib/lp/bugs/browser/tests/test_buglisting.py
@@ -196,7 +196,7 @@ class TestBugTaskSearchListingPage(BrowserTestCase):
         form = {'search': 'Search'}
         with person_logged_in(product.owner):
             product.official_malone = True
-        flags = {u"ajax.batch_navigator.enabled": u"true"}
+        flags = {"ajax.batch_navigator.enabled": "true"}
         with FeatureFixture(flags):
             view = create_initialized_view(product, '+bugs', form=form)
             self.assertTrue(
@@ -445,7 +445,7 @@ class TestPersonBugListing(BrowserTestCase):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestPersonBugListing, self).setUp()
+        super().setUp()
         self.user = self.factory.makePerson()
         self.private_product_owner = self.factory.makePerson()
         self.private_product = self.factory.makeProduct(
diff --git a/lib/lp/bugs/browser/tests/test_bugnomination.py b/lib/lp/bugs/browser/tests/test_bugnomination.py
index 0a32ea2..a31d434 100644
--- a/lib/lp/bugs/browser/tests/test_bugnomination.py
+++ b/lib/lp/bugs/browser/tests/test_bugnomination.py
@@ -33,7 +33,7 @@ class TestBugNominationView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugNominationView, self).setUp()
+        super().setUp()
         self.distribution = self.factory.makeDistribution()
         owner = self.distribution.owner
         bug_team = self.factory.makeTeam(owner=owner)
diff --git a/lib/lp/bugs/browser/tests/test_bugs.py b/lib/lp/bugs/browser/tests/test_bugs.py
index 8581b03..4a43fe1 100644
--- a/lib/lp/bugs/browser/tests/test_bugs.py
+++ b/lib/lp/bugs/browser/tests/test_bugs.py
@@ -26,7 +26,7 @@ class TestMaloneView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestMaloneView, self).setUp()
+        super().setUp()
         self.application = getUtility(IMaloneApplication)
 
     def test_redirect_id_success(self):
diff --git a/lib/lp/bugs/browser/tests/test_bugsubscription_views.py b/lib/lp/bugs/browser/tests/test_bugsubscription_views.py
index 5dc2d09..3f55c87 100644
--- a/lib/lp/bugs/browser/tests/test_bugsubscription_views.py
+++ b/lib/lp/bugs/browser/tests/test_bugsubscription_views.py
@@ -44,7 +44,7 @@ class BugsubscriptionPrivacyTests(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(BugsubscriptionPrivacyTests, self).setUp()
+        super().setUp()
         self.user = self.factory.makePerson()
         self.bug = self.factory.makeBug(owner=self.user)
         removeSecurityProxy(self.bug).setPrivate(True, self.user)
@@ -58,7 +58,7 @@ class BugsubscriptionPrivacyTests(TestCaseWithFactory):
         subscription = removeSecurityProxy(self.bug).getSubscriptionForPerson(
             team)
         error_msg = harness.getFieldError('person')
-        expected_msg = (u'Open and delegated teams cannot be subscribed to '
+        expected_msg = ('Open and delegated teams cannot be subscribed to '
             'private bugs.')
         self.assertEqual(expected_msg, error_msg)
         self.assertIs(None, subscription)
@@ -79,7 +79,7 @@ class BugSubscriptionAdvancedFeaturesTestCase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(BugSubscriptionAdvancedFeaturesTestCase, self).setUp()
+        super().setUp()
         self.bug = self.factory.makeBug()
         self.person = self.factory.makePerson()
 
@@ -399,7 +399,7 @@ class BugSubscriptionsListViewTestCase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(BugSubscriptionsListViewTestCase, self).setUp()
+        super().setUp()
         self.product = self.factory.makeProduct(
             name='widgetsrus', displayname='Widgets R Us')
         self.bug = self.factory.makeBug(target=self.product)
@@ -421,7 +421,7 @@ class BugMuteSelfViewTestCase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(BugMuteSelfViewTestCase, self).setUp()
+        super().setUp()
         self.bug = self.factory.makeBug()
         self.person = self.factory.makePerson()
 
diff --git a/lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py b/lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py
index 342e984..23f9c99 100644
--- a/lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py
+++ b/lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py
@@ -6,7 +6,6 @@
 import json
 
 from lxml import html
-import six
 from six.moves.urllib.parse import urlparse
 from testtools.matchers import StartsWith
 
@@ -38,10 +37,10 @@ from lp.testing.views import create_initialized_view
 class TestBugSubscriptionFilterBase:
 
     def setUp(self):
-        super(TestBugSubscriptionFilterBase, self).setUp()
-        self.owner = self.factory.makePerson(name=u"foo")
+        super().setUp()
+        self.owner = self.factory.makePerson(name="foo")
         self.structure = self.factory.makeProduct(
-            owner=self.owner, name=u"bar")
+            owner=self.owner, name="bar")
         with person_logged_in(self.owner):
             self.subscription = self.structure.addBugSubscription(
                 self.owner, self.owner)
@@ -66,7 +65,7 @@ class TestBugSubscriptionFilterNavigation(
 
     def test_navigation(self):
         request = LaunchpadTestRequest()
-        request.setTraversalStack([six.text_type(self.subscription_filter.id)])
+        request.setTraversalStack([str(self.subscription_filter.id)])
         navigation = StructuralSubscriptionNavigation(
             self.subscription, request)
         view = navigation.publishTraverse(request, '+filter')
@@ -109,7 +108,7 @@ class TestBugSubscriptionFilterAPI(
         # Bug filters cannot be moved from one structural subscription to
         # another. In other words, the structural_subscription field is
         # read-only.
-        user = self.factory.makePerson(name=u"baz")
+        user = self.factory.makePerson(name="baz")
         with person_logged_in(self.owner):
             user_subscription = self.structure.addBugSubscription(user, user)
             user_subscription_url = api_url(user_subscription)
@@ -131,7 +130,7 @@ class TestBugSubscriptionFilterAPIModifications(
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugSubscriptionFilterAPIModifications, self).setUp()
+        super().setUp()
         self.webservice = webservice_for_person(
             self.owner, permission=OAuthPermission.WRITE_PUBLIC)
 
@@ -170,12 +169,11 @@ class TestBugSubscriptionFilterAPIModifications(
         # Apply changes.
         response = self.webservice.patch(
             self.subscription_filter_url, "application/json",
-            json.dumps({"description": u"It's late."}))
+            json.dumps({"description": "It's late."}))
         self.assertEqual(209, response.status)
 
         # Updated state.
-        self.assertEqual(
-            u"It's late.", self.subscription_filter.description)
+        self.assertEqual("It's late.", self.subscription_filter.description)
 
     def test_modify_statuses(self):
         # The statuses field can be modified.
@@ -224,26 +222,26 @@ class TestBugSubscriptionFilterView(
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugSubscriptionFilterView, self).setUp()
+        super().setUp()
         self.view = create_initialized_view(
             self.subscription_filter, "+definition")
 
     def test_description(self):
         # If the description is not set then the empty string is returned.
-        self.assertEqual(u"", self.view.description)
+        self.assertEqual("", self.view.description)
         # If the description is just whitespace then the empty string is
         # returned.
         with person_logged_in(self.owner):
-            self.subscription_filter.description = u"  "
-        self.assertEqual(u"", self.view.description)
+            self.subscription_filter.description = "  "
+        self.assertEqual("", self.view.description)
         # If the description is set it is returned.
         with person_logged_in(self.owner):
-            self.subscription_filter.description = u"Foo"
-        self.assertEqual(u"Foo", self.view.description)
+            self.subscription_filter.description = "Foo"
+        self.assertEqual("Foo", self.view.description)
         # Leading and trailing whitespace is trimmed.
         with person_logged_in(self.owner):
-            self.subscription_filter.description = u"  Foo\t  "
-        self.assertEqual(u"Foo", self.view.description)
+            self.subscription_filter.description = "  Foo\t  "
+        self.assertEqual("Foo", self.view.description)
 
     def test_conditions_with_nothing_set(self):
         # If nothing is set the conditions list is empty.
@@ -264,7 +262,7 @@ class TestBugSubscriptionFilterView(
             self.subscription_filter.bug_notification_level = (
                 BugNotificationLevel.METADATA)
         self.assertEqual(
-            [u'any change is made to the bug, other than a new comment being '
+            ['any change is made to the bug, other than a new comment being '
               'added'],
             self.view.conditions)
 
@@ -273,7 +271,7 @@ class TestBugSubscriptionFilterView(
             self.subscription_filter.bug_notification_level = (
                 BugNotificationLevel.LIFECYCLE)
         self.assertEqual(
-            [u'the bug is fixed or re-opened'],
+            ['the bug is fixed or re-opened'],
             self.view.conditions)
 
     def test_conditions_for_statuses(self):
@@ -287,7 +285,7 @@ class TestBugSubscriptionFilterView(
                 BugTaskStatus.TRIAGED,
                 ]
         self.assertEqual(
-            [u"the status is New, Confirmed, or Triaged"],
+            ["the status is New, Confirmed, or Triaged"],
             self.view.conditions)
 
     def test_conditions_for_importances(self):
@@ -301,7 +299,7 @@ class TestBugSubscriptionFilterView(
                 BugTaskImportance.HIGH,
                 ]
         self.assertEqual(
-            [u"the importance is High, Medium, or Low"],
+            ["the importance is High, Medium, or Low"],
              self.view.conditions)
 
     def test_conditions_for_tags(self):
@@ -309,15 +307,15 @@ class TestBugSubscriptionFilterView(
         self.assertEqual([], self.view.conditions)
         # If set, a description of the tags is returned.
         with person_logged_in(self.owner):
-            self.subscription_filter.tags = [u"foo", u"bar", u"*"]
+            self.subscription_filter.tags = ["foo", "bar", "*"]
         self.assertEqual(
-            [u"the bug is tagged with *, bar, or foo"],
+            ["the bug is tagged with *, bar, or foo"],
             self.view.conditions)
         # If find_all_tags is set, the conjunction changes.
         with person_logged_in(self.owner):
             self.subscription_filter.find_all_tags = True
         self.assertEqual(
-            [u"the bug is tagged with *, bar, and foo"],
+            ["the bug is tagged with *, bar, and foo"],
             self.view.conditions)
 
     def test_conditions_for_information_types(self):
@@ -328,7 +326,7 @@ class TestBugSubscriptionFilterView(
             self.subscription_filter.information_types = [
                 InformationType.PRIVATESECURITY, InformationType.USERDATA]
         self.assertEqual(
-            [u"the information type is Private Security or Private"],
+            ["the information type is Private Security or Private"],
             self.view.conditions)
 
     def assertRender(self, dt_content=None, dd_content=None):
@@ -347,8 +345,8 @@ class TestBugSubscriptionFilterView(
         # description is very simple, and there's a short message describing
         # the absense of conditions.
         self.assertRender(
-            u"This filter allows all mail through.",
-            u"There are no filter conditions!")
+            "This filter allows all mail through.",
+            "There are no filter conditions!")
 
     def test_render_with_no_description_and_conditions(self):
         # If conditions are set but no description, the rendered description
@@ -366,35 +364,35 @@ class TestBugSubscriptionFilterView(
                 BugTaskImportance.MEDIUM,
                 BugTaskImportance.HIGH,
                 ]
-            self.subscription_filter.tags = [u"foo", u"bar"]
+            self.subscription_filter.tags = ["foo", "bar"]
         self.assertRender(
-            u"This filter allows mail through when:",
-            u" and ".join(self.view.conditions))
+            "This filter allows mail through when:",
+            " and ".join(self.view.conditions))
 
     def test_render_with_description_and_no_conditions(self):
         # If a description is set it appears in the content of the dt tag,
         # surrounded by "curly" quotes.
         with person_logged_in(self.owner):
-            self.subscription_filter.description = u"The Wait"
+            self.subscription_filter.description = "The Wait"
         self.assertRender(
-            u"\u201cThe Wait\u201d allows all mail through.",
-            u"There are no filter conditions!")
+            "\u201cThe Wait\u201d allows all mail through.",
+            "There are no filter conditions!")
 
     def test_render_with_no_events_allowed(self):
         self.view.filters_everything = True
         self.assertRender(
-            u"This filter allows no mail through.",
-            u"")
+            "This filter allows no mail through.",
+            "")
 
     def test_render_with_description_and_conditions(self):
         # If a description is set it appears in the content of the dt tag,
         # surrounded by "curly" quotes.
         with person_logged_in(self.owner):
-            self.subscription_filter.description = u"The Wait"
-            self.subscription_filter.tags = [u"foo"]
+            self.subscription_filter.description = "The Wait"
+            self.subscription_filter.tags = ["foo"]
         self.assertRender(
-            u"\u201cThe Wait\u201d allows mail through when:",
-            u" and ".join(self.view.conditions))
+            "\u201cThe Wait\u201d allows mail through when:",
+            " and ".join(self.view.conditions))
 
     def findEditLinks(self, view):
         root = html.fromstring(view.render())
@@ -447,7 +445,7 @@ class TestBugSubscriptionFilterEditView(
             "field.statuses": ["NEW", "INCOMPLETE"],
             "field.importances": ["LOW", "MEDIUM"],
             "field.information_types": ["USERDATA"],
-            "field.tags": u"foo bar",
+            "field.tags": "foo bar",
             "field.find_all_tags": "on",
             "field.actions.update": "Update",
             }
@@ -457,7 +455,7 @@ class TestBugSubscriptionFilterEditView(
             self.assertEqual([], view.errors)
         # The subscription filter has been updated.
         self.assertEqual(
-            u"New description", self.subscription_filter.description)
+            "New description", self.subscription_filter.description)
         self.assertEqual(
             frozenset([BugTaskStatus.NEW, BugTaskStatus.INCOMPLETE]),
             self.subscription_filter.statuses)
@@ -468,7 +466,7 @@ class TestBugSubscriptionFilterEditView(
             frozenset([InformationType.USERDATA]),
             self.subscription_filter.information_types)
         self.assertEqual(
-            frozenset([u"foo", u"bar"]), self.subscription_filter.tags)
+            frozenset(["foo", "bar"]), self.subscription_filter.tags)
         self.assertTrue(self.subscription_filter.find_all_tags)
 
     def test_delete(self):
@@ -491,7 +489,7 @@ class TestBugSubscriptionFilterAdvancedFeatures(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugSubscriptionFilterAdvancedFeatures, self).setUp()
+        super().setUp()
         self.setUpTarget()
 
     def setUpTarget(self):
@@ -511,7 +509,7 @@ class TestBugSubscriptionFilterAdvancedFeatures(TestCaseWithFactory):
                     "field.description": "New description",
                     "field.statuses": ["NEW", "INCOMPLETE"],
                     "field.importances": ["LOW", "MEDIUM"],
-                    "field.tags": u"foo bar",
+                    "field.tags": "foo bar",
                     "field.find_all_tags": "on",
                     'field.bug_notification_level': level.title,
                     "field.actions.create": "Create",
@@ -535,10 +533,10 @@ class TestBugSubscriptionFilterCreateView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugSubscriptionFilterCreateView, self).setUp()
-        self.owner = self.factory.makePerson(name=u"foo")
+        super().setUp()
+        self.owner = self.factory.makePerson(name="foo")
         self.structure = self.factory.makeProduct(
-            owner=self.owner, name=u"bar")
+            owner=self.owner, name="bar")
         with person_logged_in(self.owner):
             self.subscription = self.structure.addBugSubscription(
                 self.owner, self.owner)
@@ -564,7 +562,7 @@ class TestBugSubscriptionFilterCreateView(TestCaseWithFactory):
             "field.statuses": ["NEW", "INCOMPLETE"],
             "field.importances": ["LOW", "MEDIUM"],
             "field.information_types": ["PRIVATESECURITY"],
-            "field.tags": u"foo bar",
+            "field.tags": "foo bar",
             "field.find_all_tags": "on",
             "field.actions.create": "Create",
             }
@@ -577,7 +575,7 @@ class TestBugSubscriptionFilterCreateView(TestCaseWithFactory):
             filter for filter in self.subscription.bug_filters
             if filter != initial_filter][0]
         self.assertEqual(
-            u"New description",
+            "New description",
             subscription_filter.description)
         self.assertEqual(
             frozenset([BugTaskStatus.NEW, BugTaskStatus.INCOMPLETE]),
@@ -589,5 +587,5 @@ class TestBugSubscriptionFilterCreateView(TestCaseWithFactory):
             frozenset([InformationType.PRIVATESECURITY]),
             subscription_filter.information_types)
         self.assertEqual(
-            frozenset([u"foo", u"bar"]), subscription_filter.tags)
+            frozenset(["foo", "bar"]), subscription_filter.tags)
         self.assertTrue(subscription_filter.find_all_tags)
diff --git a/lib/lp/bugs/browser/tests/test_bugsupervisor.py b/lib/lp/bugs/browser/tests/test_bugsupervisor.py
index d59b437..861b6e5 100644
--- a/lib/lp/bugs/browser/tests/test_bugsupervisor.py
+++ b/lib/lp/bugs/browser/tests/test_bugsupervisor.py
@@ -24,7 +24,7 @@ class TestBugSupervisorEditView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugSupervisorEditView, self).setUp()
+        super().setUp()
         self.owner = self.factory.makePerson(
             name='splat', displayname='<splat />')
         self.product = self.factory.makeProduct(
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_configure.py b/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
index 4343482..ff03f51 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
@@ -18,7 +18,7 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProductBugConfigurationView, self).setUp()
+        super().setUp()
         self.owner = self.factory.makePerson(name='boing-owner')
         self.bug_supervisor = self.factory.makePerson(
             name='boing-bug-supervisor')
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
index 1b50efa..3a693b3 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
@@ -69,7 +69,7 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugTargetFileBugConfirmationMessage, self).setUp()
+        super().setUp()
         login('foo.bar@xxxxxxxxxxxxx')
         self.product = self.factory.makeProduct()
 
@@ -79,17 +79,17 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         product = self.factory.makeProduct()
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(product))
 
         # If a product contains a customized bug filing confirmation
         # message, it is retrieved by
         # FilebugViewBase.bug_reported_acknowledgement
         product.bug_reported_acknowledgement = (
-            u"We really appreciate your bug report")
+            "We really appreciate your bug report")
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"We really appreciate your bug report",
+            "We really appreciate your bug report",
             view.getAcknowledgementMessage(product))
 
         # If the custom message is set to a string containing only white,
@@ -97,7 +97,7 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         product.bug_reported_acknowledgement = ' \t'
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(product))
 
     def test_getAcknowledgementMessage_product_in_project_group(self):
@@ -111,7 +111,7 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         # default message is used.
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(product))
 
         # If the project group has a customized message, it is used.
@@ -119,16 +119,16 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
             "Thanks for filing a bug for one of our many products.")
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thanks for filing a bug for one of our many products.",
+            "Thanks for filing a bug for one of our many products.",
             view.getAcknowledgementMessage(product))
 
         # But if the product itself has a customized message too, this
         # message is used instead of the project group's message.
         product.bug_reported_acknowledgement = (
-            u"Thanks for filing a bug for this very special product.")
+            "Thanks for filing a bug for this very special product.")
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thanks for filing a bug for this very special product.",
+            "Thanks for filing a bug for this very special product.",
             view.getAcknowledgementMessage(product))
 
     def test_getAcknowledgementMessage_product_series_in_project_group(self):
@@ -143,24 +143,24 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         # default message is used.
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(product_series))
 
         # If the project group has a customized message, it is used.
         project_group.bug_reported_acknowledgement = (
-            u"Thanks for filing a bug for one of our many product_seriess.")
+            "Thanks for filing a bug for one of our many product_seriess.")
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thanks for filing a bug for one of our many product_seriess.",
+            "Thanks for filing a bug for one of our many product_seriess.",
             view.getAcknowledgementMessage(product_series))
 
         # But if the product has a customized message too, this
         # message is used instead of the project group's message.
         product.bug_reported_acknowledgement = (
-            u"Thanks for filing a bug for this very special product.")
+            "Thanks for filing a bug for this very special product.")
         view = create_initialized_view(product, name='+filebug')
         self.assertEqual(
-            u"Thanks for filing a bug for this very special product.",
+            "Thanks for filing a bug for this very special product.",
             view.getAcknowledgementMessage(product_series))
 
     def test_getAcknowledgementMessage_distribution(self):
@@ -169,17 +169,17 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         distribution = self.factory.makeDistribution()
         view = create_initialized_view(distribution, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(distribution))
 
         # If a distribution contains a customized bug filing confirmation
         # message, it is retrieved by
         # FilebugViewBase.bug_reported_acknowledgement
         distribution.bug_reported_acknowledgement = (
-            u"We really appreciate your bug report")
+            "We really appreciate your bug report")
         view = create_initialized_view(distribution, name='+filebug')
         self.assertEqual(
-            u"We really appreciate your bug report",
+            "We really appreciate your bug report",
             view.getAcknowledgementMessage(distribution))
 
     def test_getAcknowledgementMessage_distributionsourcepackage(self):
@@ -188,16 +188,16 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         dsp = self.factory.makeDistributionSourcePackage()
         view = create_initialized_view(dsp, name='+filebug')
         self.assertEqual(
-            u"Thank you for your bug report.",
+            "Thank you for your bug report.",
             view.getAcknowledgementMessage(dsp))
 
         # If a custom message is defined for a DSP, it is used instead of
         # the default message.
         dsp.bug_reported_acknowledgement = (
-            u"We really appreciate your bug report")
+            "We really appreciate your bug report")
         view = create_initialized_view(dsp, name='+filebug')
         self.assertEqual(
-            u"We really appreciate your bug report",
+            "We really appreciate your bug report",
             view.getAcknowledgementMessage(dsp))
 
     def test_getAcknowledgementMessage_dsp_custom_distro_message(self):
@@ -205,19 +205,19 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
         # is used for bugs filed on DistributionSourcePackages.
         dsp = self.factory.makeDistributionSourcePackage()
         dsp.distribution.bug_reported_acknowledgement = (
-            u"Thank you for filing a bug in our distribution")
+            "Thank you for filing a bug in our distribution")
         view = create_initialized_view(dsp, name='+filebug')
         self.assertEqual(
-            u"Thank you for filing a bug in our distribution",
+            "Thank you for filing a bug in our distribution",
             view.getAcknowledgementMessage(dsp))
 
         # Bug if a custom message is defined for a DSP, it is used instead of
         # the message for the distribution.
         dsp.bug_reported_acknowledgement = (
-            u"Thank you for filing a bug for this DSP")
+            "Thank you for filing a bug for this DSP")
         view = create_initialized_view(dsp, name='+filebug')
         self.assertEqual(
-            u"Thank you for filing a bug for this DSP",
+            "Thank you for filing a bug for this DSP",
             view.getAcknowledgementMessage(dsp))
 
     def test_bug_filed_acknowlegdgement_notification(self):
@@ -239,11 +239,11 @@ class TestBugTargetFileBugConfirmationMessage(TestCaseWithFactory):
 
         # This message can be customized.
         product.bug_reported_acknowledgement = (
-            u"We really appreciate your bug report")
+            "We really appreciate your bug report")
         view = create_initialized_view(product, name='+filebug')
         view.submit_bug_action.success(form_data)
         self.assertEqual(
-            [u'<p class="last">We really appreciate your bug report</p>'],
+            ['<p class="last">We really appreciate your bug report</p>'],
             [notification.message
              for notification in view.request.response.notifications])
 
@@ -303,7 +303,7 @@ class FileBugViewMixin:
             pass
 
     def setUp(self):
-        super(FileBugViewMixin, self).setUp()
+        super().setUp()
         self.target = self.factory.makeProduct()
         transaction.commit()
         login_person(self.target.owner)
@@ -369,7 +369,7 @@ class TestFileBugViewBase(FileBugViewMixin, TestCaseWithFactory):
         product.bug_reporting_guidelines = "Include bug details"
         view = create_initialized_view(product, '+filebug')
         expected_guidelines = [{
-            "source": product.displayname, "content": u"Include bug details",
+            "source": product.displayname, "content": "Include bug details",
             }]
         self.assertEqual(expected_guidelines, view.bug_reporting_guidelines)
 
@@ -757,7 +757,7 @@ class FileBugViewBaseExtraDataTestCase(FileBugViewMixin, TestCaseWithFactory):
         view.publishTraverse(view.request, token)
         view.validate(self.get_form())
         expected = [
-            u'The description and the additional information is too long. '
+            'The description and the additional information is too long. '
             'If you have lots of text to add, attach a file to the bug '
             'instead.']
         self.assertContentEqual(expected, view.errors)
@@ -827,13 +827,11 @@ class TestFileBugSourcePackage(WithScenarios, TestCaseWithFactory):
 
     scenarios = [
         ("bspn_picker", {"features": {}}),
-        ("dsp_picker", {
-            "features": {u"disclosure.dsp_picker.enabled": u"on"},
-            }),
+        ("dsp_picker", {"features": {"disclosure.dsp_picker.enabled": "on"}}),
         ]
 
     def setUp(self):
-        super(TestFileBugSourcePackage, self).setUp()
+        super().setUp()
         if self.features:
             self.useFixture(FeatureFixture(self.features))
 
@@ -912,7 +910,7 @@ class ProjectGroupFileBugGuidedViewTestCase(TestCaseWithFactory):
 
     def test_redirect_to_project(self):
         # The view redirects to the select sub project.
-        view = self.makeProjectGroupFileBugView('fnord', 'A bug', u'is os')
+        view = self.makeProjectGroupFileBugView('fnord', 'A bug', 'is os')
         response = view.request.response
         self.assertEqual(302, response.getStatus())
         self.assertEqual(
@@ -923,7 +921,7 @@ class ProjectGroupFileBugGuidedViewTestCase(TestCaseWithFactory):
 
     def test_redirect_to_project_unicode_summary(self):
         # The summary is reencoded properly when it contains unicode.
-        view = self.makeProjectGroupFileBugView('fnord', u'caf\xe9', '')
+        view = self.makeProjectGroupFileBugView('fnord', 'caf\xe9', '')
         response = view.request.response
         self.assertEqual(
             'http://bugs.launchpad.test/fnord/+filebug?'
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_patches_view.py b/lib/lp/bugs/browser/tests/test_bugtarget_patches_view.py
index 690a785..fad5f48 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_patches_view.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_patches_view.py
@@ -19,7 +19,7 @@ class TestBugTargetPatchCountBase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestBugTargetPatchCountBase, self).setUp()
+        super().setUp()
         login('foo.bar@xxxxxxxxxxxxx')
         self.product = self.factory.makeProduct()
 
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_subscription.py b/lib/lp/bugs/browser/tests/test_bugtarget_subscription.py
index 38280d2..6b881cf 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_subscription.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_subscription.py
@@ -18,7 +18,7 @@ class TargetSubscriptionViewTestCase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TargetSubscriptionViewTestCase, self).setUp()
+        super().setUp()
         self.product = self.factory.makeProduct(
             name='widgetsrus', displayname='Widgets R Us')
         self.subscriber = self.factory.makePerson()
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_tags.py b/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
index 4e48b2e..9837a90 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
@@ -45,7 +45,7 @@ class TestBugTargetTags(WithScenarios, TestCaseWithFactory):
         return ociproject, ociproject
 
     def setUp(self):
-        super(TestBugTargetTags, self).setUp()
+        super().setUp()
         builder = getattr(self, self.factory_name)
         self.view_context, self.bug_target = builder()
 
@@ -57,26 +57,26 @@ class TestBugTargetTags(WithScenarios, TestCaseWithFactory):
         self.assertEqual([], [tag['tag'] for tag in view.tags_cloud_data])
 
     def test_tags(self):
-        self.factory.makeBug(target=self.bug_target, tags=[u'foo'])
+        self.factory.makeBug(target=self.bug_target, tags=['foo'])
         view = create_view(
             self.view_context,
             name="+bugtarget-portlet-tags-content")
         self.assertEqual(
-            [u'foo'],
+            ['foo'],
             [tag['tag'] for tag in view.tags_cloud_data])
 
     def test_tags_order(self):
         """Test that the tags are ordered by most used first"""
-        self.factory.makeBug(target=self.bug_target, tags=[u'tag-last'])
+        self.factory.makeBug(target=self.bug_target, tags=['tag-last'])
         for counter in range(0, 2):
             self.factory.makeBug(
-                target=self.bug_target, tags=[u'tag-middle'])
+                target=self.bug_target, tags=['tag-middle'])
         for counter in range(0, 3):
             self.factory.makeBug(
-                target=self.bug_target, tags=[u'tag-first'])
+                target=self.bug_target, tags=['tag-first'])
         view = create_view(
             self.view_context,
             name="+bugtarget-portlet-tags-content")
         self.assertEqual(
-            [u'tag-first', u'tag-middle', u'tag-last'],
+            ['tag-first', 'tag-middle', 'tag-last'],
             [tag['tag'] for tag in view.tags_cloud_data])
diff --git a/lib/lp/bugs/browser/tests/test_bugtask.py b/lib/lp/bugs/browser/tests/test_bugtask.py
index 5eb97d6..d53dd1b 100644
--- a/lib/lp/bugs/browser/tests/test_bugtask.py
+++ b/lib/lp/bugs/browser/tests/test_bugtask.py
@@ -186,7 +186,7 @@ class TestBugTaskView(TestCaseWithFactory):
         # `BugActivityItem`s.
         bug = self.factory.makeBug()
         view = create_initialized_view(
-            bug.default_bugtask, name=u'+index', rootsite='bugs')
+            bug.default_bugtask, name='+index', rootsite='bugs')
 
         def add_activity(what, old=None, new=None, message=None):
             getUtility(IBugActivitySet).new(
@@ -268,7 +268,7 @@ class TestBugTaskView(TestCaseWithFactory):
                 '%s.actions.save' % product.name: 'Save Changes',
                 }
             view = create_initialized_view(
-                bug.default_bugtask, name=u'+editstatus',
+                bug.default_bugtask, name='+editstatus',
                 form=form_data)
             # The bugtask's target won't have changed, since an error
             # happend. The error will be listed in the view.
@@ -304,9 +304,9 @@ class TestBugTaskView(TestCaseWithFactory):
         product = self.factory.makeProduct(name='foobar')
         bug = self.factory.makeBug(target=product, tags=['depends-on+987'])
         getUtility(ILaunchBag).add(bug.default_bugtask)
-        view = create_initialized_view(bug.default_bugtask, name=u'+index')
-        expected = [(u'depends-on+987',
-            u'/foobar/+bugs?field.tag=depends-on%2B987')]
+        view = create_initialized_view(bug.default_bugtask, name='+index')
+        expected = [('depends-on+987',
+            '/foobar/+bugs?field.tag=depends-on%2B987')]
         self.assertEqual(expected, view.unofficial_tags)
         browser = self.getUserBrowser(canonical_url(bug), bug.owner)
         self.assertIn(
@@ -367,7 +367,7 @@ class TestBugTasksNominationsView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugTasksNominationsView, self).setUp()
+        super().setUp()
         login(ADMIN_EMAIL)
         self.bug = self.factory.makeBug()
         self.view = BugTasksNominationsView(self.bug, LaunchpadTestRequest())
@@ -602,7 +602,7 @@ class TestBugTasksTableView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugTasksTableView, self).setUp()
+        super().setUp()
         login(ADMIN_EMAIL)
         self.bug = self.factory.makeBug()
         self.view = BugTasksTableView(self.bug, LaunchpadTestRequest())
@@ -1198,7 +1198,7 @@ class TestBugTaskEditViewStatusField(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugTaskEditViewStatusField, self).setUp()
+        super().setUp()
         bug_supervisor = self.factory.makePerson(name='bug-supervisor')
         product = self.factory.makeProduct(bug_supervisor=bug_supervisor)
         self.bug = self.factory.makeBug(target=product)
@@ -1282,7 +1282,7 @@ class TestBugTaskEditViewAssigneeField(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugTaskEditViewAssigneeField, self).setUp()
+        super().setUp()
         self.owner = self.factory.makePerson()
         self.product = self.factory.makeProduct(owner=self.owner)
         self.bugtask = self.factory.makeBug(
@@ -1331,13 +1331,13 @@ class TestBugTaskEditView(WithScenarios, TestCaseWithFactory):
     scenarios = [
         ("spn_picker", {"features": {}, "allow_binarypackagename": True}),
         ("dsp_picker", {
-            "features": {u"disclosure.dsp_picker.enabled": u"on"},
+            "features": {"disclosure.dsp_picker.enabled": "on"},
             "allow_binarypackagename": False,
             }),
         ]
 
     def setUp(self):
-        super(TestBugTaskEditView, self).setUp()
+        super().setUp()
         if self.features:
             self.useFixture(FeatureFixture(self.features))
 
@@ -1601,12 +1601,12 @@ class BugTaskViewTestMixin():
 
     def _assert_shouldShowStructuralSubscriberWidget(self, show=True):
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertEqual(show, view.shouldShowStructuralSubscriberWidget())
 
     def _assert_structural_subscriber_label(self, label):
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertEqual(label, view.structural_subscriber_label)
 
     def test_mustache_cache_is_none_for_feed(self):
@@ -1618,7 +1618,7 @@ class BugTaskViewTestMixin():
         """No mustache model for the advanced search form."""
         form = {'advanced': 1}
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs', form=form)
+            self.target, name='+bugs', rootsite='bugs', form=form)
         cache = IJSONRequestCache(view.request)
         self.assertIsNone(cache.objects.get('mustache_model'))
 
@@ -1629,7 +1629,7 @@ class TestPersonBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestPersonBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makePerson()
 
     def test_shouldShowStructuralSubscriberWidget(self):
@@ -1646,7 +1646,7 @@ class TestDistributionBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestDistributionBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeDistribution()
 
     def test_structural_subscriber_label(self):
@@ -1663,7 +1663,7 @@ class TestOCIProjectOfProductBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestOCIProjectOfProductBugs, self).setUp()
+        super().setUp()
         self.initTarget()
 
     def initTarget(self):
@@ -1694,7 +1694,7 @@ class TestDistroSeriesBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestDistroSeriesBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeDistroSeries()
 
     def test_shouldShowStructuralSubscriberWidget(self):
@@ -1711,7 +1711,7 @@ class TestDistributionSourcePackageBugs(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestDistributionSourcePackageBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeDistributionSourcePackage()
 
     def test_shouldShowStructuralSubscriberWidget(self):
@@ -1725,7 +1725,7 @@ class TestDistroSeriesSourcePackageBugs(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestDistroSeriesSourcePackageBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeSourcePackage()
 
     def test_shouldShowStructuralSubscriberWidget(self):
@@ -1738,7 +1738,7 @@ class TestProductBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProductBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeProduct()
 
     def test_shouldShowStructuralSubscriberWidget(self):
@@ -1754,7 +1754,7 @@ class TestProductSeriesBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProductSeriesBugs, self).setUp()
+        super().setUp()
         self.target = self.factory.makeProductSeries()
 
 
@@ -1764,7 +1764,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProjectGroupBugs, self).setUp()
+        super().setUp()
         self.owner = self.factory.makePerson(name='bob')
         self.target = self.factory.makeProject(
             name='container', owner=self.owner)
@@ -1778,7 +1778,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
     def test_empty_project_group(self):
         # An empty project group does not use Launchpad for bugs.
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertFalse(self.target.hasProducts())
         self.assertFalse(view.should_show_bug_information)
 
@@ -1788,7 +1788,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         self.makeSubordinateProduct(False)
         self.assertTrue(self.target.hasProducts())
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertFalse(view.should_show_bug_information)
 
     def test_project_group_with_subordinate_using_launchpad(self):
@@ -1797,7 +1797,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         self.makeSubordinateProduct(True)
         self.assertTrue(self.target.hasProducts())
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertTrue(view.should_show_bug_information)
 
     def test_project_group_with_mixed_subordinates(self):
@@ -1807,7 +1807,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         self.makeSubordinateProduct(True)
         self.assertTrue(self.target.hasProducts())
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs')
+            self.target, name='+bugs', rootsite='bugs')
         self.assertTrue(view.should_show_bug_information)
 
     def test_project_group_has_no_portlets_if_not_using_LP(self):
@@ -1815,7 +1815,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         # bug portlets.
         self.makeSubordinateProduct(False)
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs', current_request=True)
+            self.target, name='+bugs', rootsite='bugs', current_request=True)
         self.assertFalse(view.should_show_bug_information)
         contents = view.render()
         report_a_bug = find_tag_by_id(contents, 'bug-portlets')
@@ -1826,7 +1826,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         # portlets.
         self.makeSubordinateProduct(True)
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs', current_request=True)
+            self.target, name='+bugs', rootsite='bugs', current_request=True)
         self.assertTrue(view.should_show_bug_information)
         contents = view.render()
         report_a_bug = find_tag_by_id(contents, 'bug-portlets')
@@ -1837,7 +1837,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         # a 'Getting started' help link.
         self.makeSubordinateProduct(False)
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs', current_request=True)
+            self.target, name='+bugs', rootsite='bugs', current_request=True)
         contents = view.render()
         help_link = find_tag_by_id(contents, 'getting-started-help')
         self.assertIsNot(None, help_link)
@@ -1847,7 +1847,7 @@ class TestProjectGroupBugs(TestCaseWithFactory, BugTaskViewTestMixin):
         # a 'Getting started' help link.
         self.makeSubordinateProduct(True)
         view = create_initialized_view(
-            self.target, name=u'+bugs', rootsite='bugs', current_request=True)
+            self.target, name='+bugs', rootsite='bugs', current_request=True)
         contents = view.render()
         help_link = find_tag_by_id(contents, 'getting-started-help')
         self.assertIs(None, help_link)
@@ -2524,7 +2524,7 @@ class TestBugTaskSearchListingView(BrowserTestCase):
             canonical_url(product, view_name='+bugs') +
             '/?field.tag=depends-on%2B987')
         self.assertEqual(
-            [{'url': expected_url, 'tag': u'depends-on+987'}], tags)
+            [{'url': expected_url, 'tag': 'depends-on+987'}], tags)
 
 
 class TestBugTaskExpirableListingView(BrowserTestCase):
@@ -2543,7 +2543,7 @@ class TestBugTaskExpirableListingView(BrowserTestCase):
         title = bug.title
         content = self.getMainContent(
             bug.default_bugtask.target, "+expirable-bugs")
-        self.assertIn(title, six.text_type(content))
+        self.assertIn(title, str(content))
 
 
 class TestBugListingBatchNavigator(TestCaseWithFactory):
diff --git a/lib/lp/bugs/browser/tests/test_bugtask_adding.py b/lib/lp/bugs/browser/tests/test_bugtask_adding.py
index 378b38d..a0a73a6 100644
--- a/lib/lp/bugs/browser/tests/test_bugtask_adding.py
+++ b/lib/lp/bugs/browser/tests/test_bugtask_adding.py
@@ -21,7 +21,7 @@ class TestProductBugTaskCreationStep(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProductBugTaskCreationStep, self).setUp()
+        super().setUp()
         ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
         self.ubuntu_series = ubuntu['hoary']
         self.sourcepackagename = self.factory.makeSourcePackageName('bat')
diff --git a/lib/lp/bugs/browser/tests/test_bugtracker_component.py b/lib/lp/bugs/browser/tests/test_bugtracker_component.py
index e294de6..bcf26d0 100644
--- a/lib/lp/bugs/browser/tests/test_bugtracker_component.py
+++ b/lib/lp/bugs/browser/tests/test_bugtracker_component.py
@@ -20,13 +20,13 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(BugTrackerEditComponentViewTextCase, self).setUp()
+        super().setUp()
         regular_user = self.factory.makePerson()
         login_person(regular_user)
 
         self.bug_tracker = self.factory.makeBugTracker()
         self.comp_group = self.factory.makeBugTrackerComponentGroup(
-            u'alpha', self.bug_tracker)
+            'alpha', self.bug_tracker)
 
     def _makeForm(self, sourcepackage):
         if sourcepackage is None:
@@ -47,7 +47,7 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
             distroseries=distro.currentseries, sourcepackagename=package_name)
 
     def test_view_attributes(self):
-        component = self._makeComponent(u'Example')
+        component = self._makeComponent('Example')
         dsp = self._makeUbuntuSourcePackage('example')
         form = self._makeForm(dsp)
         view = create_initialized_view(
@@ -61,7 +61,7 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
         self.assertEqual(url, view.cancel_url)
 
     def test_linking(self):
-        component = self._makeComponent(u'Example')
+        component = self._makeComponent('Example')
         dsp = self._makeUbuntuSourcePackage('example')
         form = self._makeForm(dsp)
 
@@ -70,7 +70,7 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
         self.assertEqual(dsp, component.distro_source_package)
 
     def test_linking_notifications(self):
-        component = self._makeComponent(u'Example')
+        component = self._makeComponent('Example')
         dsp = self._makeUbuntuSourcePackage('example')
         form = self._makeForm(dsp)
 
@@ -85,7 +85,7 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
             expected, notifications.pop().message)
 
     def test_unlinking(self):
-        component = self._makeComponent(u'Example')
+        component = self._makeComponent('Example')
         dsp = self._makeUbuntuSourcePackage('example')
         component.distro_source_package = dsp
         form = self._makeForm(None)
@@ -106,8 +106,8 @@ class BugTrackerEditComponentViewTextCase(TestCaseWithFactory):
         # to make multiple components linked to the same source package,
         # so the view needs to be sure to not allow this to be done and
         # pop up a friendly error message instead.
-        component_a = self._makeComponent(u'a')
-        component_b = self._makeComponent(u'b')
+        component_a = self._makeComponent('a')
+        component_b = self._makeComponent('b')
         package = self._makeUbuntuSourcePackage('example')
         form = self._makeForm(package)
 
diff --git a/lib/lp/bugs/browser/tests/test_bugview.py b/lib/lp/bugs/browser/tests/test_bugview.py
index fae96b8..a4685c0 100644
--- a/lib/lp/bugs/browser/tests/test_bugview.py
+++ b/lib/lp/bugs/browser/tests/test_bugview.py
@@ -25,7 +25,7 @@ class TestBugView(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestBugView, self).setUp()
+        super().setUp()
         login('test@xxxxxxxxxxxxx')
         self.bug = self.factory.makeBug()
         self.view = BugView(self.bug, LaunchpadTestRequest())
@@ -67,7 +67,7 @@ class TestBugInformationTypePortletView(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBugInformationTypePortletView, self).setUp()
+        super().setUp()
         login('test@xxxxxxxxxxxxx')
         self.bug = self.factory.makeBug()
         self.view = BugInformationTypePortletView(
diff --git a/lib/lp/bugs/browser/tests/test_bugwatch_views.py b/lib/lp/bugs/browser/tests/test_bugwatch_views.py
index cdda6a4..6e32227 100644
--- a/lib/lp/bugs/browser/tests/test_bugwatch_views.py
+++ b/lib/lp/bugs/browser/tests/test_bugwatch_views.py
@@ -25,7 +25,7 @@ class TestBugWatchEditView(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestBugWatchEditView, self).setUp()
+        super().setUp()
         self.person = self.factory.makePerson()
 
         login_person(self.person)
diff --git a/lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py b/lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py
index a3f259a..155b233 100644
--- a/lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py
+++ b/lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py
@@ -23,7 +23,7 @@ class TestConfigureBugTrackerBase(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestConfigureBugTrackerBase, self).setUp()
+        super().setUp()
         login('test@xxxxxxxxxxxxx')
         self.target = self.makeTarget()
         self.menu = self.getMenu()
diff --git a/lib/lp/bugs/browser/tests/test_cve.py b/lib/lp/bugs/browser/tests/test_cve.py
index 93bc073..12aa9c8 100644
--- a/lib/lp/bugs/browser/tests/test_cve.py
+++ b/lib/lp/bugs/browser/tests/test_cve.py
@@ -31,7 +31,7 @@ class TestCVEReportView(TestCaseWithFactory):
 
     def setUp(self):
         """Create a few bugtasks and CVEs."""
-        super(TestCVEReportView, self).setUp()
+        super().setUp()
         distroseries = self.factory.makeDistroSeries()
         self.resolved_bugtasks = []
         self.unresolved_bugtasks = []
diff --git a/lib/lp/bugs/browser/tests/test_expose.py b/lib/lp/bugs/browser/tests/test_expose.py
index 3ee4951..f0c5bc5 100644
--- a/lib/lp/bugs/browser/tests/test_expose.py
+++ b/lib/lp/bugs/browser/tests/test_expose.py
@@ -92,7 +92,7 @@ class TestExposeAdministeredTeams(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestExposeAdministeredTeams, self).setUp()
+        super().setUp()
         self.request = FakeRequest()
         self.user = self.factory.makePerson()
 
@@ -123,9 +123,9 @@ class TestExposeAdministeredTeams(TestCaseWithFactory):
         expose_user_administered_teams_to_js(self.request, self.user, context,
             absoluteURL=fake_absoluteURL)
         team_info = self.request.objects['administratedTeams']
-        self.assertThat(team_info[0]['title'], Equals(u'Team 1 (team-1)'))
+        self.assertThat(team_info[0]['title'], Equals('Team 1 (team-1)'))
         self.assertThat(team_info[0]['has_preferredemail'], Equals(False))
-        self.assertThat(team_info[1]['title'], Equals(u'Team 2 (team-2)'))
+        self.assertThat(team_info[1]['title'], Equals('Team 2 (team-2)'))
         self.assertThat(team_info[1]['has_preferredemail'], Equals(True))
 
     def test_teams_for_non_distro(self):
@@ -154,15 +154,15 @@ class TestExposeAdministeredTeams(TestCaseWithFactory):
         # The link is the unique display name of the team.
         self.assertThat(
             team_info[0]['title'],
-            Equals(u'Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
+            Equals('Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
         self.assertThat(
             team_info[1]['title'],
-            Equals(u'Bug Supervisor Team (bug-supervisor-team)'))
+            Equals('Bug Supervisor Team (bug-supervisor-team)'))
         self.assertThat(
-            team_info[2]['title'], Equals(u'Unrelated Team (unrelated-team)'))
+            team_info[2]['title'], Equals('Unrelated Team (unrelated-team)'))
         # The link is the API link to the team.
         self.assertThat(team_info[0]['link'],
-            Equals(u'http://example.com/bug-supervisor-sub-team'))
+            Equals('http://example.com/bug-supervisor-sub-team'))
 
     def test_query_count(self):
         # The function issues a constant number of queries regardless of
@@ -265,13 +265,13 @@ class TestExposeAdministeredTeams(TestCaseWithFactory):
         # The link is the unique display name of the team.
         self.assertThat(
             team_info[0]['title'],
-            Equals(u'Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
+            Equals('Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
         self.assertThat(
             team_info[1]['title'],
-            Equals(u'Bug Supervisor Team (bug-supervisor-team)'))
+            Equals('Bug Supervisor Team (bug-supervisor-team)'))
         # The link is the API link to the team.
         self.assertThat(team_info[0]['link'],
-            Equals(u'http://example.com/bug-supervisor-sub-team'))
+            Equals('http://example.com/bug-supervisor-sub-team'))
 
     def test_teams_for_distro_with_no_bug_super(self):
         self._setup_teams(self.user)
@@ -297,15 +297,15 @@ class TestExposeAdministeredTeams(TestCaseWithFactory):
         # The link is the unique display name of the team.
         self.assertThat(
             team_info[0]['title'],
-            Equals(u'Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
+            Equals('Bug Supervisor Sub Team (bug-supervisor-sub-team)'))
         self.assertThat(
             team_info[1]['title'],
-            Equals(u'Bug Supervisor Team (bug-supervisor-team)'))
+            Equals('Bug Supervisor Team (bug-supervisor-team)'))
         self.assertThat(
-            team_info[2]['title'], Equals(u'Unrelated Team (unrelated-team)'))
+            team_info[2]['title'], Equals('Unrelated Team (unrelated-team)'))
         # The link is the API link to the team.
         self.assertThat(team_info[0]['link'],
-            Equals(u'http://example.com/bug-supervisor-sub-team'))
+            Equals('http://example.com/bug-supervisor-sub-team'))
 
 
 class TestStructuralSubscriptionHelpers(TestCase):
diff --git a/lib/lp/bugs/browser/tests/test_structuralsubscription.py b/lib/lp/bugs/browser/tests/test_structuralsubscription.py
index 89d8e07..a6fd6a9 100644
--- a/lib/lp/bugs/browser/tests/test_structuralsubscription.py
+++ b/lib/lp/bugs/browser/tests/test_structuralsubscription.py
@@ -36,7 +36,7 @@ class StructuralSubscriptionTraversalTestBase(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(StructuralSubscriptionTraversalTestBase, self).setUp()
+        super().setUp()
         login('foo.bar@xxxxxxxxxxxxx')
         self.eric = self.factory.makePerson(name='eric')
         self.michael = self.factory.makePerson(name='michael')
@@ -84,7 +84,7 @@ class StructuralSubscriptionTraversalTestBase(TestCaseWithFactory):
 
     def tearDown(self):
         logout()
-        super(StructuralSubscriptionTraversalTestBase, self).tearDown()
+        super().tearDown()
 
 
 class TestProductSeriesStructuralSubscriptionTraversal(
@@ -171,7 +171,7 @@ class TestStructuralSubscribersPortletViewBase(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestStructuralSubscribersPortletViewBase, self).setUp()
+        super().setUp()
         self.setUpTarget()
         self.view = create_initialized_view(
             self.target, name='+portlet-structural-subscribers')
@@ -217,10 +217,9 @@ class TestStructuralSubscriptionAPI(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestStructuralSubscriptionAPI, self).setUp()
-        self.owner = self.factory.makePerson(name=u"foo")
-        self.structure = self.factory.makeProduct(
-            owner=self.owner, name=u"bar")
+        super().setUp()
+        self.owner = self.factory.makePerson(name="foo")
+        self.structure = self.factory.makeProduct(owner=self.owner, name="bar")
         with person_logged_in(self.owner):
             self.subscription = self.structure.addBugSubscription(
                 self.owner, self.owner)
diff --git a/lib/lp/bugs/browser/widgets/bug.py b/lib/lp/bugs/browser/widgets/bug.py
index e203d39..ae41daa 100644
--- a/lib/lp/bugs/browser/widgets/bug.py
+++ b/lib/lp/bugs/browser/widgets/bug.py
@@ -88,7 +88,7 @@ class BugTagsWidgetBase:
         if tags is None:
             return self._missing
         else:
-            return u" ".join(tags)
+            return " ".join(tags)
 
     def _toFieldValue(self, input):
         """Convert a space separated string to a list of strings."""
@@ -139,7 +139,7 @@ class BugTagsWidget(BugTagsWidgetBase, TextWidget):
 
     def __call__(self):
         """Return the input with a script."""
-        input_markup = super(BugTagsWidget, self).__call__()
+        input_markup = super().__call__()
         script_markup = """
             <a href="/+help-bugs/tag-search.html"
                class="sprite maybe action-icon"
diff --git a/lib/lp/bugs/browser/widgets/bugtask.py b/lib/lp/bugs/browser/widgets/bugtask.py
index 621ab69..c6ace3d 100644
--- a/lib/lp/bugs/browser/widgets/bugtask.py
+++ b/lib/lp/bugs/browser/widgets/bugtask.py
@@ -16,7 +16,6 @@ __all__ = [
     "NewLineToSpacesWidget",
     ]
 
-import six
 from zope.browserpage import ViewPageTemplateFile
 from zope.component import getUtility
 from zope.formlib.interfaces import (
@@ -378,8 +377,7 @@ class BugTaskBugWatchWidget(RadioWidget):
         #      value instead of a valid field value.
         if value == self._missing:
             value = self.context.missing_value
-        elif (isinstance(value, six.string_types) and
-              value != self._new_bugwatch_value):
+        elif isinstance(value, str) and value != self._new_bugwatch_value:
             value = self._toFieldValue(value)
         # check if we want to select first item, the previously selected item
         # or the "nothing selected" item.
@@ -434,7 +432,7 @@ class BugTaskBugWatchWidget(RadioWidget):
         access to the id.
         """
         id = '%s.%s' % (name, index)
-        elem = renderElement(u'input',
+        elem = renderElement('input',
                              value=value,
                              name=name,
                              id=id,
@@ -450,7 +448,7 @@ class BugTaskBugWatchWidget(RadioWidget):
         access to the id.
         """
         id = '%s.%s' % (name, index)
-        elem = renderElement(u'input',
+        elem = renderElement('input',
                              value=value,
                              name=name,
                              id=id,
@@ -522,7 +520,7 @@ class BugTaskTargetWidget(LaunchpadTargetWidget):
                         " Launchpad" % entered_name))
                 raise self._error
             return self.package_widget.getInputValue() or distribution
-        return super(BugTaskTargetWidget, self).getInputValue()
+        return super().getInputValue()
 
     def setRenderedValue(self, value):
         self.setUpSubWidgets()
@@ -539,7 +537,7 @@ class BugTaskTargetWidget(LaunchpadTargetWidget):
                 self.package_widget.setRenderedValue(value)
                 self._syncPackageVocabularyDistribution(value.pillar)
         else:
-            super(BugTaskTargetWidget, self).setRenderedValue(value)
+            super().setRenderedValue(value)
 
 
 class BugTaskSourcePackageNameWidget(SourcePackageNameWidgetBase):
@@ -601,8 +599,7 @@ class FileBugSourcePackageNameWidget(SourcePackageNameWidgetBase):
 
     def _toFieldValue(self, input):
         """See `SourcePackageNameWidgetBase`."""
-        source = super(FileBugSourcePackageNameWidget, self)._toFieldValue(
-            input)
+        source = super()._toFieldValue(input)
         if (source is not None and
                 not bool(getFeatureFlag('disclosure.dsp_picker.enabled'))):
             # XXX cjwatson 2016-07-25: Convert to a value that the
@@ -623,7 +620,7 @@ class AssigneeDisplayWidget(BrowserWidget):
     """A widget for displaying an assignee."""
 
     def __init__(self, context, vocabulary, request):
-        super(AssigneeDisplayWidget, self).__init__(context, request)
+        super().__init__(context, request)
 
     def __call__(self):
         assignee_field = self.context
@@ -651,7 +648,7 @@ class DBItemDisplayWidget(BrowserWidget):
     """A widget for displaying a bugtask dbitem."""
 
     def __init__(self, context, vocabulary, request):
-        super(DBItemDisplayWidget, self).__init__(context, request)
+        super().__init__(context, request)
 
     def __call__(self):
         dbitem_field = self.context
diff --git a/lib/lp/bugs/browser/widgets/tests/test_bug.py b/lib/lp/bugs/browser/widgets/tests/test_bug.py
index 2a2d6c3..4bb797a 100644
--- a/lib/lp/bugs/browser/widgets/tests/test_bug.py
+++ b/lib/lp/bugs/browser/widgets/tests/test_bug.py
@@ -39,7 +39,7 @@ class BugTagsWidgetTestCase(TestCaseWithFactory):
         # Products with tags have a list of tags.
         product = self.factory.makeProduct()
         with person_logged_in(product.owner):
-            product.official_bug_tags = [u'cows', u'pigs', u'sheep']
+            product.official_bug_tags = ['cows', 'pigs', 'sheep']
         widget = self.get_widget(product)
         js = widget.official_tags_js
         self.assertEqual('var official_tags = ["cows", "pigs", "sheep"];', js)
@@ -55,7 +55,7 @@ class BugTagsWidgetTestCase(TestCaseWithFactory):
         # Distributions with tags have a list of tags.
         distribution = self.factory.makeDistribution()
         with person_logged_in(distribution.owner):
-            distribution.official_bug_tags = [u'cows', u'pigs', u'sheep']
+            distribution.official_bug_tags = ['cows', 'pigs', 'sheep']
         widget = self.get_widget(distribution)
         js = widget.official_tags_js
         self.assertEqual('var official_tags = ["cows", "pigs", "sheep"];', js)
@@ -65,7 +65,7 @@ class BugTagsWidgetTestCase(TestCaseWithFactory):
         # Products with tags have a list of tags.
         product = self.factory.makeProduct()
         with person_logged_in(product.owner):
-            product.official_bug_tags = [u'cows', u'pigs', u'sheep']
+            product.official_bug_tags = ['cows', 'pigs', 'sheep']
         widget = self.get_widget(product)
         markup = widget()
         self.assertIn(
diff --git a/lib/lp/bugs/externalbugtracker/base.py b/lib/lp/bugs/externalbugtracker/base.py
index 8ce49ef..6ebd4bc 100644
--- a/lib/lp/bugs/externalbugtracker/base.py
+++ b/lib/lp/bugs/externalbugtracker/base.py
@@ -324,7 +324,7 @@ class LookupBranch(treelookup.LookupBranch):
             raise TypeError(
                 'Result is not a member of BugTaskStatus: %r' % (
                     self.result))
-        super(LookupBranch, self)._verify()
+        super()._verify()
 
     def _describe_result(self, result):
         """See `treelookup.LookupBranch._describe_result`."""
diff --git a/lib/lp/bugs/externalbugtracker/bugzilla.py b/lib/lp/bugs/externalbugtracker/bugzilla.py
index a84a575..fa5f448 100644
--- a/lib/lp/bugs/externalbugtracker/bugzilla.py
+++ b/lib/lp/bugs/externalbugtracker/bugzilla.py
@@ -19,7 +19,6 @@ import xmlrpc.client
 from defusedxml import minidom
 import pytz
 import requests
-import six
 from zope.component import getUtility
 from zope.interface import (
     alsoProvides,
@@ -66,7 +65,7 @@ class Bugzilla(ExternalBugTracker):
     _test_xmlrpc_proxy = None
 
     def __init__(self, baseurl, version=None):
-        super(Bugzilla, self).__init__(baseurl)
+        super().__init__(baseurl)
         self.version = self._parseVersion(version)
         self.is_issuezilla = False
         self.remote_bug_status = {}
@@ -185,7 +184,7 @@ class Bugzilla(ExternalBugTracker):
         # high bit set for non-ASCII characters, we can now strip out any
         # ASCII control characters without touching encoded Unicode
         # characters.
-        bad_chars = b''.join(six.int2byte(i) for i in range(0, 32))
+        bad_chars = b''.join(bytes((i,)) for i in range(0, 32))
         for char in b'\n', b'\r', b'\t':
             bad_chars = bad_chars.replace(char, b'')
         trans_map = bytes.maketrans(bad_chars, b' ' * len(bad_chars))
@@ -333,7 +332,7 @@ class Bugzilla(ExternalBugTracker):
         if self.version is None:
             self.version = self._probe_version()
 
-        super(Bugzilla, self).initializeRemoteBugDB(bug_ids)
+        super().initializeRemoteBugDB(bug_ids)
 
     def getRemoteBug(self, bug_id):
         """See `ExternalBugTracker`."""
@@ -561,7 +560,7 @@ class BugzillaAPI(Bugzilla):
 
     def __init__(self, baseurl, xmlrpc_transport=None,
                  internal_xmlrpc_transport=None):
-        super(BugzillaAPI, self).__init__(baseurl)
+        super().__init__(baseurl)
         self._bugs = {}
         self._bug_aliases = {}
 
@@ -639,7 +638,7 @@ class BugzillaAPI(Bugzilla):
             # Some versions of Bugzilla return a single alias string,
             # others return a (possibly empty) list.
             aliases = remote_bug.get('alias', '')
-            if isinstance(aliases, six.string_types):
+            if isinstance(aliases, str):
                 aliases = [] if not aliases else [aliases]
             for alias in aliases:
                 self._bug_aliases[alias] = remote_bug['id']
diff --git a/lib/lp/bugs/externalbugtracker/debbugs.py b/lib/lp/bugs/externalbugtracker/debbugs.py
index 89b252c..b34d2c8 100644
--- a/lib/lp/bugs/externalbugtracker/debbugs.py
+++ b/lib/lp/bugs/externalbugtracker/debbugs.py
@@ -73,7 +73,7 @@ class DebBugs(ExternalBugTracker):
     batch_size = BATCH_SIZE_UNLIMITED
 
     def __init__(self, baseurl, db_location=None):
-        super(DebBugs, self).__init__(baseurl)
+        super().__init__(baseurl)
         # debbugs syncing can be enabled/disabled separately.
         self.sync_comments = (
             self.sync_comments and
diff --git a/lib/lp/bugs/externalbugtracker/github.py b/lib/lp/bugs/externalbugtracker/github.py
index d5b6f25..4e686ee 100644
--- a/lib/lp/bugs/externalbugtracker/github.py
+++ b/lib/lp/bugs/externalbugtracker/github.py
@@ -134,7 +134,7 @@ class GitHub(ExternalBugTracker):
             raise BadGitHubURL(baseurl)
         path = "/repos" + path[:-len("/issues")]
         baseurl = urlunsplit(("https", host, path, query, fragment))
-        super(GitHub, self).__init__(baseurl)
+        super().__init__(baseurl)
         self.cached_bugs = {}
 
     @property
@@ -220,7 +220,7 @@ class GitHub(ExternalBugTracker):
 
     def _getHeaders(self):
         """See `ExternalBugTracker`."""
-        headers = super(GitHub, self)._getHeaders()
+        headers = super()._getHeaders()
         headers["Accept"] = "application/vnd.github.v3+json"
         return headers
 
@@ -237,12 +237,11 @@ class GitHub(ExternalBugTracker):
                 url, self.timeout,
                 token=self.credentials["token"]) as auth_header:
             headers["Authorization"] = auth_header
-            return super(GitHub, self).makeRequest(
-                method, url, headers=headers)
+            return super().makeRequest(method, url, headers=headers)
 
     def _getPage(self, page, last_accessed=None, **kwargs):
         """See `ExternalBugTracker`."""
-        return super(GitHub, self)._getPage(
+        return super()._getPage(
             page, last_accessed=last_accessed, token=self.credentials["token"])
 
     def _getCollection(self, base_page, last_accessed=None):
@@ -262,8 +261,7 @@ class GitHub(ExternalBugTracker):
                     return
                 else:
                     raise
-            for item in response.json():
-                yield item
+            yield from response.json()
             if "next" in response.links:
                 page = response.links["next"]["url"]
             else:
diff --git a/lib/lp/bugs/externalbugtracker/gitlab.py b/lib/lp/bugs/externalbugtracker/gitlab.py
index d62552b..cc7ac40 100644
--- a/lib/lp/bugs/externalbugtracker/gitlab.py
+++ b/lib/lp/bugs/externalbugtracker/gitlab.py
@@ -48,7 +48,7 @@ class GitLab(ExternalBugTracker):
             raise BadGitLabURL(baseurl)
         path = "/api/v4/projects/%s" % quote(path[:-len("/issues")], safe="")
         baseurl = urlunsplit(("https", host, path, query, fragment))
-        super(GitLab, self).__init__(baseurl)
+        super().__init__(baseurl)
         self.cached_bugs = {}
 
     @property
@@ -145,7 +145,7 @@ class GitLab(ExternalBugTracker):
         token = self.credentials["token"]
         if token is not None:
             headers["Private-Token"] = token
-        return super(GitLab, self).makeRequest(method, url, headers=headers)
+        return super().makeRequest(method, url, headers=headers)
 
     def _getCollection(self, base_page, last_accessed=None):
         """Yield each item from a batched remote collection.
@@ -164,8 +164,7 @@ class GitLab(ExternalBugTracker):
                     return
                 else:
                     raise
-            for item in response.json():
-                yield item
+            yield from response.json()
             if "next" in response.links:
                 page = response.links["next"]["url"]
             else:
diff --git a/lib/lp/bugs/externalbugtracker/mantis.py b/lib/lp/bugs/externalbugtracker/mantis.py
index bd62d0a..40562da 100644
--- a/lib/lp/bugs/externalbugtracker/mantis.py
+++ b/lib/lp/bugs/externalbugtracker/mantis.py
@@ -175,7 +175,7 @@ class Mantis(ExternalBugTracker):
     """
 
     def __init__(self, baseurl):
-        super(Mantis, self).__init__(baseurl)
+        super().__init__(baseurl)
         self._cookie_jar = RequestsCookieJar()
         self._logger = logging.getLogger()
 
@@ -185,7 +185,7 @@ class Mantis(ExternalBugTracker):
         if not isinstance(hooks.setdefault('response', []), list):
             hooks['response'] = [hooks['response']]
         hooks['response'].append(mantis_login_hook)
-        return super(Mantis, self).makeRequest(
+        return super().makeRequest(
             method, url, cookies=self._cookie_jar, hooks=hooks, **kwargs)
 
     @cachedproperty
diff --git a/lib/lp/bugs/externalbugtracker/roundup.py b/lib/lp/bugs/externalbugtracker/roundup.py
index cf7a215..2bd3de2 100644
--- a/lib/lp/bugs/externalbugtracker/roundup.py
+++ b/lib/lp/bugs/externalbugtracker/roundup.py
@@ -161,7 +161,7 @@ class Roundup(ExternalBugTracker):
         The fields/columns to fetch from the remote bug tracker are
         derived based on the host part of the baseurl.
         """
-        super(Roundup, self).__init__(baseurl)
+        super().__init__(baseurl)
         self.host = URI(self.baseurl).host
 
         self._status_fields = (
diff --git a/lib/lp/bugs/externalbugtracker/rt.py b/lib/lp/bugs/externalbugtracker/rt.py
index cf33635..3819aa9 100644
--- a/lib/lp/bugs/externalbugtracker/rt.py
+++ b/lib/lp/bugs/externalbugtracker/rt.py
@@ -36,7 +36,7 @@ class RequestTracker(ExternalBugTracker):
     batch_query_threshold = 1
 
     def __init__(self, baseurl, cookie_jar=None):
-        super(RequestTracker, self).__init__(baseurl)
+        super().__init__(baseurl)
 
         if cookie_jar is None:
             cookie_jar = RequestsCookieJar()
@@ -66,7 +66,7 @@ class RequestTracker(ExternalBugTracker):
             # To log in to an RT instance we must pass a username and
             # password to its login form, as a user would from the web.
             try:
-                super(RequestTracker, self).makeRequest(
+                super().makeRequest(
                     'GET', '%s/' % self.baseurl,
                     params=self.credentials, cookies=self._cookie_jar)
             except requests.RequestException as e:
@@ -74,7 +74,7 @@ class RequestTracker(ExternalBugTracker):
                     "Unable to authenticate with remote RT service: "
                     "Could not submit login form: %s" % e)
             self._logged_in = True
-        return super(RequestTracker, self).makeRequest(
+        return super().makeRequest(
             method, url, cookies=self._cookie_jar, **kwargs)
 
     def getRemoteBug(self, bug_id):
diff --git a/lib/lp/bugs/externalbugtracker/tests/test_debbugs.py b/lib/lp/bugs/externalbugtracker/tests/test_debbugs.py
index 76e576e..a6cb72a 100644
--- a/lib/lp/bugs/externalbugtracker/tests/test_debbugs.py
+++ b/lib/lp/bugs/externalbugtracker/tests/test_debbugs.py
@@ -32,7 +32,7 @@ from lp.testing import TestCase
 class TestDebBugs(TestCase):
 
     def setUp(self):
-        super(TestDebBugs, self).setUp()
+        super().setUp()
         self.tempdir = self.makeTemporaryDirectory()
 
     def get_tracker(self):
diff --git a/lib/lp/bugs/externalbugtracker/tests/test_github.py b/lib/lp/bugs/externalbugtracker/tests/test_github.py
index 6c825b5..87cdafa 100644
--- a/lib/lp/bugs/externalbugtracker/tests/test_github.py
+++ b/lib/lp/bugs/externalbugtracker/tests/test_github.py
@@ -65,7 +65,7 @@ class TestGitHubRateLimit(TestCase):
     layer = ZopelessLayer
 
     def setUp(self):
-        super(TestGitHubRateLimit, self).setUp()
+        super().setUp()
         self.rate_limit = getUtility(IGitHubRateLimit)
         self.addCleanup(self.rate_limit.clearCache)
 
@@ -131,7 +131,7 @@ class TestGitHub(TestCase):
     layer = ZopelessLayer
 
     def setUp(self):
-        super(TestGitHub, self).setUp()
+        super().setUp()
         self.addCleanup(getUtility(IGitHubRateLimit).clearCache)
         self.sample_bugs = [
             {"id": 101, "number": 1, "state": "open", "labels": []},
diff --git a/lib/lp/bugs/externalbugtracker/tests/test_gitlab.py b/lib/lp/bugs/externalbugtracker/tests/test_gitlab.py
index 2810441..9fd7351 100644
--- a/lib/lp/bugs/externalbugtracker/tests/test_gitlab.py
+++ b/lib/lp/bugs/externalbugtracker/tests/test_gitlab.py
@@ -51,7 +51,7 @@ class TestGitLab(TestCase):
     layer = ZopelessLayer
 
     def setUp(self):
-        super(TestGitLab, self).setUp()
+        super().setUp()
         self.sample_bugs = [
             {"id": 101, "iid": 1, "state": "opened", "labels": []},
             {"id": 102, "iid": 2, "state": "opened", "labels": ["feature"]},
diff --git a/lib/lp/bugs/externalbugtracker/tests/test_mantis.py b/lib/lp/bugs/externalbugtracker/tests/test_mantis.py
index 2f6e11e..99de31b 100644
--- a/lib/lp/bugs/externalbugtracker/tests/test_mantis.py
+++ b/lib/lp/bugs/externalbugtracker/tests/test_mantis.py
@@ -24,7 +24,7 @@ class TestMantisBugBatchParser(TestCase):
     """Test the MantisBugBatchParser class."""
 
     def setUp(self):
-        super(TestMantisBugBatchParser, self).setUp()
+        super().setUp()
         self.logger = BufferLogger()
 
     def test_empty(self):
diff --git a/lib/lp/bugs/externalbugtracker/tests/test_xmlrpc.py b/lib/lp/bugs/externalbugtracker/tests/test_xmlrpc.py
index c473f34..234822c 100644
--- a/lib/lp/bugs/externalbugtracker/tests/test_xmlrpc.py
+++ b/lib/lp/bugs/externalbugtracker/tests/test_xmlrpc.py
@@ -44,11 +44,11 @@ class TestRequestsTransport(TestCase):
             "socket.getaddrinfo",
             side_effect=socket.gaierror(
                 socket.EAI_NONAME, "Name or service not known")))
-        transport = RequestsTransport(u"http://test.invalid/";)
+        transport = RequestsTransport("http://test.invalid/";)
         for proxy in (None, "http://squid.internal:3128/";):
             self.pushConfig("launchpad", http_proxy=proxy)
             e = self.assertRaises(
                 requests.ConnectionError,
-                transport.request, u"test.invalid", u"xmlrpc",
-                u"\N{SNOWMAN}".encode('utf-8'))
+                transport.request, "test.invalid", "xmlrpc",
+                "\N{SNOWMAN}".encode())
             self.assertIn("Name or service not known", str(e))
diff --git a/lib/lp/bugs/externalbugtracker/trac.py b/lib/lp/bugs/externalbugtracker/trac.py
index 9d67e1f..f036a48 100644
--- a/lib/lp/bugs/externalbugtracker/trac.py
+++ b/lib/lp/bugs/externalbugtracker/trac.py
@@ -328,7 +328,7 @@ class TracLPPlugin(Trac):
 
     def __init__(self, baseurl, xmlrpc_transport=None,
                  internal_xmlrpc_transport=None, cookie_jar=None):
-        super(TracLPPlugin, self).__init__(baseurl)
+        super().__init__(baseurl)
 
         if cookie_jar is None:
             cookie_jar = RequestsCookieJar()
@@ -345,7 +345,7 @@ class TracLPPlugin(Trac):
 
     def makeRequest(self, method, url, **kwargs):
         """See `ExternalBugTracker`."""
-        return super(TracLPPlugin, self).makeRequest(
+        return super().makeRequest(
             method, url, cookies=self._cookie_jar, **kwargs)
 
     @ensure_no_transaction

References